Учебный курс. Подключение lcd к микроконтроллеру. Разбираемся с флагом занятости.
Для 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 байта.
Значит не обманул.
Файлы
Проект для IARa. Проект для WINAVR.
Comments
должно быть както так:
void LCD_SendStringF lash(prog_uint8 _t *str)
{
uint8_t data = pgm_read_byte(s tr);
while (data)
{
LCD_WriteData(d ata);
str++;
data = pgm_read_byte(s tr);
}
}
Ну и пользуясь случаем - спасибо за статью.
static inline void LCD_Wait(void)
{
unsigned char d;
DDR_DATA = 0;
PORT_DATA = 0xff;
ClearBit(PORT_SIG, RS);
SetBit(PORT_SIG, RW);
do
{
SetBit(PORT_SIG, E);
_delay_ms(2);
ClearBit(PORT_SIG, E);
d = PIN_DATA;
}
while(d & (1
Скачай какой нибудь из проектов, где она применяется, если не разберешься как ее использовать. Например вот этот - часы на микроконтроллер е http://www.chipenable.ru/index.php/files-for-lessons-iar-avr/13-files-for-lessons/127-chasy-na-mikrokontrollere-iar-avr.html
RSS feed for comments to this post