|
|
  |
Проблема с управлением HD44780, Не удается должным образом вывести на дисплей необходимую информацию |
|
|
|
Dec 28 2012, 16:03
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980

|
А незабываемый AVRLib - http://www.procyonengineering.com/embedded/avr/avrlib/ пробовали? Ещё имейте в виду, что некоторые дисплеи некорректно работают с 4-бит режимом. Даже если Вы домучаете свой конкретный экземпляр, можете поиметь проблемы переносимости (в смысле работоспособности на разных модулях LCD). У меня лично лежит пара дисплеев, которые я так и не победил на 4 битах  . Один 16x2, второй 20x4. Попробуйте ещё встроенную библиотеку CvAVR. Она только в 4-бит режиме и работает.
--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса. (с) Мария Эдуарда
|
|
|
|
|
Dec 28 2012, 17:33
|
Участник

Группа: Участник
Сообщений: 27
Регистрация: 28-05-12
Пользователь №: 72 050

|
Лет 7 назад я использовал ЖКИ модуль с Mega8. Программу писал на ассемблере. Посылаю кусок инициализации с некоторыми комментариями. Буду рад если поможет.
Прикрепленные файлы
LCD.txt ( 2.26 килобайт )
Кол-во скачиваний: 49
|
|
|
|
|
Dec 29 2012, 13:17
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673

|
Цитата(Genadi Zawidowski @ Dec 28 2012, 20:47)  http://forum.cqham.ru/viewtopic.php?t=17803, там архив с исходниками - файл с именем hd44780.c - для ускорения работы используется проверка готовности дисплея чтением его регистра состояни (т.е., вывод WR задействован). Там всё очень сложно и запутано для меня. Ситуация такая что знакомый написал мне прошивку для проверки работоспособности LCD (выводит русский текст) - и всё нормально вывелось, т.е. косяк точно в моей программе. Один например уже нашел: Вместо - temp =(lcd & ~(1<<RS)) | (1<<E); //задаём тип данных, который хотим переслать Нужно было - temp =(lcd | ~(1<<RS)) | (1<<E); Теперь я могу вывести на экран всякую белеберду, но не то что мне нужно и не там где мне нужно.
|
|
|
|
|
Dec 29 2012, 22:52
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (endasm @ Dec 29 2012, 15:17)  Нужно было - temp =(lcd | ~(1<<RS)) | (1<<E); Сократите это выражение до temp =lcd | ~(1<<RS) и подумайте - вы действительно этого хотели?
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 30 2012, 07:53
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673

|
Цитата(Сергей Борщ @ Dec 30 2012, 01:52)  Сократите это выражение до temp =lcd | ~(1<<RS) и подумайте - вы действительно этого хотели? Я ошибся когда писал сообщение, на самом деле там: PORTC =(lcd & ~(1<<RS)) | (1<<E);
|
|
|
|
|
Dec 30 2012, 14:08
|

Частый гость
 
Группа: Участник
Сообщений: 148
Регистрация: 23-02-07
Пользователь №: 25 618

|
Цитата(endasm @ Dec 30 2012, 10:53)  Я ошибся когда писал сообщение, на самом деле там: PORTC =(lcd & ~(1<<RS)) | (1<<E); Посмотрите LCD library for HD44870 based LCD'sКак что установить помощьв lcd.h назначаете порты и выводы. Код #define LCD_PORT PORTA /**< port for the LCD lines */ #define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */ #define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */ #define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */ #define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */ #define LCD_DATA0_PIN 0 /**< pin for 4bit data bit 0 */ #define LCD_DATA1_PIN 1 /**< pin for 4bit data bit 1 */ #define LCD_DATA2_PIN 2 /**< pin for 4bit data bit 2 */ #define LCD_DATA3_PIN 3 /**< pin for 4bit data bit 3 */ #define LCD_RS_PORT LCD_PORT /**< port for RS line */ #define LCD_RS_PIN 4 /**< pin for RS line */ #define LCD_RW_PORT LCD_PORT /**< port for RW line */ #define LCD_RW_PIN 5 /**< pin for RW line */ #define LCD_E_PORT LCD_PORT /**< port for Enable line */ #define LCD_E_PIN 6 /**< pin for Enable line */ Используете так Код #include "lcd.h"
// main int main(void) { lcd_init(LCD_DISP_ON); // инициализация LCD lcd_clrscr(); // очищаем индикатор lcd_puts("Proba Linia1"); lcd_gotoxy(0,1); lcd_puts(" Linia2"); while(1) { } }
Сообщение отредактировал Marian - Dec 30 2012, 14:24
|
|
|
|
|
Dec 30 2012, 21:16
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673

|
Вообщем переделал я немного функции и дисплей почти корректно заработал, но вот проблема походу кроется ещё в моем компиляторе: латиницу он нормально кодирует в соответствии ACSII, а вот вместо цифр и кириллицы на дисплее отображается всякие левые символы, к примеру я программирую что бы было "абвгдеёжз", а на дисплее "аЦЩдфцищ'". с цифрами всё ещё хуже - там вообще какие то вертикальные полосочки и крестики вместо них( например int i=1; lcd_SendData(i); - на дисплее две вертикальные палочки с черточкой посередине). Судя по таблице знакогенератора (  ) - мой компилятор не корректно кодирует ACSII в двоичный код, так как если я ввожу в программе тупо код нужного мне символа - то всё прекрасно выводится на ЖКИ. Программирую в AtmelStudio 6.0.1863. Подскажите что бы такое изменить и где в студии или же как в программе переназначить кодировки символов (цифр и кириллицы). Вот работающий код: CODE #define E 4 //E = PORTC.4 - стробирующий сигнал #define RS 5 //RS = PORTC.5 - определение типа данных: команда(RS=0) или данные(RS=1) #define RW 6 //RW = PORTC.6 - выбор режима: запись(RW=0) или чтение(RW=1)
void lcd_SendCmd(unsigned char lcd) //функция передачи команд в дисплей { _delay_us(15); PORTC = (lcd>>4 & ~(1<<RS) & ~(1<<RW)) | (1<<E); //задаём тип данных, который хотим переслать, выводим в порт старшую тетраду команды, сигналы RS и E _delay_us(15); PORTC &= ~(1<<E); //cигнал записи команды _delay_us(15); PORTC = (lcd & ~(1<<RS) & ~(1<<RW)) | (1<<E); //задаём тип данных, который хотим переслать, выводим в порт младшую тетраду команды, сигналы RS и E _delay_us(10); PORTC &= ~(1<<E); //cигнал записи команды _delay_us(15); }
void lcd_SendData(unsigned char lcd) //функция передачи данных в дисплей { _delay_us(15); PORTC = ((lcd>>4) | (1<<RS) | (1<<E)) & ~(1<<RW); //задаём тип данных, который хотим переслать, выводим в порт старшую тетраду данных, сигналы RS и E _delay_us(15); PORTC &= ~(1<<E); //cигнал записи данных _delay_us(15); PORTC = (lcd | (1<<RS) | (1<<E)) & ~(1<<RW); //задаём тип данных, который хотим переслать, выводим в порт младшую тетраду данных, сигналы RS и E _delay_us(15); PORTC &= ~(1<<E); //cигнал записи данных _delay_us(15); }
void lcd_init(void) //функция инициализации дисплея { lcd_SendCmd(0b00101000); //4-бит интерфейс, 2 строки, 5х8 точек _delay_ms(3); lcd_SendCmd(0b00000110); //адресс будет инкреминтироваться, экран не движется _delay_ms(3); lcd_SendCmd(0b00000001); //очистка дисплея, указатель встал на 0x00 DDRAM _delay_ms(5); lcd_SendCmd(0b00001100); //включаем ЖКИ, без отображения курсора _delay_ms(3); }
Сообщение отредактировал IgorKossak - Dec 31 2012, 18:06
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!, форматирование
|
|
|
|
|
Dec 30 2012, 21:54
|
Частый гость
 
Группа: Участник
Сообщений: 105
Регистрация: 22-06-05
Пользователь №: 6 228

|
Цитата(endasm @ Dec 31 2012, 01:16)  Подскажите что бы такое изменить и где в студии или же как в программе переназначить кодировки символов (цифр и кириллицы). Коды кирилических символов в LCD не соответствуют кодам ASCII: буквы, одинаковые по написанию используются в обоих алфавитах. Т.е. нужна перекодировка. Хорошо бы заставить это сделать компилятор, но можно и в "реальном времени": CODE void hd44780_putc(char c) { if ((c >= 'А') && (c <= 'я')) { c = cyrillic[ c - 'А' ].code; } else if (c == 'ё') { c = 0xB5; } else if (c == 'Ё') { c = 0xA2; }
// ... вывод на LCD ... }
typedef struct { char symbol; uint8_t code; }symbol_table_t;
static const symbol_table_t cyrillic[66] = { {'А', 0x41}, //'A' {'Б', 0xA0}, {'В', 0x42}, //'B' {'Г', 0xA1}, {'Д', 0xE0}, {'Е', 0x45}, //'E' {'Ж', 0xA3}, {'З', 0xA4}, {'И', 0xA5}, {'Й', 0xA6}, {'К', 0x4B}, //'K' {'Л', 0xA7}, {'М', 0x4D}, //'M' {'Н', 0x48}, //'H' {'О', 0x4F}, //'O' {'П', 0xA8}, {'Р', 0x50}, //'P' {'С', 0x43}, //'C' {'Т', 0x54}, //'T' {'У', 0xA9}, {'Ф', 0xAA}, {'Х', 0x58}, //'X' {'Ц', 0xE1}, {'Ч', 0xAB}, {'Ш', 0xAC}, {'Щ', 0xE2}, {'Ъ', 0xAD}, {'Ы', 0xAE}, {'Ь', 0x62}, //'b' {'Э', 0xAF}, {'Ю', 0xB0}, {'Я', 0xB1}, {'а', 0x61}, //'a' {'б', 0xB2}, {'в', 0xB3}, {'г', 0xB4}, {'д', 0xE3}, {'е', 0x65}, //'e' {'ж', 0xB6}, {'з', 0xB7}, {'и', 0xB8}, {'й', 0xB9}, {'к', 0xBA}, {'л', 0xBB}, {'м', 0xBC}, {'н', 0xBD}, {'о', 0x6F}, //'o' {'п', 0xBE}, {'р', 0x70}, //'p' {'с', 0x63}, //'c' {'т', 0xBF}, {'у', 0x79}, //'y' {'ф', 0xE4}, {'х', 0x78}, //'x' {'ц', 0xE5}, {'ч', 0xC0}, {'ш', 0xC1}, {'щ', 0xE6}, {'ъ', 0xC2}, {'ы', 0xC3}, {'ь', 0xC4}, {'э', 0xC5}, {'ю', 0xC6}, {'я', 0xC7}, {'Ё', 0xA2}, {'ё', 0xB5} };
Сообщение отредактировал IgorKossak - Dec 31 2012, 18:07
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Dec 30 2012, 21:55
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(endasm @ Dec 30 2012, 23:16)  а вот вместо цифр и кириллицы на дисплее отображается всякие левые символы, к примеру я программирую что бы было "абвгдеёжз", а на дисплее "аЦЩдфцищ'". Видимо производитель LCD закодировал символы как ему вздумалось, а не в соответствии с существующими кодировками (а может какой-то и соответствует?). Цитата(endasm @ Dec 30 2012, 23:16)  с цифрами всё ещё хуже - там вообще какие то вертикальные полосочки и крестики вместо них( например int i=1; lcd_SendData(i); - на дисплее две вертикальные палочки с черточкой посередине). А что вы там ждёте? Задали дисплею выдать байт 0x00 - он и выдал что-то непечатное. Вам надо преобразовать число к печатному виду. Или вы думаете в дисплее printf реализован который за вас это сделает? Цитата(endasm @ Dec 30 2012, 23:16)  мой компилятор не корректно кодирует ACSII в двоичный код, так как если я ввожу в программе тупо код нужного мне символа - то всё прекрасно выводится на ЖКИ. Создайте таблицу перекодировки в соответствии с рисунком. Латиницу перекодировать не надо - только то что после 0x7F.
|
|
|
|
|
Dec 30 2012, 22:18
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673

|
Цитата(_Артём_ @ Dec 31 2012, 00:55)  Видимо производитель LCD закодировал символы как ему вздумалось, а не в соответствии с существующими кодировками (а может какой-то и соответствует?).
А что вы там ждёте? Задали дисплею выдать байт 0x00 - он и выдал что-то непечатное. Вам надо преобразовать число к печатному виду. Или вы думаете в дисплее printf реализован который за вас это сделает?
Создайте таблицу перекодировки в соответствии с рисунком. Латиницу перекодировать не надо - только то что после 0x7F. Да, вы правы на счет цифр. Сейчас делаю таким макаром: int i=1; lcd_SendData(i+48); - подскажите всегда ли это будет работать с цифрами и какие недостатки таит в себе такой подход?
|
|
|
|
|
Dec 30 2012, 23:02
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673

|
Вообщем всё наконец таки заработало как надо, спасибо огромное товарищу "S17". Понимаю что С++ надо учить и учить что бы так свободно с ним обращаться как Вы. Спасибо всем, на днях напишу ещё свои функции для других операций с ЖКИ (в планах функция установки курсора в произвольное место DDRAM с координатами x,y и т.д), думаю сам справлюсь. Благодарю за помощь. Фото ЖКИ
Сообщение отредактировал endasm - Dec 30 2012, 23:08
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|