#include <iom16.h>
#include <inavr.h>
#define XTALL 0.1024
#define delay_us(us) __delay_cycles (XTALL * us);
#define delay_ms(ms) delay_us (1000 * ms)
#define Led PORTB_Bit0
#define D PORTA
#define A0 PORTA_Bit6
#define RW PORTA_Bit5
#define E PORTA_Bit4
#define BS PINA_Bit3
//Пример программы для буквенно-цифровых индикаторов MT10S1, MT16S2, MT20S2, MT24S2, MT20S4 с подключением по 4-х битному режиму.
#define MT10S1 //Выбор типа ЖК индикатора из списка: MT10S1, MT16S2, MT20S2, MT24S2, MT20S4.
#ifdef MT10S1 //Текст для ЖК индикатора MT10S1
#define Len1 8 //Количество символов в первой строке индикатора (10 символов на индикаторе набраны из двух строк!)
#define Len2 2 //Количество символов в второй строке индикатора
#define Len3 0 //Количество символов в третьей строке индикатора
#define Len4 0 //Количество символов в четвёртой строке индикатора
const char Text1[Len1]={ 'М','Э','Л','Т',' ','1','0','S' };
const char Text2[Len2]={ '1',24 };
#endif
void WriteByte(unsigned char b,unsigned int cd) {
//Сначала проверим готовность индикатора
//При необходимости настроить здесь шину данных на ввод
RW=1; A0=0; //Чтение флага занятости
delay_ms(40); //Это время предустановки адреса (tAS)
E=1; delay_ms(230); //Это минимально допустимая длительность сигнала E=1 (информация на шину данных индикатором будет выдана раньше, не более чем через 120нс)
while(BS==1); //Ждать сброса флага занятости
E=0; delay_ms(270); //Минимально допустимый интервал между сигналами E=1
E=1; delay_ms(230); //Получим младшую половину байта
E=0; delay_ms(270); //Минимально допустимый интервал между сигналами E=1
//При необходимости настроить здесь шину данных на вывод
RW=0;
if (cd==1){A0=1;}else{A0=0;}
D=b>>4;
delay_ms(40); //Это время предустановки адреса (tAS)
E=1; delay_ms(230); //Время предустановки данных попало сюда (tDSW)
E=0; delay_ms(270); //Минимально допустимый интервал между сигналами E=1
D=b&0x0F; //Выдадим младшие 4 бита (при этом биты RW и A0 измениться не должны!)
E=1; delay_ms(230); //Время предустановки данных попало сюда (tDSW)
E=0; delay_ms(270); //Минимально допустимый интервал между сигналами E=1
}
void WriteCmd(unsigned char

{ WriteByte(b,0); }
void WriteData(unsigned char

{ WriteByte(b,1); }
void LCDinit(void) {
E=0; delay_ms(20);
//При необходимости настроить здесь шину данных на вывод
RW=0; A0=0; D=0x03; //Установка типа интерфейса (8 бит) (0x03 - старший полубайт команды 0x30) - в начале ВСЕГДА переключаем индикатор в 8-ми битный режим работы
delay_ms(40); //Это время предустановки адреса (tAS)
E=1; delay_ms(230); //Время предустановки данных попало сюда (tDSW)
E=0; delay_ms(40); //Пауза между командами
E=1; delay_ms(230); //Минимально допустимая длительность сигнала E=1
E=0; delay_ms(40); //Пауза между командами
E=1; delay_ms(230);
E=0; delay_ms(40); //Пауза между командами
D=0x02; //Установка типа интерфейса (4 бит) (0x02 - старший полубайт команды 0x20) (при этом биты RW и A0 измениться не должны!)
E=1; delay_ms(230); //Время предустановки данных попало сюда (tDSW)
E=0; delay_ms(270); //Минимально допустимый интервал между сигналами E=1
//Здесь индикатор входит в рабочий режим с установленным типом интерфейса и можно подавать команды как обычно
WriteCmd(0x2A); //Настройка правильного режима ЖКИ
WriteCmd(0x0C); //Включение индикатора, курсор выключен
WriteCmd(0x01); //Очистка индикатора
WriteCmd(0x06); //Установка режима ввода данных: сдвигать курсор вправо
}
void main(void) {
PORTA=0x00;
DDRA=0xff;
PORTB=0x00;
DDRB=0xff;
int i;
Led=1;
LCDinit();
WriteCmd(0x80); //Установка курсора в начало первой строки индикатора
//WriteData('a');
/*
#if Len1>0
for(i=0;i<Len1;i++) { WriteData(Text1[i]); }
#endif
#if Len3>0
for(i=0;i<Len3;i++) { WriteData(Text3[i]); } //Третья строка расположена в внутреннем ОЗУ ЖК индикатора сразу за первой
#endif
WriteCmd(0x80+0x40); //Установка курсора в начало второй строки индикатора
#if Len2>0
for(i=0;i<Len2;i++) { WriteData(Text2[i]); }
#endif
#if Len4>0
for(i=0;i<Len4;i++) { WriteData(Text4[i]); } //Четвёртая строка расположена в внутреннем ОЗУ ЖК индикатора сразу за второй
#endif
*/
}