Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Микропроцессорные системы. Применение микроконтроллеров семейства AVR для управления внешними устройствами

.pdf
Скачиваний:
1
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
51
Конструктор класса CycloBuf() создает класс, который не имеет привязки к массиву байт. Метод void CycloBuf::init (uint8_t* buffer, uint8_t size) осуществ-
ляет привязку экземпляра класса к массиву байт. Параметр buffer – ука­затель на массив байт; параметр size задает размер массива байт и цик-
лического буфера.
Метод void CycloBuf::clear(); очищает циклический буфер. Метод bool CycloBuf::isEmpty(); проверяет, пуст ли циклический
буфер. Если буфер пуст, то возвращает значение true, если не пуст –
возвращает значение false. Метод bool CycloBuf::putByte(uint8_t c); помещает байт c в цик-
лический буфер. Если буфер не полон, то байт помещается в него и ме­тод возвращает значение true. Если байт нельзя поместить в буфер,
то метод возвращает значение false. Метод bool CycloBuf::getByte(uint8_t& c); извлекает значение из
циклического буфера и помещает его в байт c. Если буфер не пуст,
то байт с извлекается из него и метод возвращает значение true. Если бу- фер пуст, то метод возвращает значение false, а значение c не изменяется.
8.3. Универсальный асинхронный приемопередатчик UART
Универсальный асинхронный приемопередатчик используется для
обмена данными между микропроцессорными устройствами. Логиче­ски, протокол обмена UART полностью совпадает с протоколом интер­фейса RS232. В модуле AVR Butterfly имеется преобразователь уровней, позволяющий подключать UART к интерфейсу RS232, например, персо-
нального компьютера. Термин «асинхронный» означает, что данные могут приниматься и независимо друг от друга без отдельных сигналов синхронизации. При программировании интерфейсов передачи данных, подобных
UART, возникает проблема взаимодействия драйвера и остальных про­граммных модулей. Суть проблемы состоит в следующем: поскольку UART – устройство относительно медленное, то передача массива ин­формации побайтно с ожиданием ведет к непроизводительным потерям времени на ожидание передачи байта. Например, при скорости обмена UART 115200, за время передачи одного байта, процессор AVR на ча-
стоте 8 МГц успевает выполнить около 690 операций. Выход из ситуации – использование буферов для приема и переда-
чи информации, совмещенное с генерацией прерываний от UART при
приеме или передаче каждого байта.
52
Наиболее удобно, в данном случае, использовать циклические бу­фера. Поскольку данный вид буферов может использоваться по-разному, то реализация вынесена в отдельный модуль.
8.3.1. Аппаратные средства UART
С точки зрения программиста, UART микроконтроллера AVR
представляет собой несколько регистров управления – UCSRA, UCSRB, UCSRC, PORTE, DDRE, UBRR и регистр данных UDR. Назначения
этих регистров были рассмотрены ранее.
8.3.2. Драйвер UART
Драйвер UART приведен в прил. Г (файлы cUSART.h и cUSART.cpp ).
Все обращения к драйверу USART идут через метод cUSART::instance(). Метод cUSART::instance().start() инициализирует аппаратную часть UART и разрешает обработку прерываний от UART. Метод cUSART::instance().setBaud ( uint16_t baud ) задает ско-
рость передачи данных в бит/сек. Стандартные скорости передачи дан-
ных по RS232 – 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200. Метод uint8_t cUSART::instance().get(char* s, uint8_t size) полу-
чает не более size байт из приемного буфера и помещает их в буфер,
на который указывает s. Метод возвращает реально полученное число байт. Если метод вернул 0, то приемный буфер пуст и данных нет. Метод uint8_t cUSART::instance().putc(char c) помещает один
байт в буфер передачи и запускает передачу по UART, если она еще не запущена. Метод возвращает 1, если символ помещен в буфер передачи,
или 0, если символ не передан (например, в буфере передачи нет места). Метод uint8_t cUSART::instance().puts(const char* s) помещает
строку, размещенную по адресу s в памяти данных, в буфер передачи.
Метод возвращает помещенное в буфер передачи число байт. Метод uint8_t cUSART::instance().putsF(const char* s) помещает
строку, размещенную по адресу s в памяти программ, в буфер переда-
чи. Метод возвращает помещенное в буфер передачи число байт. Метод uint8_t cUSART::instance().put(const char* s, uint8_t size)
помещает массив size байт, размещенный по адресу s в памяти данных, в буфер передачи. Метод возвращает помещенное в буфер передачи
число байт.
53
8.4. Дисплей
Микроконтроллер ATMega169 имеет встроенный контроллер управления ЖКИ-дисплеем. В состав модуля AVR Butterfly входит ЖКИ-дисплей, способный отображать шесть символов (рис. 20).
Рис. 20. Дисплей модуля AVR Butterfly
Каждый из символов дисплея состоит из четырнадцати сегментов.
Это позволяет отображать все символы латинского и кириллическо-
го алфавитов, цифры и спецсимволы. Кроме того, имеются два символа «двоеточие», которые можно отображать между вторым и третьим,
а также между четвертым и пятым символами (нумерация символов – слева направо, рис. 21).
Рис. 21. Структура символа ЖКИ-дисплея
Драйвер дисплея
Драйвер ЖКИ-дисплея приведен в прил. Д (файлы LCD_driver.h и LCD_driver.cpp).
Драйвер имеет следующие функции:
установка уровня контраста изображения на дисплее; вывод строки символов из памяти данных на дисплей; вывод строки символов из памяти программ на дисплей; функция прокрутки (скроллинга) строки на дисплее, если ее раз-
мер более 6 символов;
установка режима вывода разделительных символов «двоеточие».
Все обращения к драйверу USART идут через метод
cLCD::instance().
54
Метод void cLCD::instance().puts(const char *Data) осуществляет
вывод строки символов, размещенной в памяти данных по адресу s,
на дисплей. Максимальный размер строки задается константой
cLCD::Constant::TextBufferSize. Если строка длиннее, чем
cLCD::Constant::TextBufferSize, то лишние символы не выводятся.
Метод void cLCD::instance().putsF(const char *FlashData) осу-
ществляет вывод строки символов, размещенной в памяти программ по адресу s, на дисплей. Максимальный размер строки задается кон­стантой cLCD::Constant::TextBufferSize. Если строка длиннее, чем
cLCD::Constant::TextBufferSize, то лишние символы не выводятся. Метод void cLCD::instance().showColons(const bool ColonsOn)
определяет вывод символов «двоеточие» на дисплей. Если
ColonsOn=true, то символы «двоеточие» выводятся на дисплей. Если
ColonsOn=false, то символы «двоеточие» не выводятся на дисплей.
Метод void cLCD::instance().setContrast(uint8_t level) устанавли-
вает уровень контраста изображения на дисплее. Значение level может
принимать значение от 0 (низкий контраст) до 15 (высокий контраст).
8.5. Джойстик
Как было указано ранее, джойстик служит для ввода информации
пользователем и представляет собой с точки зрения схемотехники пять переключателей типа «сухой контакт», подключенных к 5 линиям ввода микроконтроллера ATMega169. Соответствие положения джойстика и
линий ввода микроконтроллера приведено в табл. 1.
Драйвер джойстика
Драйвер джойстика приведен в прил. Е (файлы JOY_driver.h и JOY_driver.cpp).
Драйвер имеет следующие функции:
считывание линий джойстика и определение того, какая из линий
активна (т. е. в каком положении находится джойстик и его цен­тральная кнопка);
запоминание последнего активного положения джойстика; задержка для устранения дребезга контактов, для организации ко-
торой используется программный таймер. Все обращения к драйверу джойстика идут через метод cJOYSTICK::instance(). Метод cJOYSTICK::instance().start() инициализирует аппарат-
ную часть микроконтроллера AVR (линии портов, прерывания), создает
55
программный таймер для устранения дребезга контактов и разрешает
опрос джойстика. Метод uint8_t cJOYSTICK::instance().getLastKey() позволяет за- просить последнее состояние джойстика. Состояния джойстика определены константами:
cJOYSTICK::JoyKeys::None – джойстик неподвижен, централь-
ная кнопка не нажата;
cJOYSTICK::JoyKeys::Enter – нажата центральная кнопка; cJOYSTICK::JoyKeys::Up – джойстик в положении «вверх»; cJOYSTICK::JoyKeys::Dn – джойстик в положении «вниз»; cJOYSTICK::JoyKeys::Left – джойстик в положении «влево»; cJOYSTICK::JoyKeys::Right – джойстик в положении «вправо».
56
Список литературы
1. Голубцов М.С. Микроконтроллеры AVR : от простого к сложно-
му / М.С. Голубцов. – Москва : СОЛОН-Пресс, 2003. – 288 с. (Се-
рия «Библиотека инженера»).
2. Гребнев В.В. Микроконтроллеры семейства AVR фирмы Atmel /
В.В. Гребнев. – Москва : ИП. РадиоСофт, 2002. – 176 с.
3. Евстифеев А.В. Микроконтроллеры AVR семейства CLASSIC
фирмы ATMEL / А.В. Евстифеев. – Москва : Издательский дом
«Додэка-XXI», 2002. – 288 с.
4. Гриффитс А. GCC. Настольная книга пользователей, программи-
стов и системных администраторов / А. Гриффитс. – Москва :
ООО ТИД «ДС», 2004. – 624 с.
5. Знакомство с компилятором GCC [Электронный ресурс]. – Режим
доступа : http://www.linuxcenter.ru/lib/books/linuxdev/linuxdev1.
phtml, свободный. – Загл. с экрана.
6. Компилятор G++ [Электронный ресурс]. – Режим доступа :
http://www.linuxcenter.ru/lib/books/linuxdev/linuxdev4.phtml, сво-
бодный. – Загл. с экрана.
7. Managing Projects with GNU Make [Электронный ресурс] // O'Reil-
ly Media, Inc., 2004. – Режим доступа : http://shop.oreilly.com/
product/9780596006105.do, свободный. – Загл. с экрана.
8. Корнеев В.В. Современные микропроцессоры / В.В. Корнеев,
А.В. Кисилев. – Москва : Нолидж, 2000. – 316 с.
9. Гончаровский О.В. Встроенные микропроцессорные системы :
учебное пособие / О.В. Гончаровский, Н.Н. Матушкин, А.А. Южа-
ков. – Пермь : Изд-во Перм. нац. исслед. политехн. ун-та, 2012. –
198 с.
57
Приложение A. Исходные тексты программного модуля
калибровки (os_calibrate.cpp, os_calibrate.h)
// os_calibrate.h #ifndef OS_CALIBRATE_H #define OS_CALIBRATE_H
#define F_CPU 8000000 void OSCCAL_calibration(void); #endif /* OS_CALIBRATE_H */ // os_calibrate.cpp
#include <avr/interrupt.h> #include <avr/io.h> #include <util/delay.h> #include "os_calibrate.h"
void OSCCAL_calibration(void){
unsigned char calibrate = false; int temp; unsigned char tempL;
cli(); CLKPR = (1<<CLKPCE); // set prescaler = 8, Inter RC 8Mhz / 8 = 1Mhz CLKPR = (1<<CLKPS1) | (1<<CLKPS0); TIMSK2 = 0; ASSR = (1<<AS2);
OCR2A = 200; TIMSK0 = 0; TCCR1B = (1<<CS10); TCCR2A = (1<<CS20); while((ASSR & 0x01) | (ASSR & 0x04));
_delay_ms(1000); while(!calibrate){
cli(); TIFR1 = 0xFF;
TIFR2 = 0xFF; TCNT1H = 0; // clear timer1 counter TCNT1L = 0; TCNT2 = 0; // clear timer2 counter
58
while ( !(TIFR2 & (1<<OCF2A)) ); TCCR1B = 0; // stop timer1
if ( (TIFR1 & (1<<TOV1)) ){ temp = 0xFFFF; } else{ tempL = TCNT1L; temp = TCNT1H; temp = (temp << 8); temp += tempL; }
if (temp > 6250){ OSCCAL--; } else if (temp < 6120){ OSCCAL++; } else calibrate = true; TCCR1B = (1<<CS10); }
EIMSK=0; EIFR=0xFF;
// 1mhz #if F_CPU == 1000000UL CLKPR = (1<<CLKPCE); CLKPR = (1<<CLKPS1) | (1<<CLKPS0);
// 2mhz #elif F_CPU == 2000000 CLKPR = (1<<CLKPCE); CLKPR = (1<<CLKPS1) | (0<<CLKPS0);
// 8mhz #elif F_CPU == 8000000 CLKPR = (1<<CLKPCE); CLKPR = (0<<CLKPS1) | (0<<CLKPS0);
#endif }
59
Приложение Б. Исходные тексты программного драйвера пула
программных таймеров (cSoftTimers.cpp, cSoftTimers.h)
// Файл cSoftTimers.h #ifndef CSOFTTIMERS_H #define CSOFTTIMERS_H
#include "stdint.h"
/** * @brief Программные таймеры */ class cSoftTimers { public:
enum Constants{ /// Максимальное число таймеров maxTimers=0x08 };
/** * @brief Идентификатор таймера */ typedef int8_t idT;
/** * @brief Процедура, Вызывается по таймеру */ typedef void(*timerProc)();
/** * @brief Описатель таймера */ typedef struct { // Период таймера (1мс – 60000 мс) uint16_t period; // Счетчик uint16_t counter; // Процедура обработки таймера timerProc proc; } dscTimer;
/**
60
* @brief Конструктор */ cSoftTimers();
/** * @brief Добавить таймер * * @param period – Период таймера (1мс – 60000 мс) * @param handler – Процедура обработки таймера * @return cSoftTimers::idT – Идентификатор таймера или -1, если некуда добавить таймер */ idT addTimer( uint16_t period, timerProc handler );
/** * @brief Удалить таймер * * @param id – Идентификатор таймера * @return void */ void delTimer(idT id);
/** * @brief Перезапуск таймера * * @param id – Идентификатор таймера * @return void */ void rstTimer(idT id);
/** * @brief Запуск таймеров * * @return void */ void start();
/** * @brief Остановка таймеров * * @return void */ void stop();
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]