Для 8-ми разрядной шины процедура чтения флага занятости и адреса выглядит следующим образом:
1. Настроить порт микроконтроллера на вход
2. Установить RW = 1
3. Установить RS = 0
4. Установить E = 1
5. Считать значение байта данных с шины DB7…DB0
6. Установить E = 0
7. Установить RW = 0
8. Настроить порт на выход
#define FLAG_BF 7
#pragma inline = forced
void LCD_Wait(void)
{
unsigned char data;
DDRX_DATA = 0; //конфигурируем порт на вход
PORT_DATA = 0xff; //включаем pull-up резисторы
SetBit(PORT_SIG, RW); //RW в 1 чтение из lcd
ClearBit(PORT_SIG, RS); //RS в 0
do{
SetBit(PORT_SIG, EN);
_delay_us(2);
data = PIN_DATA; //чтение данных с порта
ClearBit(PORT_SIG, EN);
}while((data & (1<<FLAG_BF))!= 0 );
ClearBit(PORT_SIG, RW);
DDRX_DATA = 0xff;
}
Теперь состыкуем функцию ожидания готовности дисплея LCD_Wait() c функциями записи команд/данных.
//функция записи команды
void LCD_WriteCom(unsigned char data)
{
LCD_Wait(); //ожидание готовности дисплея
ClearBit(PORT_SIG, RS); //установка RS в 0 - команды
LCD_CommonFunc(data);
}
//функция записи данных
void LCD_WriteData(unsigned char data)
{
LCD_Wait(); //ожидание готовности дисплея
SetBit(PORT_SIG, RS); //установка RS в 1 - данные
LCD_CommonFunc(data);
}
Надеюсь вы не забыли, что в предыдущей статье я вынес общие куски кода в отдельную встраиваемую функцию. Ее тоже нужно подправить - удалить программную задержку _delay_us(40);
#pragma inline = forced
void LCD_CommonFunc(unsigned char data)
{
PORT_DATA = data; //вывод данных на шину индикатора
SetBit(PORT_SIG, EN); //установка E в 1
_delay_us(2);
ClearBit(PORT_SIG, EN); //установка E в 0 - записывающий фронт
}
Исправим функции вывода строк следующим образом.
//функция вывода строки из флэш памяти
void LCD_SendStringFlash(unsigned char __flash *str)
{
unsigned char data;
while (*str)
{
data = *str++;
LCD_WriteData(data);
}
}
//функция вывда строки из ОЗУ
void LCD_SendString(unsigned char *str)
{
unsigned char data;
while (*str)
{
data = *str++;
LCD_WriteData(data);
}
}
В хедере:
#define CHECK_FLAG_BF
В сишном файле:
void LCD_Wait(void)
{
#ifdef CHECK_FLAG_BF
//код реализующий опрос флага занятости
#else
//программная задержка
#endif
}
#pragma inline = forced
void LCD_Wait(void)
{
#ifdef CHECK_FLAG_BF
unsigned char data;
DDRX_DATA = 0; //конфигурируем порт на вход
PORT_DATA = 0xff; //включаем pull-up резисторы
SetBit(PORT_SIG, RW); //RW в 1 чтение из lcd
ClearBit(PORT_SIG, RS); //RS в 0 команды
do{
SetBit(PORT_SIG, EN); //EN = 1
_delay_us(2);
data = PIN_DATA; //чтение данных с порта
ClearBit(PORT_SIG, EN); //EN = 0
}while((data & (1<<FLAG_BF))!= 0 ); //пока флаг не сброшен, крутимся в цикле
ClearBit(PORT_SIG, RW);
DDRX_DATA = 0xff;
#else
_delay_us(40);
#endif
}
Проверим не обманул ли я вас.
В настройках проекта устанавливаем разрешение выдачи файла листинга.
Project > Options…
С/С++ Compiler >List галочка Output List File
Включаем оптимизацию по размеру на максимум
С/С++ Compiler > Optimizations
Сохраняем.
Сейчас строчка #define CHECK_FLAG_BF не закомментирована.
Жмем F7.
Открываем файл листинга - 170 байтов.
Закомментируем #define CHECK_FLAG_BF и снова запустим компиляцию. Теперь - 144 байта.
Значит не обманул.