Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.90/21: Рейтинг темы: голосов - 21, средняя оценка - 4.90
wypuk
0 / 0 / 0
Регистрация: 23.05.2010
Сообщений: 4
1

О выводе на дисплей LCD HD44780

28.07.2013, 11:22. Просмотров 4048. Ответов 6
Метки нет (Все метки)

Пишу программу на Atmego32A. Столкнулся с проблемкой при выводе на дисплей. Функции вывода на дисплей взял из библиотеки DY HOTT-а. Единственным отличаем от его способа - то что выводимую строку я беру не из Ftosh, а из ОЗУ. В ОЗУ она предварительно переносится из Ftosh. Вобщем вижу такой баг, что периодически строка выводится правильно, бывает выводится только часть строки начиная не с первого символа, а со 2.. 3.. 4.. и т.д., бывает символы пропускаются, а бывает выводятся китайские иероглифы))). Вообщем вот код задачи вывода на дисплей, может где ошибка?
Код
Out_LCD_error:
push temp
push XL
push XH
push RegOS
push R11

ldi  RegOS, 0b00000001         ;очистить дисплей
rcall CMD_WR
ldi  RegOS, 0b00000110         ;инкримент адреса и сдвиг курсора
rcall CMD_WR
ldi  RegOS, 0b00001100         ;включить дисплей
rcall CMD_WR
ldi  temp, lengh_phrase_2                              ;длина фразы находящейся в ОЗУ
mov  R11, temp                                           ;использую R11 как счетчик т.к. temp используется в функции DATA_WR
ldi  XL, low (phrase_2)                                  ;адрес начала строки
ldi  XH, high(phrase_2)
Write_LCD_Data:
ld   RegOS, X+                                             ;загружаю символ из строки
rcall DATA_WR                                             ;запись в дисплей
dec  R11                                                     ;инкрементируем счетчик
brne Write_LCD_Data                                    ;на запись следующего символа
cbr  Flag, 1<<4                                            ;Flag - глобальная переменная

pop  R11
pop  RegOS
pop  XH
pop  XL
pop  temp
rjmp End_Task_Manager
Вот код функции вывода данных на дисплей
Код
;   Запись команды в дисплей. Код команды в R17

CMD_WR:
rcall BusyWoyt                     ; Ждем готовности
cbi   CMD_PORT, RS                  ; Идет команда!
rjmp  WR_END                     ; Переход на запись

;   Запись данных в дисплей. Код данных в R17

DATA_WR:
rcall BusyWoyt                     ; Ждем готовности
sbi   CMD_PORT, RS                  ; Идут данные!
WR_END:
cbi   CMD_PORT, RW                  ; Запись!
sbi   CMD_PORT, E                  ; Поднять строб

rcall PortOut                     ; Порт настроить на выход!
push  R17                        ; Сохраним данные которые будем выводить в стеке
omdi  R17, 0xF0                     ; Отдавим по маске данным младшую тетраду.

in    R16, DATA_PORT               ; Возьмем из порта данных старое значение
omdi  R16, 0x0F                     ; Отдавим ему старшую тетраду

push  R16                        ; Сохраним результа в стеке. Пригодится

or    R16, R17                     ; Склеим младшую тетраду из порта со старшей тетрадой данных

out   DATA_PORT, R16               ; Выдадим этого мутанта в порт.

rcall LCD_Delay                     ; Подождем
cbi   CMD_PORT, E                  ; Бросим строб вниз - данные ушли в индикатор
rcall LCD_Delay                     ; Подождем

sbi   CMD_PORT, E                  ; Поднимем строб
pop   R16                        ; Достанем из стека младшую тетраду из порта
pop   R17                        ; И данные которые мы выводим

swap  R17                        ; Поменяем тетрады местами у байта данных
omdi  R17, 0xF0                     ; Отдавим младшую тетраду

or    R16, R17                     ; Склеим младшую тетраду из порта с старшей тетрадой данных (бывшая младшая)
out   DATA_PORT, R16               ; Выдадим в порт

rcall LCD_Delay                     ; Подождем
cbi   CMD_Port, E                  ; Бросим строб
rcall LCD_Delay

rcall PortIn                     ; Порт вернем в прежнее состояние - на вход
ret                              ; Возврат

;   Настройка порта на вход

PortIn:
in    R16, DATA_DDR                  ; Динные из DDR в регистр
omdi  R16, 0x0F                     ; Отдавливаем старшую тетраду - нам нужно сохранить младшую и обнулить старшую
out   DATA_DDR, R16                  ; Выдаем результат в порт.

in    R16, DATA_PORT               ; Берем данные из порта
ori   R16, 0xF0                     ; Выставляем все биты старшей тетрады, не трогая младшую
out   DATA_PORT, R16               ; Выдаем в порт
ret

;   Настройка порта на выход

PortOut:
in    R16, DATA_DDR                  ; Динные из ДДР в регистр
ori   R16, 0xF0                     ; Выставляем все биты старшей тетрады, не трогая младшую
out   DATA_DDR, R16                  ; Выдаем данные в порт
ret

;   Ожидание готовности дисплея

BusyWoyt:
cbi   CMD_PORT, RS                  ; Идет Команда!
sbi   CMD_PORT, RW                  ; Чтение!
BusyLoop:
sbi   CMD_PORT, E                  ; Поднять строб
rcall LCD_Delay                     ; Подождать
cbi   CMD_PORT, E                  ; Бросить строб - первый цикл (старший полубайт)
rcall LCD_Delay                     ; Подождем маленько

in    R16, DATA_PIN                  ; Считать байт
push  R16                        ; Сохранить его в стек. Дело в том, что у нас R16 убивается в LCD_Delay

sbi   CMD_PORT, E                  ; Поднимем строб
rcall LCD_Delay                     ; Подождем
cbi   CMD_PORT, E                  ; Опустим строб   - нужно для пропуска второго полубайта
rcall LCD_Delay                     ; Задержка снова

pop   R16                        ; А теперь достаем сныканый байт - в нем наш флаг. Может быть.

omdi  R16, 0x80                     ; Продавливаем по маске. Есть флаг?
brne  BusyLoop                     ; Если нет, то переход
BusyNo:
ret

;   Задержка

LCD_Delay:
ldi   R16, SPEED                  ; Задержка на несколько тактов. Для того чтобы дисплей
L_loop:
dec   R16                        ; Успевал обрабатывать данные
brne  L_loop
ret
Думал, что проблема может быть в параметре SPEED от которого зависит задержка в функции DATA_WR. Пробовал увеличивать параметр SPEED до 30 в отличае от рекомендованных 14 на 16 МГц - никакого эффекта.
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
28.07.2013, 11:22
Ответы с готовыми решениями:

ATMega8. Вывод данных с UART на LCD дисплей HD44780
Помогите разобраться с приемом данных с UART и выводом их на LCD-дисплей ...многое перепробовал, но...

Инициализация lcd на HD44780
Здравствуйте! Пытаюсь освоить lcd на HD44780. Понимаю, что есть много уже готовых библиотек, я их...

Мигающий текст на LCD HD44780
Всем привет! А как проще всего сделать часть текста выводимого на LCD типа HD44780 мигающим? Именно...

Библиотерка LCD на контроллере HD44780
Для работы на си с данным дисплеем в winAVR есть библиотека &quot;lcd_lib&quot;. Возьмем к примеру функцию...

Дисплей HD44780 и Atmega16
Написал код для вывода текста на дисплей HD44780 через мегу16 и все работало и строки выводил пока...

6
Гарнист
0 / 0 / 0
Регистрация: 22.01.2010
Сообщений: 3,496
28.07.2013, 11:58 2
А что за странное чтение готовности? Почему значение считывается при неактивном E? Да ещё спустя некоторое время?
0
wypuk
0 / 0 / 0
Регистрация: 23.05.2010
Сообщений: 4
28.07.2013, 13:08 3
Цитата Сообщение от Гарнист
А что за странное чтение готовности? Почему значение считывается при неактивном E? Да ещё спустя некоторое время?
Да, я тут поменял немного в коде DY HOTT-а, т.к. посчитал что там ошибка.
Покрайней мере в статье про LCD написано:
Ожидание готовности, чтение флага занятости.
1.Порт данных на вход с подтяжкой (DDR=0, PORT=1)
2.RS=0 (команда)
3.RW=1 (чтение)
4.E=1 (Готовьсь!!!)
5.Пауза (14 тактов процессора на 8МГЦ хватало)
6.Е=0 (Пли!)
7.Читаем из порта. Если бит 7 (Busy flag) установлен, то повторяем все заново, пока не сбросится.
Т.е. чтение флага занятости происходит после спада на выводе "Е"
А в его коде по сути был написан другой алгоритм:
Код
BusyWoyt:   CLI                  ; Ожидание флага занятости контроллера дисплея
RCALL   PortIn         ; Порты на вход

CBI      CMD_PORT,RS      ; Идет Команда!
SBI      CMD_PORT,RW      ; Чтение!

BusyLoop:   SBI      CMD_PORT,E      ; Поднять строб
RCALL   LCD_Delay      ; Подождать

IN      R16,DATA_PIN   ; Считать байт

PUSH   R16            ; Сохранить его в стек. Дело в том, что у нас R16 убивается в LCD_Delay

CBI      CMD_PORT,E      ; Бросить строб - первый цикл (старший полубайт)
RCALL   LCD_Delay      ; Подождем маленько

SBI      CMD_PORT,E      ; Поднимем строб
RCALL   LCD_Delay      ; Подождем
CBI      CMD_PORT,E      ; Опустим строб   - нужно для пропуска второго полубайта

RCALL   LCD_Delay      ; Задержка снова

POP      R16            ; А теперь достаем сныканый байт - в нем наш флаг. Может быть.

ANDI   R16,0x80      ; Продавливаем по маске. Есть флаг?
BRNE   BusyLoop      ; Если нет, то переход

BusyNo:      SEI                  ; Разрешаем прерывания.
RET
А в коде реализовано так: как видно шаг 6 и 7 местами поменяны
Ожидание готовности, чтение флага занятости.
1.Порт данных на вход с подтяжкой (DDR=0, PORT=1)
2.RS=0 (команда)
3.RW=1 (чтение)
4.E=1 (Готовьсь!!!)
5.Пауза (14 тактов процессора на 8МГЦ хватало)
7.Читаем из порта. Если бит 7 (Busy flag) установлен, то повторяем все заново, пока не сбросится.
6.Е=0 (Пли!)
8.Пауза (14 тактов процессора на 8МГЦ хватало)
0
wypuk
0 / 0 / 0
Регистрация: 23.05.2010
Сообщений: 4
28.07.2013, 13:56 4
Да, действительно - все дело было в цикле чтения флага занятости, вернул все как в исходнике и стало нормально без косяков выводиться!
Значит опечатка в самой статье про LCD
0
Гарнист
0 / 0 / 0
Регистрация: 22.01.2010
Сообщений: 3,496
28.07.2013, 18:47 5
Читайте даташит, а не статьи. Чтение надо производить при активном уровне сигнала.
А Хальту надо в мыл написать, пусть статью правит!
0
DY HOTT
0 / 0 / 0
Регистрация: 22.01.2010
Сообщений: 4,000
28.07.2013, 19:05 6
Будет время поправлю. Хотя я глюков не замечал. Видимо зависит от дисплея у них немного тайминги отличаются.
0
YTYOUT
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
28.07.2013, 20:14 7
Как-то я делал Woyt проще

Код
;***************************************
;-  Woyt BS
;***************************************
Woyt_BS:   ;/ Установка режима   чтения BS
cbi      LCD_Port,LCD_E      ;" Записываем данные в LCD
cbi      LCD_CtrlDDR,MsbOne
ldi      temp,1<<LCD_BUSY|1<<LCD_RW|0<<LCD_RS
outr   LCD_PORT,temp
nop                     ;/ Для частоты 18.432 Мгц нужно не менее
nop
nop                     ;/ (3-х) команд NOP !!
nop
sbi      LCD_PORT,LCD_E      ; Установить (Е )
nop
nop
BS_WAIT:
sbic   PINB,LCD_BUSY      ; Цикл проверки BS
rjmp   BS_WAIT
sbi      LCD_CtrlDDR,MsbOne   ;+ ПортB переключаем на выход
ret
0
28.07.2013, 20:14
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.07.2013, 20:14

Вывод на LCD HD44780 HEX кода
Доброго времени суток, господа. Прошу Вашей помощи в решение одной проблемы. Имею UHF RFID...

Не работает дисплей на базе HD44780
Попался мне в руки 4x20 дисплей, HD44780. Использовал Atmega164P и кварц на 8MHz. Подключение...

Проблема с подключением lcd WD-C2002T (HD44780 + HD44100)
Имеется atmega8 и lcd WD-C2002T, даташита так и не нашел, единственное что есть...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru