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

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

.pdf
Скачиваний:
1
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
71
}
void cUSART::hwInit(){
PORTE |= (1<<Constants::bitTx) | (1<<Constants::bitRx); DDRE = (DDRE & ~(1<<Constants::bitRx)) | (1<<Constants::bitTx); PCMSK0 &= ~((1<<Constants::bitTx) | (1<<Constants::bitRx)) ; // UCSRA=(1<<U2X); // Передатчик и приемник включены UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<TXCIE); // Асинхронный режим, 8 бит UCSRC =
(0<<UMSEL)|(0<<UPM0)|(0<<USBS)|(3<<UCSZ0)|(0<<UCPOL); }
void cUSART::start(){ hwInit(); }
static cUSART usart; cUSART& cUSART::instance(){ return( usart ); }
uint8_t cUSART::putc ( char c ) {
uint8_t r=(m_TxBuffer.putByte(c))?1:0;
tx_complete();
return(r);
}
uint8_t cUSART::puts ( const char* s ){
uint8_t counter=0;
while( *s ){ if( !m_TxBuffer.putByte(*(s++)) ){ break; } counter++; }
tx_complete();
72
return(counter); }
uint8_t cUSART::put ( const char* s, uint8_t size ) {
uint8_t counter=0; while( counter<size ){ if( !m_TxBuffer.putByte(*(s++)) ){ break; } counter++; }
tx_complete();
return(counter);
}
uint8_t cUSART::putsF ( const char* s ) {
uint8_t counter=0; uint8_t c;
while( c=pgm_read_byte(s++) ){ if( !m_TxBuffer.putByte(c)){ break; } counter++; }
tx_complete();
return(counter);
}
uint8_t cUSART::get( char* s, uint8_t size ) {
uint8_t counter=0;
while( counter<size ){ uint8_t c; if(!m_RxBuffer.getByte(c)){ break; } *(s++) = c; counter++;
73
} return(counter);
}
void cUSART::rx_complete(){
uint8_t c=UDR; m_RxBuffer.putByte(c);
}
void cUSART::tx_complete(){
// Для запуска передачи if(!(UCSRA & (1<<UDRE))){ return; }
uint8_t c; if (m_TxBuffer.getByte(c)){ UDR=c; }
}
void static_rx_complete(){ cUSART::instance().rx_complete(); }
ISR ( USART0_RX_vect, ISR_BLOCK ) { static_rx_complete(); }
void static_tx_complete(){ cUSART::instance().tx_complete(); }
ISR ( USART0_TX_vect, ISR_BLOCK ) { static_tx_complete(); }
74
Приложение Д. Исходные тексты программной реализации
драйвера ЖКИ-дисплея (LCD_driver.h и LCD_driver.cpp)
// LCD_driver.h #ifndef LCDDRIVER_H #define LCDDRIVER_H
#include <stdint.h>
/** * @brief LCD-Display class */ class cLCD{ public:
enum Constant{ // Прокрутка Scroll =1, ScrollDone =2,
// Неправильный символ, он же пробел SpaceInvalidChar = 0xFF,
// Размер буфера текста TextBufferSize = 20,
// Размер дисплея, в символах DisplaySize = 6,
// Прокрутка ScrollCountDef = DisplaySize, ScrollDelayDef = TextBufferSize };
/** * @brief Конструктор. Вызывается один раз и не более (синглтон) */ cLCD();
/** * @brief Печать строки * * @param Data – строка в ОЗУ
75
* @return void */ void puts(const char *Data);
/** * @brief Печать строки * * @param FlashData – строка в ПЗУ * @return void */ void putsF(const char *FlashData);
/** * @brief Рисовать двоеточия или нет * * @param ColonsOn – true – рисовать, false – нет * @return void */ void showColons(const bool ColonsOn);
/** * @brief Установить уровень контрастности * * @param level – уровень контрастности (0 – 15) * @return void */ void setContrast(uint8_t level);
/** * @brief Обращение к дисплею только через этот метод * * @return cLCD& */ static cLCD& instance();
private: /** * @brief Внешняя функция, которая прерывания дергает * * @return void */ friend void static_display_irq ();
/**
76
* @brief Буфер для хранения текста */ char m_TextBuffer[Constant::TextBufferSize + DisplaySize + 1];
/** * @brief Обновить дисплей */ bool m_UpdateDisplay;
/** * @brief Рисовать двоеточия */ bool m_ShowColons;
/** * @brief Начало строки */ uint8_t m_StrStart;
/** * @brief Конец строки */ uint8_t m_StrEnd;
/** * @brief Счетчик прокрутки */ uint8_t m_ScrollCount;
/** * @brief Флаги скроллинга Scroll и ScrollDone */ uint8_t m_Flags;
/** * @brief Функция обработки прерывания контроллера дисплея. * * @return void */ void display_irq();
/** * @brief Отправляет символ на дисплей *
77
* @param Byte – код символа * @param Digit – номер символа на дисплее * @return void */ void writeChar(const uint8_t Byte, const uint8_t Digit);
}; #endif
// LCD_driver.cpp #include <avr/pgmspace.h> #include <string.h> #include <avr/interrupt.h>
#include "LCD_driver.h"
#define LCD_LCDREGS_START ((uint8_t*)&LCDDR0)
static const uint16_t LCD_SegTable[] PROGMEM = {
0xEAA8, // '*' 0x2A80, // '+' 0x4000, // ',' 0x0A00, // '-' 0x0A51, // '.' Degree sign 0x4008, // '/' 0x5559, // '0' 0x0118, // '1' 0x1e11, // '2 0x1b11, // '3 0x0b50, // '4 0x1b41, // '5 0x1f41, // '6 0x0111, // '7 0x1f51, // '8 0x1b51, // '9' 0x0000, // ':' (Not defined) 0x0000, // ';' (Not defined) 0x8008, // '<' 0x1A00, // '=' 0x4020, // '>' 0x0000, // '?' (Not defined) 0x0000, // '@' (Not defined) 0x0f51, // 'A' (+ 'a') 0x3991, // 'B' (+ 'b') 0x1441, // 'C' (+ 'c')
78
0x3191, // 'D' (+ 'd') 0x1e41, // 'E' (+ 'e') 0x0e41, // 'F' (+ 'f') 0x1d41, // 'G' (+ 'g') 0x0f50, // 'H' (+ 'h') 0x2080, // 'I' (+ 'i') 0x1510, // 'J' (+ 'j') 0x8648, // 'K' (+ 'k') 0x1440, // 'L' (+ 'l') 0x0578, // 'M' (+ 'm') 0x8570, // 'N' (+ 'n') 0x1551, // 'O' (+ 'o') 0x0e51, // 'P' (+ 'p') 0x9551, // 'Q' (+ 'q') 0x8e51, // 'R' (+ 'r') 0x9021, // 'S' (+ 's') 0x2081, // 'T' (+ 't') 0x1550, // 'U' (+ 'u') 0x4448, // 'V' (+ 'v') 0xc550, // 'W' (+ 'w') 0xc028, // 'X' (+ 'x') 0x2028, // 'Y' (+ 'y') 0x5009, // 'Z' (+ 'z') 0x1441, // '[' 0x8020, // '\' 0x1111, // ']' 0x0000, // '^' (Not defined) 0x1000 // '_'
};
cLCD::cLCD() {
memset(m_TextBuffer, 0, sizeof(m_TextBuffer) ); m_UpdateDisplay=false; m_ShowColons=false; m_StrStart=0; m_StrEnd=0; m_ScrollCount=0;
setContrast ( 0x0F ); LCDCRB = ( 1<<LCDCS ) | ( 3<<LCDMUX0 ) | ( 7<<LCDPM0 ); LCDFRR = ( 0<<LCDPS0 ) | ( 3<<LCDCD0 ); LCDCRA = ( 1<<LCDEN ) | ( 1<<LCDAB ) | ( 1<<LCDIE ); }
79
void cLCD::putsF ( const char *FlashData ) { strcpy_P ( ( char* ) &m_TextBuffer[0], FlashData ); puts ( ( char* ) &m_TextBuffer[0] );
}
void cLCD::puts ( const char *Data ) {
uint8_t LoadB = 0; uint8_t CurrByte;
do { CurrByte = * ( Data++ ); switch ( CurrByte ) { case 'a'...'z': CurrByte &= ~ ( 1 << 5 ); case '*'...'_': m_TextBuffer[LoadB++] = ( CurrByte – '*' ); break; case 0x00: break; default: m_TextBuffer[LoadB++] = Constant::SpaceInvalidChar; } } while ( CurrByte && ( LoadB < Constant::TextBufferSize ) );
m_Flags = ( ( LoadB > Constant::DisplaySize ) ? Constant::Scroll : 0x00 );
for ( uint8_t Nulls = 0; Nulls < 7; Nulls++ ) m_TextBuffer[LoadB++] = Constant::SpaceInvalidChar;
m_TextBuffer[LoadB] = 0x00; m_StrStart = 0; m_StrEnd = LoadB; m_ScrollCount = Constant::ScrollCountDef + Constant::ScrollDelayDef; m_UpdateDisplay = true;
}
void static_display_irq () { cLCD::instance().display_irq(); }
void cLCD::display_irq() {
80
if ( m_Flags & Constant::Scroll ) { if ( ! ( m_ScrollCount-- ) ) { m_UpdateDisplay = true; m_ScrollCount = Constant::ScrollCountDef; } }
if ( m_UpdateDisplay ) { for ( uint8_t Character = 0; Character < Constant::DisplaySize; Character++ ) { uint8_t Byte = ( m_StrStart + Character );
if ( Byte >= m_StrEnd ) Byte -= m_StrEnd;
writeChar ( m_TextBuffer[Byte], Character ); }
if ( ( m_StrStart + Constant::DisplaySize ) == m_StrEnd ) m_Flags |= Constant::ScrollDone;
if ( m_StrStart++ == m_StrEnd ) m_StrStart = 1;
if ( m_ShowColons ) ((uint8_t*)&LCDDR0)[8]=0x01; else ((uint8_t*)&LCDDR0)[8]=0x00;
m_UpdateDisplay = false; }
}
ISR ( LCD_vect, ISR_NOBLOCK ) { static_display_irq(); }
void cLCD::writeChar ( const uint8_t Byte, const uint8_t Digit ) { uint8_t* BuffPtr = ( uint8_t* ) ( LCD_LCDREGS_START + ( Digit >> 1 ) );
uint16_t SegData = 0x0000;
if ( Byte != Constant::SpaceInvalidChar ) SegData = pgm_read_word ( &LCD_SegTable[Byte] );
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]