У меня подобная инициализация не проходила, пока не сделал как советовал кто-то из производителей контроллера (samsung?):
Код
extern char WaitDisplay(void)
{
// функция считывания флага занятости дисплея
unsigned char Time;
unsigned char Flags;
unsigned char TimesReg;
TimesReg=__save_interrupt();
__disable_interrupt(); // запрещаем прерывания
PortDIn(); // шину данных атмеги переключаем на прием данных
ClearRS(); // сбрасываем линию RS
SetRW(); // выставляем линию RW
SetE(); // выставляем линию E
__delay_cycles(0x03); // задержка в 300nS
Time=PortDisplayRead; // в Time запоминаем старший байт данных дисплея
if ((Time&0x10)!=0x00) Flags=0xFF; // запоминаем статус занятости
else Flags=0x00;
ClearE(); // сбрасываем линию E
__delay_cycles(0x06); // задержка в 542nS
SetE(); // выставляем линию E
__delay_cycles(0x03); // задержка в 300nS
Time=PortDisplayRead; // в Time запоминаем младший байт данных дисплея
__delay_cycles(0x02); // задержка в 180nS
ClearE(); // сбрасываем линию E
__restore_interrupt(TimesReg); // разрешаем прерывания
return Flags; // возвращаем статус занятости дисплея
}
extern void DataDisplay(unsigned char Value)
{
// запись данных в дисплей c ожиданием готовности
unsigned char Time;
unsigned char TimesReg;
LoopDataDisplay:
if (WaitDisplay()!=0) goto LoopDataDisplay; // выполняем цикл пока функция WaitDisplay не вернет статус не занятости дисплея
TimesReg=__save_interrupt();
__disable_interrupt(); // запрещаем прерывания
SetRS(); // выставляем линию RS
ClearRW(); // сбрасываем линию RW
Value=Revers(Value,0x00); // в Value заносим данные для передачи
Time=Value << 4; // сдвигаем на старшую половину полубайта младшую часть данных для передачи
PortDOut(); // переключаем порт D на передачу данных
PortDisplayWrite=Time; // передаем младший полубайт в дисплей
SetE(); // выставляем линию E
__delay_cycles(0x06); // задержка в 542nS
ClearE(); // сбрасываем линию E
PortDisplayWrite=Value; // передаем старший полубайт в дисплей
__delay_cycles(0x03); // задержка в 300nS
SetE(); // выставляем линию E
__delay_cycles(0x06); // задержка в 542nS
ClearE(); // сбрасываем линию E
PortDIn(); // переключаем порт D на прием данных
ClearRS(); // сбрасываем линию RS
SetRW(); // выставляем линию RW
__restore_interrupt(TimesReg); // разрешаем прерывания
}
extern void CommandDisplay(unsigned char Value)
{
// запись комманды в дисплей c ожиданием готовности
unsigned char Time;
unsigned char TimesReg;
LoopCommandDisplay:
if (WaitDisplay()!=0) goto LoopCommandDisplay; // выполняем цикл пока функция WaitDisplay не вернет статус не занятости дисплея
TimesReg=__save_interrupt();
__disable_interrupt(); // запрещаем прерывания
ClearRS(); // сбрасываем линию RS
ClearRW(); // сбрасываем линию RW
Value=Revers(Value,0x00); // в Value заносим данные для передачи
Time=Value << 4; // сдвигаем на старшую половину полубайта младшую часть данных для передачи
PortDOut(); // переключаем порт D на передачу данных
PortDisplayWrite=Time; // передаем младший полубайт в дисплей
SetE(); // выставляем линию E
__delay_cycles(0x06); // задержка в 542nS
ClearE(); // сбрасываем линию E
PortDisplayWrite=Value; // передаем старший полубайт в дисплей
__delay_cycles(0x03); // задержка в 300nS
SetE(); // выставляем линию E
__delay_cycles(0x06); // задержка в 542nS
ClearE(); // сбрасываем линию E
PortDIn(); // переключаем порт D на прием данных
ClearRS(); // сбрасываем линию RS
SetRW(); // выставляем линию RW
__restore_interrupt(TimesReg); // разрешаем прерывания
}
extern void CommandDisplay8(unsigned char Value)
{
// запись младшей части комманды в дисплей без проверки готовности
unsigned char Time;
unsigned char TimesReg;
TimesReg=__save_interrupt();
__disable_interrupt(); // запрещаем прерывания
ClearRS(); // сбрасываем линию RS
ClearRW(); // сбрасываем линию RW
Value=Revers(Value,0x00); // в Value заносим данные для передачи
Time=Value << 4; // сдвигаем на старшую половину полубайта младшую часть данных для передачи
PortDOut(); // переключаем порт D на передачу данных
PortDisplayWrite=Time; // передаем младший полубайт в дисплей
SetE(); // выставляем линию E
__delay_cycles(0x06); // задержка в 542nS
ClearE(); // сбрасываем линию E
PortDIn(); // переключаем порт D на прием данных
SetRW(); // выставляем линию RW
__restore_interrupt(TimesReg); // разрешаем прерывания
}
CommandDisplay8(0x30);
__delay_cycles(0xD800);
CommandDisplay8(0x30);
__delay_cycles(0x500);
CommandDisplay8(0x30);
__delay_cycles(0x500);
CommandDisplay8(0x28);
CommandDisplay(0x28);
CommandDisplay(0x0C);
CommandDisplay(0x06);
CommandDisplay8 - посылала данные без опроса флага занятости дисплея
CommandDisplay - с опросом флага занятости и по четырем линиям.
Revers - переворачивала байт, так цоколевки дисплея и контроллера включены были встречно.
Запись в порт корректнее сделана у vet'а:
#define WRITE_LOW_NIBBLE(x) ( PORTD = (PORTD & 0x0F) | ((x) << 4) )
#define WRITE_HIGH_NIBBLE(x) ( PORTD = (PORTD & 0x0F) | ((x) & 0xF0) )