Автор: Пользователь скрыл имя, 13 Декабря 2012 в 09:08, курсовая работа
Цель курсовой работы – получение навыков программирования аппаратных комплексов, включающих взаимодействующие между собой различные 8- или 32-разрядные микроконтроллерные системы (МК-системы) и персональные компьютеры (РС), на языках Ассемблеров, С – для микроконтроллеров (МК) и языке С++ для РС с платформой Windows.
1. Постановка задачи 6
1.1. Стандартное задание 6
1.2. Индивидуальное задание 6
2. Техническое задание 7
3. Описание аппаратных и программных средств лабораторного комплекса 8
3.1. Структура аппаратных средств 8
3.1.1. Структурная схема лабораторного комплекса 8
3.1.2. Плата МК – системы 9
3.1.2.1. Конфигурируемые узлы МК C8051F064 11
3.1.2.2. Внешняя память XRAM 16
3.1.2.3. Входные усилители 17
3.1.2.4. Микросхема моста UART-USB 18
3.1.2.5. Сопряжение платы с PC 20
3.1.2.6. Питание платы 21
3.1.3. Требования к PC 21
3.1.4. ОСЦИГЕН 21
3.2. Перечень программных средств лабораторного комплекса 22
3.2.1. Средства программирования и отладки МК-системы 22
3.2.1.1. Интегрированная среда разработки фирмы SiLabs IDE 2.0 22
3.2.1.2. Ассемблер, компилятор и линкер интегрированной среды разработки Keil 23
3.2.2. Средства разработки Windows-приложений 24
3.2.2.1. Среда разработки 24
3.2.2.2. Библиотека WIN32 API функций 24
3.2.3. Приложения для ОСЦИГЕНа. 25
3.2.3.1. Драйвер конфигурируемого выносного блока 25
3.2.3.2. Windows-приложение OGView 25
3.2.4. Драйвер виртуального COM-порта фирмы SiLabs 26
4. Разработка программного комплекса для решения целевой задачи 26
4.1. Функциональная схема реализации функций запоминающего осциллографа 26
4.2. Состав и механизм взаимодействия приложений программного комплекса 27
4.2.1. Схема программного комплекса 27
4.2.2. Протокол обмена между PC-приложением и МК-приложением 27
4.2.3. Таблица допустимых команд 27
4.2.4. Размещение в памяти значений выборок сигнала со стороны МК и ПК 28
4.3. Разработка приложения для МК-системы 29
4.3.1. Обобщенная схема алгоритма 29
4.3.2. Обоснование выбора языка программирования и среды разработки 30
4.3.3. Описание файлов проекта приложения 30
4.3.3.1. Модули приложения 30
4.3.3.2. Модули, подключаемые на этапе линкования 30
4.3.4. Структура и организация программы 30
4.3.5. Схемы алгоритмов и описание функций приложения 30
4.3.5.1. Перечень функций приложения 30
4.3.5.2. Организация бесконечного цикла встроенного приложения 31
4.3.5.3. Отключение сторожевого таймера 31
4.3.5.4. Переключение с внутреннего генератора на внешний 32
4.3.5.5. Конфигурирование портов ввода/вывода 33
4.3.5.6. Конфигурирование аналого-цифровых преобразователей ADC 32
4.3.5.7. Конфигурирование интерфейса DMA 34
4.3.5.8. Инициализация последовательного интерфейса UART 35
4.3.5.9. Выбор и инициализация таймера для установки скорости обмена данными по последовательному каналу 36
4.3.5.10. Инициализация таймера для установки времени дискретизации входного сигнала 36
4.3.5.11. Выбор режимов работы внешней памяти XRAM и ее интерфейса 36
4.3.5.12. Инициализация прерываний 37
4.3.5.13. Формирование цифровых отсчетов и их сохранение во внешней памяти XRAM 37
4.3.5.14. Передача данных на PC 37
4.3.5.15. Прием данных с PC 37
4.3.5.16. Другие используемые функции 38
4.3.5.17. Конфигурирование узлов МК с учетом данных, пришедших с PC 38
4.4. Разработка Windows-приложения 39
4.4.1. Особенности использования среды разработки 39
4.4.2. Описание файлов проекта 39
4.4.3. Обобщенная схема алгоритма многопоточного приложения 40
4.4.4. Внешний вид и описание графического интерфейса, принципы построения программы 40
4.4.5. Описание структуры и организация программы 41
4.4.5.1. Назначение подключаемых файлов 41
4.4.5.2. Описание прототипов функций 41
4.4.5.3. Функция WinMain() 42
4.4.5.4. Функция главного окна 42
4.4.5.5. Организация дополнительных потоков, их назначение 43
4.4.5.6. Рабочие функции дополнительных потоков 43
4.4.5.7. Синхронизация потоков 43
4.4.5.8. Особенности обработки сообщений Windows в программе 43
4.4.5.9. Функция рисования графика восстановленного сигнала 45
4.4.5.10. Разметка осей графика 45
4.4.5.11. Использование контекстуальной памяти для рисования графика 45
4.4.6. Работа с COM-портом, описание WinAPI-функций и структур данных 46
4.4.6.1. Инициализация COM-порта, обоснование выбора режима (синхронный, асинхронный), объема буфера приема/передачи данных 46
4.4.6.2. Организация настроек COM¬-порта в графическом интерфейсе 48
4.4.6.3. Использование функций WaitCommEvent(), WaitForSingleObject(), WaitForMultiplyObject() 49
4.4.7. Работа оператора с приложением 49
4.4.7.1. Последовательность запуска приложения на МК и ПК в лаборатории 49
4.4.7.2. Примеры последовательности 49
4.4.7.3. Адаптация к сепктру входного сигнала 49
4.4.8. Описание протокола RS-232 49
5. Список используемых источников информации 87
6. Приложения 50
6.1. Исходные тексты модулей программы для МК 50
6.2. Фрагменты листингов файлов МК-приложения, полученные в результате трансляций: MAP-file и др 56
6.3. Исходные тексты файлов Windows-приложения 58
6.4. Алгоритмы 72
6.4.1. Обобщенный алгоритм программы для МК 72
6.4.2. Дополнительные алгоритмы программы для МК 73
6.4.2.1. Алгоритм процедуры отключения WDT 73
6.4.2.2. Алгоритм функции SYSCLK_Init 74
6.4.2.3. Алгоритм функции Port_Init 75
6.4.2.4. Алгоритм функции ADCInit 76
6.4.2.5. Алгоритм функции DMAInit 77
6.4.2.6. Алгоритм работы функции UART0_Init 79
6.4.2.7. Алгоритм функции Timer3_Init 80
6.4.2.8. Алгоритм функции main 81
6.4.2.9. Алгоритм функции Config 82
6.4.2.10. Алгоритм функции SendData 83
6.4.2.11. Алгоритм функции ReceiveData 84
6.4.3. Обобщенный алгоритм программы Windows-приложения 85
6.4.3.1. Алгоритм работы функции рисования графика 85
6.4.3.2. Алгоритм обработки сообщений 86
mess.adc_mode=2;mess.ADC0=0;
break;
case ID_SAMP:
mess.samples=SampChk();
i=0;
while(pow((double)2,++i)<mess.
if(i>16||mess.samples<=0) MessageBox(hWnd,TEXT("Number of samples should be between 1 and 65536"),0,MB_OK);
else mess.S=i-1;
break;
case ID_UINC:
if(mess.u_zoom<10)
mess.u_zoom*=1.1;
SendMessage(WB_Wnd, WM_PAINT, NULL, NULL);
break;
case ID_UDEC:
if(mess.u_zoom>0.4)
mess.u_zoom/=1.1;
SendMessage(WB_Wnd, WM_PAINT, NULL, NULL);
break;
case ID_TINC:
if(mess.time_zoom<20)
mess.time_zoom*=1.1;
SendMessage(WB_Wnd, WM_PAINT, NULL, NULL);
break;
case ID_TDEC:
if(mess.time_zoom>0.1)
mess.time_zoom/=1.1;
SendMessage(WB_Wnd, WM_PAINT, NULL, NULL);
break;
case ID_DEMO:
demo();//simulating sine wave& printing it
SendMessage(WB_Wnd, WM_PAINT, NULL, NULL);
break;
case ID_START:
_beginthread(MyThreadSend, 0, 0);//starting sending and recieving data in extra thread
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK WorkBenchProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)//messages processing function of graph(only WM_PAINT is processing)
{ std::string Str;
WCHAR buf[10];
switch(msg)
{
case WM_PAINT:
{
// Getting DC and creating buffer DC
HDC hDC = GetDC (hWnd);
HDC hDCbuf=CreateCompatibleDC(hDC)
// creating bitmap for buffer painting
RECT rc;
GetClientRect(hWnd, &rc);
HBITMAP hBmpBuffer = CreateCompatibleBitmap(hDC, rc.right, rc.bottom);
SelectObject (hDCbuf, hBmpBuffer);
// creating Pen(will do this several times
HPEN hPen = CreatePen (PS_SOLID, 1, RGB(255, 255, 255));
// aquiring Pen into DC,remembering old Pen
HPEN hOldPen = (HPEN)SelectObject (hDCbuf, hPen);
//erasing area
Rectangle(hDCbuf,rc.left, rc.top, rc.right, rc.bottom);
DeleteObject (hPen);
//beginnig of painting
//painting grid
hPen = CreatePen (PS_DOT, 1, RGB(0, 0, 0));
SelectObject (hDCbuf, hPen);
for(int i=0;i<10;i++)
Line(hDCbuf,0, i*20,600,i*20);
for(int i=0;i<30;i++)
Line(hDCbuf,i*20, 0,i*20,600);
DeleteObject(hPen);
//writing names of the axes
int i=parcechar(3./mess.u_zoom,
buf[i++]=' ';
buf[i++]='V';
TextOut(hDCbuf, 23, 5, buf,i );
i=parcechar(480000./(mess.
buf[i++]=' ';
buf[i++]='m';
buf[i++]='s';
TextOut(hDCbuf, 430, 160, buf,i );
//painting axes
hPen = CreatePen (PS_SOLID, 2, RGB(0, 0, 0));
SelectObject (hDCbuf, hPen);
Line(hDCbuf, rc.left+19, rc.top, rc.left+19, rc.bottom);
Line(hDCbuf, rc.left+19, rc.bottom-3, rc.right, rc.bottom-3);
Line(hDCbuf, 13, 20, 33, 20);
Line(hDCbuf, 480, 170, 480, 180);
DeleteObject (hPen);
//painting graph in extra thread
if(mess.ready){
uintptr_t Thread0=_beginthread(
WaitForSingleObject((HANDLE)
}
// adding old Pen to DC
SelectObject(hDCbuf, hOldPen);
InvalidateRect(hWnd, NULL, true);
BitBlt(hDC, rc.left, rc.top, rc.right, rc.bottom, hDCbuf, 0, 0, SRCCOPY);
// releasing all local variables
DeleteObject (hPen);
ReleaseDC (hWnd, hDC);
ValidateRect(hWnd, 0);
DeleteDC(hDCbuf);
DeleteObject(hBmpBuffer);
}
return 0;
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
6.2. Исходные тексты модулей программы для МК
#include <c8051f060.h>
#include <stdio.h>
//----------------------------
// Определение 16-битных SFR для 'F06x
//----------------------------
sfr16 RCAP3 = 0xCA; // Timer3, значение адреса после перезагрзки
sfr16 TMR3 = 0xCC; // Timer3, адрес счетчика
sfr16 ADC0 = 0xBE; // ADC0, адрес результата
sfr16 DMA0CT = 0xF9; // DMA, счетчик операций
sfr16 DMA0DA = 0xD9; // DMA0, адрес начала
//----------------------------
// Глобальные константы
//----------------------------
#define SYSCLK 11059200 // SYSCLK частота в Гц
#define BAUDRATE 115200 // Скорость передачи UART0
sbit P1_6=P1^6;
// инструкции DMA
#define DMA0_END_OF_OP 0x00 // конец операций
#define DMA0_GET_ADC0 0x10 // Получение данных ADC0
#define DMA0_GET_DIFF 0x40 // Получение Retrieve разностных (дифференциальных) данных (ADC0-ADC1)
#define XRAM_START_ADD 0x0000 // DMA0 XRAM стартовый адрес ADC data log
//-------------------------
// Глобальные переменные
//-------------------------
unsigned char xdata * data read_ptr; // указатель XRAM
unsigned int NUM_SAMPLES; // количество выборок ADC (каждая выборка 2 байта)
unsigned char ADC_Mode; // режим ADC
unsigned int SAMP_RATE ; // частота дискретизации ADC в Гц (писать в RCAP3)
//----------------------------
// Конфигурирование портов ввода/вывода
//----------------------------
void Port_Init (void)
{
char old_SFRPAGE = SFRPAGE;
SFRPAGE = CONFIG_PAGE; // Переключение на страницу конфигурации
XBR0=0x04; // запись значения b00000100, включение бита подключения входов/выходов UART0
// TX0 соединен с P0.0; RX0 - с P0.1
XBR1=0x00; // SYSCLK, T2EX, T2, INT1, IN0, T1E, T0E, CP1 не соеденены с портами ввода/вывода
XBR2=0x40; // запись значения b01000000, установка в 1 бита включения матрицы (распределяет выводы)
// слаботоковые подтяжки включены (бит7 = 0)
P0MDOUT=0xFF; // запись значения b11111111, все выводы (P0.0-7) настроены как цифровой двухконтактный выход (Push-Pull)
// по умолчанию они настроены для работы в режиме Open_Drain
P1MDOUT |= 0x40; // запись значения b10111111, все выводы, кроме P1.6 настроены как цифровой двухконтактный выход (Push-Pull)
// порт P1.6 настроен для работы в режиме Open_Drain
SFRPAGE = old_SFRPAGE; // восстановление SFRPAGE
}
//----------------------------
// Инициализация UART0
//----------------------------
// Настройка
UART0, использующую Timer1 (режим 2, 8-разрядный
автоперезагружаемый таймер-
// (стандартный
асинхронный полудуплексный
void UART0_Init (void)
{
char old_SFRPAGE = SFRPAGE;
SFRPAGE = UART0_PAGE; // Переключение на страницу UART0
SCON0 = 0x50; //запись значения b01010000 в регистр управления SCON0
//установка в 01 битов выбора режима UART0 (7 и 8 биты) - режим 1, 8-разрядный UART0, изменяемая скорость передачи
//установка в 1 бита разрешения приема (бит 4) - прием данных UART0 разрешен
// SCON: mode 1, 8-bit UART, enable RX
SSTA0 |= 0x10; //логическое или со значением b00010000 в регистр состояния и выбора счетчика тактирования SSTA0
//бит 4: 1 - скоротсть
передачи данных
//биты 3-2 (биты выбора
генератора скорости
//биты 1-0 (биты выбора генератора скорости приемника данных): 00 - таймер T1
// инициализация T1
SFRPAGE = TIMER01_PAGE; // Переключение на страницу Timer 0/1
TMOD = 0x20; // запись значения b00100000, режим 2 (8-разрядный автоперезагружаемый таймер-счетчик)
TH1 = -(SYSCLK / BAUDRATE)/16; // задание значения переполнения таймера для скорости передачи данных
TL1 = -(SYSCLK / BAUDRATE)/16; // задание начального значения таймера для скорости передачи данных
TR1 = 1; // запуск T1
CKCON |= 0x10; //логическое или со значением b00010000, таймер Т1 тактируется сичтемных тактовым сигналом SYSCLK
SFRPAGE = old_SFRPAGE; // восстановление SFRPAGE
}
//----------------------------
// инициализация SYSCLK
//----------------------------
// Запуск внешнего осцилятора
void SYSCLK_Init (void)
{
char old_SFRPAGE = SFRPAGE;
int i;
SFRPAGE = CONFIG_PAGE; // Переключение на страницу конфигурации
OSCXCN = 0x77; // запись значения b01110111
//бит 7: 0 -кварцевый генератор не используется или еще не стабилен
//биты 6-4: 111 - режим
кварцевого генератора с
//бит 3: зарезервирован
//биты 2-0 (управления частотой внешнего генератора): 111 - частота генератора задается от 10 МГц до 30 МГц
// частота =(22118400/2=11059200)
for (i=0; i <5000; i++) ; // пауза длительностью как минимум 1 мс, чтобы исключить
//преждевременное
переключение системы от
while (!(OSCXCN & 0x80)) ; //(OSCXCN & b10000000) опрашиваем флаг стабилизации кв.генератора до тех пор,
// пока он не установится в 1 (кв.генератор стабилен)
RSTSRC |= 0x04; //логическое или со значением b00000100
// позволяет восстановить отсутствующие часы детектора
CLKSEL |= 0x01; // запись значения b00000001, переключение на работу от внешнего генератора
OSCICN = 0x00; // отключение внутреннего генератора
SFRPAGE = old_SFRPAGE; // восстановление SFRPAGE
}
//----------------------------
// инициализация ADC
//----------------------------
// Настройка
ADC0 и ADC1(если нужно) с
void ADC_Init (void)
{
char old_SFRPAGE = SFRPAGE;
int i;
SFRPAGE = ADC0_PAGE; // Переключение на страницу ADC0
ADC0CN = 0xC4; // запись значения b11000100, бит 7: 1 -включение ADC0,
//бит 6: 1 - режим слежения определяется битами 3-2
//бит 3-2: 01 - слежение(выборка) начинается при переполнении таймера 3
REF0CN = 0x03; // запись значения b00000011, включение генератора напряжения смещения ADC0 и
//включение внутреннего
буферного усилителя,
for(i=0;i<10000;i++); // задержка для стабилизации генератора опорного напряжения
ADC0CF = 0x00; // установка в качестве периода сигнала дискретизации ADC0 Tconv = 21*Tsysclk
//Режим ADC
if (ADC_Mode == 's')
AMX0SL = 0x00; // режим ADC0
else if (ADC_Mode=='d')
{
AMX0SL = 0x40; // запись значения b10000000, выбор дифференциального режима работы
SFRPAGE = ADC1_PAGE; // Переключение на страницу ADC1
ADC1CN = 0xC4; //запись значения b11000100, бит 7: 1 -включение ADC1,
//бит 6: 1 - режим слежения определяется битами 3-2
//бит 3-2: 01 - слежение(выборка) начинается при переполнении таймера 3
REF1CN = 0x03; // запись значения b00000011, включение генератора напряжения смещения ADC1 и
//включение внутреннего буферного усилителя
for(i=0;i<10000;i++); // задержка для стабилизации генератора опорного напряжения
ADC1CF = 0x00; // установка в качестве периода сигнала дискретизации ADC1 Tconv = 21*Tsysclk
}
SFRPAGE = old_SFRPAGE; // восстановление SFRPAGE
}
//----------------------------
// инициализация DMA0
//----------------------------
// Настройка DMA0 в режим 1 и выбор ADC для извлечения данных
void DMA0_Init()
{
char old_SFRPAGE = SFRPAGE;
SFRPAGE=DMA0_PAGE; // Переключение на страницу DMA0
DMA0CN = 0x00; // отключаем DMA0
DMA0DA = XRAM_START_ADD; //запись 16-разрядной переменной, установка начального адреса данных
DMA0CT = NUM_SAMPLES; // запись значения переменной количества выборок в регистр счетчика повторений
DMA0IPT = 0x00; // запись начального адреса команд в регистр адреса команд
// Помещение инструкций в стек с последующим выполнением
if (ADC_Mode == 's')
DMA0IDT = DMA0_GET_ADC0; // получение данных от ADC0
else DMA0IDT = DMA0_GET_DIFF; // получение данных в дифф. режиме от [ADC0 - ADC1]
DMA0IDT = DMA0_END_OF_OP; // конец операций
DMA0BND = 0x00; // запись адреса, с которого начинается выполнение команд, в регистр границы команд
DMA0CN = 0x20; // запись значения b00100000, включение DMA в первом режиме
SFRPAGE=old_SFRPAGE; // восстановление SFRPAGE
}
//----------------------------
// инициализация Timer3
//----------------------------
// Настройка
Timer3 в режим автоперезагрузки
и генерирования частоты
// указанные <counts>, используя SYSCLK/12 в качестве базового времени.
void Timer3_Init (unsigned int counts)
{
char old_SFRPAGE = SFRPAGE;
SFRPAGE = TMR3_PAGE; // Переключение на страницу Timer 3
TMR3CN = 0x00; // отключение таймера 3
TMR3CF |= 0xC0; // учтановка частоты счетчика SYSCLK / 12
RCAP3 = (0xFFFF-counts); // инициализация значений перезагрузки, counts - значение частоты дискретизации
TMR3 = 0xFFFF; // переполнение таймера
Информация о работе Обработка аналоговых сигналов на основе МК C8051F064