Мікроконтролерна система з рідкокристалічним індикатором для управління комп’ютером
1.6 Драйвери для мікроконтролера та лістинг програми роботи РКІ
Для забезпечення роботи РКІ панелі потрібно встановити необхідні драйвери та бібліотеки для програмованих компонентів схеми.
· lcd.c, lcd.h, lcd_hw.h: Це загальна бібліотека AVR LCD. Вона базується на роботі Peter Fleury (http://jump.to/fleury). Ця версія злегка модифікована і є більше гнучкою. Вона дозволяє приєднати РК-дисплей до будь-якого контакту мікроконтролера, необхідно лише перемінити значення у файлі lcd_hw.h.
· avr-util.c, avr-util.h: функції для одержання різних затримок за часом.
· uart.c, uart.h: Це бібліотека для інтерфейсу RS232. Вона використає апаратні переривання. Як тільки від компютера приходить символ, виконується функція SIGNAL(SIG_UART_RECV), і дані копіюються із прийомного буфера в буфер рядків. Командна мова для нашої РК-панели побудований так, що кожна команда закінчується символом нового рядка. Коли буде знайдений символ нового рядка, установлюється прапор (uart_rx_linecomplete), а дані стають доступними. Це також означає, що потрібно посилати команди дисплею як найшвидше, а чекати якийсь час (мілісекунду) після кожного рядка. Кожна команда підтверджується результатом, ok, або err (при помилці). Керуюча програма perl може використати результат як селектор для посилання наступної команди.
· analog.c, analog.h: Код аналого-цифрового перетворювача. Він також управляється перериваннями. Коли запускається окреме перетворення аналог-код, програма чекає переривання SIG_ADC, щоб уважати результат з регістра ADC.
· hardwarewd.c, hardwarewd.h: Це сторожовий таймер. Використовується внутрішній дільник (ділимо на 1024), щоб управляти таймером. Таймер - це 16-бітний регістр, від якого ми віднімаємо 8-бітну змінну до переповнення. Для кварцу 4MHz ми будемо відраховувати нашу змінну близько 16 секунд. Програма на perl визначає, що компютер працює, періодично встановлюючи змінну назад у максимальне значення. Якщо вона не може цього зробити (наприклад, компютер завис), то змінна постійно зменшує своє значення, а коли вона досягне 0, реле перемкнеться й викличе апаратне перезавантаження нашого сервера.
· linuxlcdpanel.c: Це основна програма. Вона безупинно перевіряє наявність команд від інтерфейсу RS232 і натискання кнопок.
Тепер перейдемо до написання програми. Для контроля індикатора напишемо програму із декількома ключовими функціями роботи з РКІ: lcd_dat(unsigned char x) - для запису даних х, lcd_com(unsigned char x) - для запису команди х, lcd_init(void) - для початкової ініціалізації індикатора:
#include <avr/io.h> //бібліотека вводу/виводу
#define RS 2 //RS=PD2 - сигнал управління РКІ
#define E 3 //E=PD3 - сигнал управління РКІ
#define TIME 10 //Константа часової затримки для РКІ
//Частота тактування МК - 4Мгц
//Програма формування затримки
void pause (unsigned int a)
{ unsigned int i;
for (i=a;i>0;i--);
}
//Програма передачі команд в РКІ
void lcd_com (unsigned char lcd)
{ unsigned char temp;
temp=(lcd&~(1<<RS))|(1<<E);//RS=0 - це команда
PORTD=temp; //Виводимо на portD старшу тетраду команди, сигнали
RS, E
asm("nop"); //Невелика затримка в 1 такт МК, для стабілізації
PORTD=temp&~(1<<E); //Сигнал запису команди
temp=((lcd*16)&~(1<<RS))|(1<<E);//RS=0 - это команда
PORTD=temp; //Виводимо на portD молодшу тетраду команды, сигналы
RS, E
asm("nop"); //Найбільша затримка в 1 такт МК, для стабілізації
PORTD=temp&~(1<<E); //Сигнал запису команди
pause (10*TIME); //Пауза для виконання команди
}
//Програма запису даних в РКІ
void lcd_dat (unsigned char lcd)
{ unsigned char temp;
temp=(lcd|(1<<RS))|(1<<E);//RS=1 - це данні
PORTD=temp; //Виводимо на portD старшу тетраду asm("nop");
//Невелика затримка в 1 такт МК, для стабілізації
PORTD=temp&~(1<<E); //Сигнал запису даних
temp=((lcd*16)|(1<<RS))|(1<<E);//RS=1 - це данні
PORTD=temp; //Виводимо на portD молодшу тетраду даних, сигнали
RS, E
asm("nop"); //Невелика затримка в 1 такт МК, для стабілізації
PORTD=temp&~(1<<E); //Сигнал запису даних
pause(TIME); //Пауза для вивода даних
}
//Программа ініціалізації РКІ
void lcd_init (void)
{
lcd_com(0x2c);//4-провідний інтерфейс, 5x8 розмір символа
pause(100*TIME);
lcd_com(0x0c);//Показати зображення, курсор не показувати
pause(100*TIME);
lcd_com(0x01);//Очистити DDRAM и установити курсор на 0x00
pause (100*TIME);
}
//Основна програма
int main(void)
{
DDRD=0xfc;//Ініціалізація portD
PORTD=0x00;
pause(1000);//Затримка, щоб РКІ встиг включитися
lcd_init();//Ініціалізація РКІ
lcd_dat(w); //Вивід
lcd_dat(w);
lcd_dat(w);
lcd_dat(.);
lcd_dat(a);
lcd_dat(v);
lcd_dat(r);
lcd_dat(l);
lcd_dat(a);
lcd_dat(b);
lcd_dat(.);
lcd_dat(c);
lcd_dat(o);
lcd_dat(m);
lcd_com(0xc0);//Ставимо курсор на початок 2-го рядка РКІ
lcd_dat(I);//Записуємо
lcd_dat(t);
lcd_dat(");
lcd_dat(s);
lcd_dat( );
lcd_dat(s);
lcd_dat(o);
lcd_dat( );
lcd_dat(e);
lcd_dat(a);
lcd_dat(s);
lcd_dat(y);
while(1)//безкінечний цикл
;
return 1;
}
Для латині і цифр ASCII коди співпадають з зашитими в знакогенератор РКІ, відтак дозволено використовувати lcd_dat(`A). Можно зробити свою бібліотеку для роботи з РКІ, виділивши функції lcd_dat(unsigned char x), lcd_com(unsigned char x), lcd_init(void) в окремий модуль LCD.h и підключати його за необхідністю.
· Ця процедура дуже економить час, варто тільки один раз написати потрібні функції, а потім весь час їх тільки використовувати. Також варто підмітити, что незручно виводити довгу фразу по одній літері, для цього необхідно нашу строку виведення помістити в массив із unsigned char і виводити за допомогою цикла:
· int main(void)
· { unsigned char data [14]= {w,w,w,.,a,v,r,l,a,b,.,c,o,m};
· unsigned char i;
· DDRD=0xfc;//Ініціалізація portD
· PORTD=0x00;
· pause(1000); //Затримка, щоб РКІ встиг включитися
· lcd_init();//Ініціалізація РКІ
· for (i=0;i<14;i++)//Вивід запису політерно
· lcd_dat(data[i]);