3.2 Проектирование процедур обработки прерываний
В процессе работы нашего устройства могут возникнуть два прерывания - от таймера 0 и от УСАПП. Прерывание от таймера О обрабатывается очень просто: перезагружается начальное значение и флаг его срабатывания устанавливается в 1.
pragma vector=TIMERO_OVF_vect
interrupt void TIMERO_OVF_interrupt(void)
{
TCNT0=TmrO_Reload; TmrOFlag = 1;
}
Прерывание от УСАПП говорит о том, что прием пакета данных был закончен и принят в буферный регистр UDR. Обработчик этого прерывания должен принять эти данные и поместить в кольцевой буфер. Для этого должен быть рассчитан новый индекс буфера (указатель головы) и если этот индекс вдруг стал равен указателю хвоста, это говорит о том, что произошла ошибка и буфер приемника переполнился.
^pragma vector=USART_RXC__vect
^interrupt void USART_RX_interrupt{ void )
{
unsigned char data; unsigned char tmphead;
data = UDR;
tmphead = ( USART_RxHead + 1 );
USART_RxHead = tmphead; /* Сохранить новый индекс V
if < tmphead == USART_RxTail )
(
/* Ошибка! Буффер приемника переполнен */
)
USART_RxBuf[tmphead] = data; /* Сохранить полученные данные в буффере */
}
3.3 Проектирование процедур ввода информации
Ввод информации в разрабатываемое устройство осуществляется через УСАПП по протоколу RS-4 85. Как уже отмечалось, прием данных в программе происходит по прерыванию от УСАПП, обработчик которого помещает принятый байт в Оуфер приемника. В главной программе, для того, чтобы можно было анализировать этот буфер и читать данные уже непосредственно из него, необходима процедура, которая будет доставать данные из буфера таким образом, чтобы первыми поступали байты, попавшие в буфер раньше всех. Это делает процедура USART_Receive(), которая сначала ждет поступления данных в буфер, а затем по одному байту достает их оттуда.
BYTE USART_Receive( void )
1
unsigned char tmptail;
while ( USARTJixHead == USART_RxTail )
;
tmptail = USART_RxTail + 1; USART_RxTail = tmptail; return USART_RxBuf[tmptail];
f
3.4 Проектирование процедур вывода информации
Вывод информации в нашем устройстве осуществляется на LCD-дисплей. Основной процедурой, которая отображает строки поступивших данных на дисплее - это процедура AutoWriteMode(), которая по сути управляет дисплеем, выводя на него последовательно символы, хранящиеся в глобальном массиве OutString[], в режиме автозаписи, При этом нам необходимо только менять адрес позиции, в которую выводятся данные.
WORD AutoWriteMode(WORD Address, BYTE NumBytes)
{
SetAddressPointer(Address); SendCommanct{SET_DATA_AUTO_HRITE_COMMAND);
forfint i = 0; i < NumBytes; i++) {
AutoWrite(OutString[i]);
Address++; }
SendCommand(AUTO_RESET_COMMAND); return Address; }
3.5 Проектирование процедур управления периферийными устройствами
Все процедуры управления LCD-дисплеем осуществляются согласно системе команд встроенного контроллера Т6963:
3.6 Проектирование процедуры main()
Процедура main{) работает следующим образом после инициализации все узлов AVR и периферийных устройств, разрешается выполнение всех прерываний. После этого программа ждет срабатывания таймера, который настроен таким образом, что он немного чаще, чем может происходить прерывание от УСАПП. Сигналом того, что таймер 0 сработал служит факт установки глобальной переменной TmrOFlag в 1, что делается обработчиком прерываний таймера.
Затем, все время, пока кольцевой буфер не будет пуст, происходит считывание данных из него. Считанный байт помещается в строку-массив OutString[], и увеличивается счетчик принятых байт.
После этого проверяется, а не был ли последний принятый из буфера байт признаком окончания строки. Если да, то в режиме автозаписи эта строка выводится на дисплей (за исключением последнего символа конца строки). После этого строка обнуляется и счетчик принятых байт устанавливается в ноль.
В любом случае происходит сброс флага таймера в ноль и происходит ожидание следующего срабатывания таймера.
4. Листинг программы
Файл макроопределений my_header.h:
^define BYTE unsigned char ttdefine WORD unsigned int
ttdefine READ_STATUS_COMMAND 0x39
ttdefine DATA_WRITE_COMMAND 0x32
tfdefine COMMANDjmTE_COMMAND ОхЗА
// Установка регистров
^define SET_CURSOR_COMMAKD 0x21
tfdefine SET_OFFSET_COMMAND 0x22
#define SET_ADDRESS_COMMAND 0x24
// Установка контрольного слова
#define SET_TEXT_HOME_ADDRESS_COMMAND 0x^0
fldefine SET_TEXT_AREA_COMMAHD0x41
#define SET_GR№HIC_HOME_ADDRESS_CO№1AND 0x42
#define SET_GRAPHIC_AREA_CCMMAND0x43
// Константы установки режима
^define OR_MODE0x80
tfdefine EXOR_MODE0x81
^define ANDJMODE0x83
#define TEXT_ATTRIBUTE_MODE0x84
^define INTERNAL_CG_ROM_MODE 0x80
tfdefine EXTERNAL_CG_RAM__MODE 0x88
// Константы режима дисплея
#define DISPLAY_OFF0x90
^define CURSOR_ON_BLIHK_OFF0x92
^define CURSOR_ON_BLINK_OK0x93
#define TEXT_ON_GRAPHIC_OFF0x94
#define TEXT__OFF_GRAPHIC_ON0x98
^define TEXT_ON_GRAPHIC_OnOX9C
// Размер курсора
#define ONE_LINE OxAO
tfdefine TWO_LINE OxAl
^define THREE_LINEOxA2
ttdefine FOUR_LINE ОхАЗ
^define FIVE_LINE OxA4
^define SIX_LINE OxA5
^define SEVEN_LINEOxA6
^define EIGHT_LINEOxA7
// Автоматическое чтение/данных
tfdefine SET_DATA_AUTO_WRITE_COMMAND OxBO
^define SET_DATA_AUTO_READ_COMMAND OxBl
^define AUTO_RESET_COMMANDOxB2
//
#define SCREEN_PEEK_CCMMANDOxEO
#define SCREEN_COPY_CC»1MANDOxE8
// Установка/сброс Оитов
tfdefine SET_BIT OxFO
^define RESET_BIT OxF8
^define BIT_0 OxFO
#define BIT_1 OxFl
ttdefine BIT_2 OxF2
^define BIT_3 OxF3
idefine BIT_4 OxF4
#define BIT_5 OxFS
^define BIT_6 OxF6
^define BIT_7OxF7
Файл главкой программы kurs.c;
/* Includes */ ^include <iom!28.h> ^include <ina90.h>
Sinclude "my_header.h"
^define USART_RX_BUFFER_SI2E 128
itdefine TmrOReload 4
static unsigned char TmrOFlag;
Static unsigned char USART_RxBuf[USART_RX_BUFFER_SIZE];
static volatile unsigned char USART_RxHead; static volatile unsigned char USART_RxTail;
static BYTE OutString[128];
// Процедуры инициализации устройств
void InitAVR(void);
void USART_Init( unsigned int baudrate );
void InitLCD(void);
void InitTimer(void);
void InitPortARead(void);
void InitPortAWrite(void)?
void InitPortCWrite(void);
// Процедуры для работы с УСАПП и LCD
unsigned char USART_Receive( void );
void Data«rite<BYTE Data);
void CommandWrite(BYTE Command);
void ReadStatus(void);
void ReadStatus2(void);
void SendCoimand{BYTE Command);
void SendlByteCommand(BYTE Data, BYTE Command);
void Send2ByteCommand(WORD Data, BYTE Command);
void SetCursorPointer(WORD Position)
void SetAddressPointer(WORD Address)
void ByteWriteToRam(WORD AddressPointer, BYTE Data)
void AutoWrite(BYTE Data);
void mainf void )
f
BYTE HumBytes = 0;
InitAVR();
_SEI(); /* Разрешить прерывания */
while (!)
{
if(TmrOFlag) // Произошло срабатывание таймера
{
BYTE rec = 0;
while(DatalnReceiveBuffer() != 0) // Пока буффер не пуст
{
rec = USART_Receive(); // Приняли байт из буффера
OutString[NumBytes] = Rebuild(rec); // Записали его в строку NumBytes-n-;// Увеличить счетчик принятых байт
if (rec == OxOD)// Конец строки - ?
f
/* Выводим строку на LCD в режиме AutoWrite*/
AutoWriteModefO, —NumBytes)
for(int i = 0; i <= NumBytes; i++) OutStringU] = 0;
NumBytes = 0; }
\
TmrOFlag = 0;
} )
}
/* Процедура инициализации USART */ void USART_Init( unsigned int baudrate ) t
unsigned char x;
/* Установить частоту */
UBRROH = (unsigned char) (baudrate»8) ;
UBRROL = (unsigned char) baudrate;
/* Включить приемник UART */ UCSRB = { (1 « RXCIE) | (1«RXEH) ) ;
У/Формат приема данных: 8 бит данных, 1 стоп-бит, проверка на четность UCSRC = (1«URSEL) I (3«UCSZO) | (1«UPM1) ;
/* Обнулить буффер приемника */ х = 0;
USARTJbcTail = х; USART_RxHead = х;
)
/* Процедура чтения из приемника */ BYTE USART_Receive( void }
{
unsigned char tmptail;
while ( USART_RxHead == USART_RxTail ) /* Ждем поступления данных */ ;
tmptail = USART_RxTail + 1; /* Рассчет индекса буффера */ USART_RxTail = tmptail;/* Сохранить новели индекс */
return USART_RxBuf[tmptail]; /* Вернуть данные */
>
unsigned char DatalnReceiveBuffer( void )
{
return ( USART_RxHead != USART_RxTail ); /* Возвращает О если буффер пуст */
}
/* Обработчик прерывания от приемника */ #pragma vector=USART_RXC_vect _interrupt void USART_RX_interrupt( void ) {
unsigned char data;
unsigned char tmphead;
/* Прочесть полученные данные */
data = UDR;
/* Рассчет нового индекса */
tmphead = ( USARTJRxHead + 1 };
USART_RxHead = tmphead; /* Сохранить новый индекс V
if ( tmphead == USART_RxTail ) (
/* Ошибка! Буффер приемника переполнен */
}
USART_RxBuf[tmphead] = data; /* Сохранить полученные данные в буффере */ }
// Процедура инициализации таймера
void JnitTimer(void)
{
disable_interrupt();
TCCRO = 5;// timerO counts elk/1024
TIMSK |= M « TOIEO); //Enable TimerO Interrupt TCWTO = TmrO_Reload; TmrOFlag = 0;
enable_interrupt(};
}
/* Обработчик прерывания от таймера */ tfpragma vector=TIMERO_OVF_vect
interrupt void TIMERO_OVF_interrupt(void)
(
TCNTO=TmrO_Reload;
TmrOFlag =1; }
void InitPortARead(void) {
DDRA = 0;
PORTA = Oxff; }
void InitPortAWrite(void) {
DDRA = Oxff; }
void InitPortCWrite(void) I
DDRC = Oxff;
PORTC = 0x30; }
void InitLCD(void) {
int tmp = 0;
Send2ByteComraand(tm.p, ET_TEXT_HOME_ADDRESS_COMMAND);
tmp = 0x14;
Send2ByteCommand(tmp, SET_TEXT_AREA_COMMAND);
tmp = 0x80;
CoromandWrite(INTERNAL_CG_ROM_MODE);
CommandWrite{TEXT_ON_GRAPHIC_OFF);
I
void InitAVR(void)
I
InitPortAWriteO ;
InitPortCWriteO ;
InitLCDO;
InitTimer();
USART_Init( 47 };//Установить частоту 9,600 используя 1.3728MHz кристалл
}
// Процедуры для работы с LCD-дисплеем void DataWrite(BYTE Data)
t
PINC = DATA_WRITE_COMMAND;
PIНА ~ Data; }
void CommandWrite(BYTE Command)
f
PINC = CCMMRND_WRITE_COMMAND;
Р1ЫА = Command; J
void ReadStatus(void) {
BYTE tempFlag = 0; BYTE stat; InitPortAReadO ; while(tempFlag != 1) (
PINC = READ_STATUS_COMMAND;
Stat = PIMH.;
if((stat & 0x03) == 0x03) tempFlag = 1; }
InitPortAWriteO }
void ReadStatusS(void)
{
BYTE tempFlag = 0; BYTE stat; InitPortAReadO; while(tempFlag != 1) {
PINC = READ_STATUS_COMMAND;
stat = PINA;
if((stat b 0x08) == 0x08) tempFlag = 1; }
InitPortAWriteO }
void SendCommandfBYTE Command)
i
ReadStatus{); WriteCommand(Command); }
void SendlByteCommandfBYTE Data, BYTE Command) {
ReadStatus();
DataWrite(Data);
ReadStatus{);
CommandWrite(Command); }
void Send2ByteCommand{WORD Data, BYTE Command) {
ReadStatus();
DataWrite((BYTE)Data);
ReadStatus();
DataHrite((BYTE)(Data » 8));
ReadStatus ();
CommandWrite(Command); }
// Position: младший байт - координата X (от OOh до 4Fh)
//старший байт - координата Y (от OOh до IFh)
void SetCursorPointer(WORD Position)
{
Send2ByteComnand(Positon, SET_CURSOR_COMMAND);
>
// Address: младший байт
//старший байт
void SetAddressPointer(WORD Address)
{
Serid2BytesCommand[Address, S£T_ADDRESS_COMMAND);
}
void ByteWriteToRamfWORD AddressPointer, BYTE Data)
(
SetAddressPointer(AddressPointer);
ReadStatus();
DataWrite (Data) ,-
ReadStatus();
DataWrite(DATAJWRITEjLNC_ADP); }
void AutoWrite(BYTE Data) (
ReadStatus2();
PINA = Data;
}
// Массив символов OutString должен быть объявлен как
// глобальный массив типа BYTE
WORD AutoWriteModefWORD Address, BYTE NumBytes)
I
SetAddressPointer(Address);
SendCommand(SET_DATA_AUTO_WRITE_COMMRND);
for(int i = 0; i < NumBytes; i++) {
AutoWrite(OutString[i]);
Address++; }
SendCommand (AUTO_RESET_CCMMAND) ; return Address;
}
... снизить вероятность возникновения пожаров на данном объекте. ЗАКЛЮЧЕНИЕ С целью обеспечения безопасности движения речного транспорта в камере шлюза Усть-Каменогорской гидроэлектростанции в данном дипломном проекте была разработана радиолокационная станция обнаружения надводных целей, она гораздо эффективнее, чем, например система видео наблюдения. Были рассчитаны основные тактико- ...
... устройств относительно не велика, соответственно по форме финансирования это могут быть и частные фирмы и госпредприятия. Величина закупок данного вида устройств не может быть высока, т.к. операция измерения отношения двух напряжений является весьма специфической, хотя как таковая она может быть использована в управлении различными техпроцессами на заводах. Приобретая разрабатываемое устройство, ...
... операции чтения Схема стабилизатора напряжения Стабилизатор напряжения построен на микросхеме LM7805. Данная микросхема является линейным стабилизатором напряжения. Напряжение стабилизации 5V. На рисунке 11 приведена схема включения стабилизатора. Рисунок 11 – Схема подключения стабилизатора к микроконтроллеру. 3. Проектирование программного обеспечения микропроцессора 3.1 ...
... 60 минут. Устройство должно обеспечивать долговременное хранение записанной информации при выключении питания устройства. Необходимо предусмотреть индикацию режимов работы цифрового диктофона, а также органы управления режимами устройства. Так как информация должна вводиться и преобразовываться для хранения в цифровой вид, то необходимо применить АЦП и оцифровывать сигнал по методу импульсно- ...
0 комментариев