Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Микропроцессорные системы. Применение микроконтроллеров семейства AVR для управления внешними устройствами
.pdf
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] );
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
