2.3 Схемасброса
Схемасбросадолжнаформироватьимпульслогическогонулядля подачиегонаинверсныйвыводсбросамикроконтроллераRESET. Это импульсдолженформироватьсяпри, например, нажатиинакнопку сбросаустройстваилиприпереключенииключа. Кромеэтого, этот сигналсбросадолженподаватьсяинавыводсбросаLCD - дисплея.
Длятакойсхемыподходитвключениетранзистора, показанноена рис.3. Когдаключоткрыт, транзисторнаходитсявзакрытом состоянииинавходыRESETAVRиRSTLCD-дисплеяпоступает сигналлогическойединицы. Когдаключзамыкается, транзистор открываетсяинавходысбросаустройствпоступаетсигнал логическогонуля.
Рис.3 Схемаформированиясигналасброса
2.4 Схемывходныхивыходныхустройств
Входнымустройствомвнашемпроектеявляетсямикросхема обеспечениясвязипопротоколупередачиданныхRS-485 МАХ 485 со следующимиэлектрическимихарактеристиками:
Изэтихпараметроввидно, чтомикросхемаМАХ485 согласуетсяс микроконтроллеромATmegal6.
Рис. 4 ПодключениемикросхемыMAX4S5
Выходноеустройствожидкокристаллическийграфический дисплейBG12864DфирмыBolyminсовстроеннымконтроллером Т6963С. Этотдисплейобладаетследующимихарактеристиками:
•Механическиехарактеристики
•Назначениевыводов
ВсоответствиисэтимипараметрамисхемаподключенияLCD-дисплеякмикроконтроллерубудетследующей:
2.5 Схемастабилизаторанапряжения
Вкачествестабилизаторанапряжениявнашемустройстве используетсяимпульсныйпонижающийстабилизаторLM2574, который обладаетследующимихарактеристиками:
• входноенапряжение - до 60 V {дляHVверсий)
• выходноенапряжение - 3.3 V, 5 V, 12 V, 15V
• выходнойток - 0.5 А
Схемавключениястабилизаторадляпреобразования +10 V - +5 Vприведенанарис.6:
Рис. 6 (Схема стабилизатора напряжения
3. Проектированиепрограммногообеспечения микроконтроллера
3.1 Проектированиефункцииинициализациимикроконтроллера
Процедураинициализациимикроконтроллерадолжнасостоятьиз процедурилиоператоровинициализациивсехузловсамого микроконтроллераивсехпериферийныхустройств, иустановитьвсе начальныезначениядляихрегистров. Такимобразом, мыдолжны проинициализироватьследующиеузлыустройства - портА, портС, УСАПП, таймер 0 иLCD-дисплей.
ПортыАиСвначалеработыустройстваработаюттолькона выводданных, поэтомуприихнастройкенеобходимов соответствующиерегистрыDDRxзаписатьзначение 0, темсамым настроив все их выводы на передачу данных. Для этого используются две процедуры;
voidInitPortAWrite(void){
DDRA = Oxff; }
void InitPortCWrite(void){ DDRC = Oxff; PORTC = 0x30;
ИнициализациятаймераОпроходитпоследующемуалгоритму - устанавливаетсяделительчастотына 1024 записьюзначения 5 в регистрTCCRO. Затемразрешаетсяпрерываниеэтоготаймераи устанавливаетсяегоначальноезначение:
void InitTimer(void)
i
_disable_interrupt() ;
TCCRO = 5;// установитьделительчастоты 1024
TIMSK |= (1 «TOIEO); // разрешитьпрерываниятаймера
TCNTO = TmrO_Reload;
enable_interrupt{);
]
ИнициализацияУСАППработаетследующимобразом - врегистр
UBRRзаписываетсязначение, котороесоответствуетзаданной скоростипередачиданныхдлясоответствующейчастотыработы микроконтроллера.
УСАПП и параметры кадра данных. Кроме этого, т.к. прием и обработка данных в программе происходит через кольцевой буфер, то в процедуре инициализации необходимо провести начальные установки для головы и хвост буфера - обнулить их.
void USART_Init( unsigned int baudrate )
i
unsigned char x;
UBRROH = (unsigned char) (baudrate»8) ; UBRROL = (unsigned char) baudrate;
UCSRB = ({1 « RXCIE) j <1«ЮС£Н) ) ;
UCSRC = (1«URSEL) | (3«UCSZO) | (1«UPM1);
x = 0;
USART_RxTail = x; USARTJRxHead = x;
}
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
^defineEIGHT_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;
staticBYTEOutString[128];
// Процедурыинициализацииустройств
void InitAVR(void);
void USART_Init( unsigned int baudrate );
void InitLCD(void);
void InitTimer(void);
void InitPortARead(void);
void InitPortAWrite(void)?
voidInitPortCWrite(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) // Покабуффернепуст