Обработка аналоговых сигналов на основе МК C8051F064

Автор: Пользователь скрыл имя, 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

Работа содержит 1 файл

Обобщенная пояснительная записка.doc

— 5.12 Мб (Скачать)

mess.adc_mode=2;mess.ADC0=0;mess.ADC1=1;

break;

case ID_SAMP:

mess.samples=SampChk();

i=0;

while(pow((double)2,++i)<mess.samples);

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);

buf[i++]=' ';

buf[i++]='V';

TextOut(hDCbuf, 23, 5, buf,i );

 

i=parcechar(480000./(mess.freq*mess.time_zoom), buf);

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(MyThreadPaint,   0,   (void *)hDCbuf);

WaitForSingleObject((HANDLE)Thread0, 100);

}

 

 

// 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-разрядный  автоперезагружаемый таймер-счетчик), в режим 1

// (стандартный  асинхронный полудуплексный обмен  данными с использованием 10 бит  для передачи 1 байта данных)

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 - скоротсть  передачи данных последовательного  порта UART0 удваивается

//биты 3-2 (биты выбора  генератора скорости передатчика  данных): 00 - таймер T1

//биты 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 - режим  кварцевого генератора с делением  тактовой частоты на 2

//бит 3: зарезервирован

//биты 2-0 (управления  частотой внешнего генератора): 111 - частота генератора задается от 10 МГц до 30 МГц

// частота =(22118400/2=11059200)Hz

 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(если нужно) с управлением  преобразованием Timer3

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 и

//включение внутреннего  буферного усилителя, внутреннее  опорное напряжение подается  на вход VREF0

 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 в режим автоперезагрузки  и генерирования частоты дискретизации  ADC

// указанные  <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