Сел я и дописал свою библиотеку для LCD на базе HD44780.
Как она работает я тут расписывать не буду — код весьма плотно фарширован комментариями. Тем более я уже рассказывал как работать с этим дисплеем Поэтому, думаю, разберетесь. Если будут вопросы, то обращайтесь. Тут же я расскажу как ей пользоваться.
Состав
Библиотека состоит из двух файлов LCD.asm и LCD_macro.inc для подключения по 8ми битной шине и LCD4.asm и LCD4_macro.inc для подключения по четырех битной шине данных. Используете тот вариант, по которому у вас подключен дисплей.
- Файл LCD.asm содержит все основные настройки портов и, собственно, код.
- LCD_macro.inc содержит макросы для работы с дисплеем. И используется для работы с библиотекой.
Порт данных использует биты 7…4 любого порта на 4 битном подключении, или весь порт целиком на 8ми разрядном
Порт управления использует 3 любых бита любого порта. Главное, чтобы они были на одном порту. Впрочем код можно и чуток подправить :)
Подключение библиотеки в код.
Где нибудь в начале программы, там где обычно определяют макросы, добавляете строчку
1 | .include "LCD4_macro.inc" |
А в конце кода, там где все процедуры, добавляете
1 | .include "LCD4.asm" |
Разумеется файл должен быть в папке проекта, иначе компилятор его не найдет.
Настройка
В файле LCD.asm есть раздел LCD_Define
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ;=========== LCD Define ==================================== .equ DATA_PORT = PORTB ; LCD Порт данных .equ DATA_PIN = PINB .equ DATA_DDR = DDRB .equ CMD_PORT = PORTA ; LCD Порт управления .equ CMD_PIN = PINA .equ CMD_DDR = DDRA .equ E = 0 ; Бит строба .equ RW = 1 ; Бит чтения/записи .equ RS = 2 ; Бит команда/Данные .equ SPEED = 14 ; 14 для XTAL=16MHz, 10 для XTAL=8MHz, ; 6 для XTAL=4MHz, 5 для XTAL<4MHz |
Порт данных и порт управления указывай те, которые у тебя используются. У меня вот это В и А. Также не забудь указать к каким битам подключены линии управления.
Параметр SPEED задается в зависимости от скорости кристалла. Больше можно, меньше нет. Можно поставить 14 и не парится. Но некрасиво :)
В файле LCD_macro.inc нужно найти блок настроек дисплея и выставить там нужные биты. Выглядит это так:
1 2 3 4 5 6 7 8 9 10 11 12 13 | .MACRO INIT_LCD ; Инициализация LCD RCALL InitHW ; Настроить контрольный порт RCALL LCD_DELAY ; Подождать WR_CMD (1<<LCD_F)|(0<<LCD_F_8B) ; Выдать функцию смены разрядности. WR_CMD (1<<LCD_F)|(0<<LCD_F_8B)|(1<<LCD_F_2L) ; Дважды. ; Так как по дефолту шина 8 бит и нельзя передать сразу вторую половину байта. WR_CMD (1<<LCD_CLR) ;0x01 WR_CMD (1<<LCD_ENTRY_MODE)|(1<<LCD_ENTRY_INC) ;0x06 WR_CMD (1<<LCD_ON)|(1<<LCD_ON_DISPLAY)|(0<<LCD_ON_CURSOR)|(0<<LCD_ON_BLINK) ;0x0C WR_CMD (1<<LCD_HOME) .ENDM |
Перечень опций, сгруппированных по типу приведен там чуть выше. Обращу внимание на то, что инициализация 4х разрядной шины идет ДВА РАЗА. Первый раз мы говорим контроллеру, что у нас шина 4 разрядная. Но при этом мы не можем сказать второй полубайт слова управления. Поэтому, когда контроллер перейдет на 4х разрядный режим, выдаем нашу посылку снова, на этот раз вторая тетрада нормально пройдет.
Использование
Перед первым использованием надо сделать инициализацию индикатора. Делается это макросом
1 | INIT_LCD |
При этом задаются параметры дисплея, указанные в разделе инициализации.
Запись байта в дисплей осуществляется макросами
1 2 | WR_CMD xx WR_DATA xx |
Где вместо хх вписываем наш байт.
Если надо выдать на экран, что либо программно сгенеренное, в таком случае используется прямой вызов процедуры. Байт передается через регистр R17.
1 2 | RCALL CMD_WR RCALL DATA_WR |
Чтение осуществляется аналогичным образом:
1 2 | RD_CMD RD_DATA |
или
1 2 | RCALL CMD_RD RCALL DATA_RD |
В данном случае макрос и процедура ничем не отличаются. Сделано просто для унификации. Считанный байт будет в регистре R17
Установка координаты курсора осуществляется макросом
LCD_COORD X,Y
Где X и Y координаты по горизонтали, и вертикали в знакоместах.
Сдвиг курсора или экрана осуществляется макросом SHIFT xx, где вместо xx подставляются нужные аргументы
1 2 3 4 | SHIFT SCR_L ; сдвиг экрана влево SHIFT SCR_К ; сдвиг экрана вправо SHIFT CUR_L ; сдвиг курсора влево SHIFT CUR_R ; сдвиг курсора вправо |
Макрос LCDCLR делает полную очистку видеопамяти.
Макрос WR_CGADR xx позволяет установить указатель в область памяти знакогенератора, чтобы можно было записать свой символ. Если затем начать слать данные, то они будут записаны в ячейки знакогенератора.
Макрос RD_CGADR xx позволяет установить указатель в область памяти знакогенератора,чтобы можно было считать байт из знакогенератора.
Макрос WR_DDADR xx устанавливает указатель на видео память. С этого момента все данные попадают на экран.
Для примера попробуем создать зиг руну, ранее упомянутую в записи про описании контроллера
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | INIT_LCD ; Инициализируем WR_CGADR 0 ; Указатель на начало знакогенератора. WR_DATA 0b00000001 ; Запись данных нового знака WR_DATA 0b00000010 WR_DATA 0b00000100 WR_DATA 0b00011111 WR_DATA 0b00000010 WR_DATA 0b00000100 WR_DATA 0b00001000 WR_DDADR 0 ; Указатель на начало видео памяти (ячейка с координатми 0,0) WR_DATA 0 ; У новоиспеченного символа код 0 напечатем его |
Системные требования и ограничения
Используется система команда ATMega на некоторых ATTiny может начать ругаться. Придется править. Занимает 474 байта кода в максимальном исполнении (4 битная шина). На 8ми битной шине будет байт на 100 короче. Если выкинуть процедуру чтения, то будет еще короче.
Процедура активно использует регистр R16 и R17, поэтому их содержимое меняется непредсказуемым образом!!! Так что либо учитывайте это, либо сохраняйте заранее эти регистры.
Вот так вот, если что будет нового то выпущу версию 2. Пользуйтесь.





надеюсь тебе помог тот код, что тебе кидал?
Ага, убедился в том, что у меня все верно. Косяк быд в процедуре ожидания флага занятости.
; Так как по дефолту шина 8 бит и нельзя передать сразу вторую половину байта. — эммм… туплю? ;-)
По дефолту контроллер ждет данные по 8ми битной шине. А У нас подключено только по 4х битной, поэтому младший полубайт мы передать не сможем и контроллер захавает его нулями (т.к. выводы висят). Но старший то пройдет и переключит шину в 4бита. И следующая посылка опять выставит 4бита (чтобы не переопределять) и в догонку выставит второй полубайт.
Ага.. точно, я туплю. =)
только что вспомнил случайно совершенно…
когда-то мне попадалася мега номер 160(?) вроде.
мельком попадалась, поработать с ней не удалось. знакомый камрад говорил, что внутри неё уже встроен управлятель для жк-дисплейчиков.
есть ли такие на самом деле или мне это померещилося?
http://atmel.com/dyn/products/devices.asp?family_id=607#1583
спасиб за инфу )
Есть целое подсемейство AVR LCD которые содержат встроенный контроллер LCD, но не такой, а для прямого управления стекляхой.
если б они её сразу со «стекляхой» поставлялися (
и по общей цене, как обычные (надеюся)…
Управление LCD-дисплеем HD44780 по одному проводу
Автор Noureddine Benabadji
18.03.2008 г.
LCD-дисплеи с контроллером HD44780 являются пожалуй одними из самых популярных символьных дисплеев для встраиваемых систем. Единственным их недостатком можно считать необходимость задействования для управления дисплеем шести I/O-линий микроконтроллера в 4-разрядном режиме либо одиннадцати I/O-линий в 8-разрядном режиме. Для сокращения числа управляющих линий можно использовать преобразователи последовательного кода в параллельный на основе стандартной логики. Однако, управлять HD44780-совместимыми LCD-дисплеями можно даже по одной линии. Такую функцию гораздо удобнее возложить не на микросхемы жёсткой логики, а на программируемый микроконтроллер, сократив, таким образом, стоимость и занимаемую схемой на печатной плате площадь. Этим целям в полной мере удовлетворяют микроконтроллеры Microchip серии PIC10F в миниатюрном корпусе SOT23–6.
Схемотехническое решение, показанное на рисунке, может оказаться полезным для многих встраиваемых систем с ограниченным числом выводов, потому как способно управлять HD44780-совместимыми LCD-дисплеями посредством однопроводной линии передачи данных, задействуя простой асинхронный RS232 протокол на скорости 9600baud. В схеме применён PIC10F202, но подойдёт любой микроконтроллер из этого семейства, потому что хорошо оптимизированный программный код (прошивка 1) состоит из всего лишь 256 слов. Увеличить скорость выше 9600baud не представляется возможным, так как PIC10F202 содержит внутренний RC-генератор с точностью 1%, а LCD-дисплей требует задержку длиной 1.6ms для некоторых инструкций, таких как «очистка дисплея». Программный код представлен в виде исходников с комментариями для LCD232 модуля; основная программа состоит из дисплейной заставки на 2 секунды и дальнейшего бесконечного цикла для ожидания 1 байта команды, максимум 16 байт данных и нуля ASCII. В тестовых целях сопряжения дисплея с внешней встраиваемой PIC-системой можно воспользоваться простой прошивкой на ассемблере (прошивка 2).
DI HALT, а ты в ISIS Proteus делал управление LCD? Я попробовал с теми библиотеками, которые ты сделал — не пошло. Попробовал пример из книжки на C сделать по выводу инфы на LCD, тоже безрезультатно. Использовал компоненты LM016L, LM017L. как на 4-х проводах, так и на 8.
Собрал вчера на макетке на 8 проводах — все работает. Сделал все тоже самое в протеусе, используя эту же прошивку — не идет…
Что пишет Протеус? У меня тож не идет,пишет …. is outside of ROM space.
DI HALT, и еще вопрос. В библиотеке LCD.asm есть команда LCD_PORT_IN. Не могу понять, откуда она взялась и как копилятор ее понимает, ведь ни функций, ни макросов, ни определений, ни меток нет с таким названием, и уж тем более в системе команд такой нету… При этой команде программа перепрыгивает на метку PortIn, но почему? Растолкуй, пожалуйста.
Макрос это. Он есть в разделе LCD_macro.inc (либо в LCD4_macro.inc для четырехпроводной версии.)
Уважаемый DI HALT,
помогите п-ста новичку с решением проблемы с ЖКИ.
Купил WH0802 и решил его первоначально проверить. Подсветка работает нормально, а вот с контрастностью непонятки: в какое бы положение не встал движок переменного резистора, регулирующего контрастность, «загорается» только верхний ряд. Нижний ни при каких обстоятельствах не контрастирует.
Перепробовал много кода — ничего не появляется.
Заранее благодарен.
У тебя проблема не в контрасте, а в неправильной инициализации. Активен только верхний ряд, т.е. ты заинциализировал его на однорядный дисплей.
Спасибо за ответ, попробую еще раз все проверить.
Однако я был уверен в том, что после отключения питания LCD, вся информация инициализации стирается в модуле. Это не так?
Стирается. При каждом включении питания его надо заново инитить.
ОК. То есть если я его отключил от питания и от контроллера,а потом в отключенном состоянии запитал, и у меня все равно контрастирует только один ряд — это не проблема, а проблема с инициализацией? Я справшиваю потому, что, например, завтра-послезавтра могу пойти в магазин и обменять (недавно там купил). Если же это не признак брака, а мое неумение составить программу — то, понятно, в моем распоряжении целая вечность для исправления ошибок.
Это не брак. Это неправильная инициализация. Ищи ошибку в коде :)
попробуй дважды послать инициализирующую последовательность. Ты же подключил его по 4х проводной шине? В таком случае скорей всего у тебя не доходит до контроллера, что он двухрядный. Нужно дважды повторить.
Нет, по 8-ми проводной.
Мне представляется, что я запутался во фьюзах (точнее я их не трогал), а кварц на плате, которая мне попалась (с контроллером) на 3,6864. Для формирования задержки я использую delay_ms(). может в этом дело? Временные периоды не соответствуют требуемым?
Вполне возможно. Если фузы не трогал, то тактовая частота (у контроллеров Мега и Тини) задается по дефолту от внутренней РС цепочки и может быть от 1 до 8 мгц в зависимости от типа МК.
Можешь увеличить временные интервалы раз так в 10. Чтобы наверняка.
Простите, но у меня никак не получается. Теперь я выяснил, что на выводах LCD 11,12,13,14 всегда есть +3,76В. Даже если я принудительно устанавливаю 0 на всех выводах, то именно на этих всегда 1. Остальные же четыре линии устанавливаются в соответствии с командами.
Нашел ошибку.
У меня в контроллере был установлен бит JTAGEN=0 (а порт для LCD — PORTF), а я подумал, что 0 — это снят. А оказывается нет. Убрал его и все заработало.
Спасибо большое.
а схему макетки, простите за наглость, не выложите?
Здравствуйте.
Пробую воспользоваться библиотекой,но я новичок в этом деле и не всё понимаю.
Подскажите что за значение @0 ?
А это из макроязыка — параметры макроподстановки. Почитай у меня про макросассемблер.
http://easyelectronics.ru/avr-uchebnyj-kurs-makroassembler.html
Большое спасибо за ссылку.
Разобрался с библиотекой.Целый день промучился.
Косяк оказался в протеусе,как выше писали.
В железе всё работает.
А для чего вот этот макрос LCD_COORD X,Y ?
Какие он координаты задаёт ? У каждого знакоместа есть ведь свой адрес.
Вот этот адрес он и вычисляет и переводит туда курсор. Просто удобнйе же мыслить категориеей столбец:строка чем линейным адресным пространством.
Указал номер строки, номер столбца и символ высветился где указано.
Очень удобно.
Пытаюсь через AVR Studio откомпилировать на ATmega48 …. закрадывается вопрос … энто вообще возможно ? (порты я поменял, но зато потом начинается кишмар, макросы например отказывается видеть видимо принципиально)
Должно работать. У меня на мега8 работало. Видимо ты какие то файлы забыл.
да, действительно, попробовал с начала, всё работает :)
Решил заюзать LCD от nokia 1100 65×96 (чип PCF8814) и написать свою тру-библиотеку на асме. Для протеуса не нашел библиотечки, решил потренироваться на дисплее от nokia 3310 48×84, а потом чуток код подправить для 1100. Вот решил я биткарты для каждого символа забить в EEPROM. Вместе с русскими буквами вышло 810 байт для шрифта 8×5. Да вот засада: я под мегу8 писал, т.к. она в наличии у меня есть, а у нее только 512 байт EEPROM… Пришлось для моделирования взять мегу 32, а это и корпус крупнее и денег стоит больше. Может есть какой-то альтернативный выход? Кто как справлялся с нехваткой EEPROM ?
А зачем ЭТО писать в EEPROM? Пиши это в Flash ROM она же не меняется никогда.
Согласен. Уже так и сделал (гребаное выравнивание по размеру слова!!!). Но я точно знаю, что мне флеша не хватит, чтобы его еще на такие вещи тратить…
У меня идея была сжать эти битмэпы и сжатые данные записать в eeprom, а при инициализации не сложным алгоритмом распаковки все это дело в ОЗУ распаковать, но пока не нашел алгоритм, который можно было бы достаточно компактно реализовать в МК… И, честно говоря, уже теряю надежду на эту задумку… Пока простой ответ нашел только такой: часть битмепов записасть в eeprom (ну например для редкоиспользуемых символов русского алфавита), а остальную часть пихнуть во флеш… пока думаю это оптимальный вариант.
Повесь внешнюю ЕЕПРОММ Флешку со шрифтами. На и2с шину.
Да! Возьми мегу 168 у ней при полном совпадении по ногам памяти вдвое больше. А разница в цене небольшая.
О, точно! А я смотрю — у Евстифеева нет в сводной таблице 168 меги… ДА, надо в нете сразу смотреть на сайте атмела все МК AVR…
Так свежак же! Не больше года назад появилась. А еще есть 328. То же самое, но на 32 метра.
328 это как 32, только ног по-меньше. про нее только на atmel.com написано, на русскоязычном сайте еще нет в списках
Хм.. посмотрел на сайте атмела — куча всяких микрух: Data Flash, Flash, EEPROM, Последовательный EEPROM, Параллельный EEPROM. Есть даже какой-то Конфигурационный EEPROM. Я аж растерялся…
Не планируется ли статейка о подключении к МК таких типов внешней памяти и методы работы с ней?
Эх… планируется :))) давно хочу про i2c шину написать. Но все как то влом, тема больно жирная :) Но видимо возьмусь таки.
Класс! Буду ждать
Неплохая прога для перегона битовой картинки в массив байтов
Я например юзал для создания биткарт символов шрифта для LCD дисплея
Во! Рулез! Спасибо! давно искал что то подобное.
Все в массы!!!
Я уже пару шрифтов 6×8 себе сделал. Один OEM (CP866), а второй ANSI (CP-1251)
Вот думаю может в своей тру библиотеке сделать поддержку больших шрифтов типа 10х16… Смотрятся куда красивее чем 6×8 :-)
Здравствуйте. Нужна помощь. Полностью сделал всё как описано, но разве что на LCD HY-1602H двухстрочный 2х16, МК — АТмега8515, порт А на дата шину LCD, порт Е на шину управления. Проблема в чём — при запуске всего этого добра все верхние сегменты полностью зажжены, нижняя строка не пашет. Я, всего лишь, для начала хочу вывести зиг руну как на примере, но ничего. Бьюсь уже достаточно времени скоро материться буду на этот LCD. Подскажите что-нибудь, пожалуйста.
Сразу видно что у тебя инициализация не прошла. Некоторые LCD требуют ее два раза проходить.
По какому интерфейсу подключил? 8 или 4 провода?
на 8 проводов
самое интересное то, что это всё происходит при подключении одного LCD, подключаю потом сразу другой такой же LCD к этой же схеме, а он ничего не выводит вообще…
Разные дисплеи, немножко разные контроллеры. Скорей всего придется поиграться с задержками временными. Сделай их чуток побольше. У меня там есть в коде LCD_Delay или как то так. Сделай ее дважды везде где найдешь. Ну и проверь не перепутал ли чего, может у них цоколевка отличается.
Спасибо за отклик, подумаю ещё… может чего и придумаю. Ещё раз спасибо.
Здравствуйте, у меня возникли проблемы при записи данных в дисплей: они туда не записываются. В результате инициализации включается две строки, и всё. Пытался включить курсор не получилось. Использовал два разных LCD, результат одинаковый.
Использовал предложенную здесь библиотеку, то же самое.
без инициализации вкл. только 1 строка, а после две, значит команды передаются правильно, тогда почему курсор не включается?
Пробовал не проверять флаг занятости, а делать задержку, результат такой же
подключал LCD: wh1202 и DV-16252
МК ATmega16
Попробуй поиграть с выдержками. Некоторые дисплеи тупые, им инициализацию два три раза слать надо.
По какой схеме подключал? полной или половинчатой?
а чем различаются символьные и графические десплеи? Уних разная система команд?
Да. Само собой.
Пытаюсь прикрутить WH0802A он аналог HD44780 на Tiny2313
И неполучается :(((
Вот моя комутация:
PD0=E
PD1=R/W
PD2=RS
PB0=DB0
PB1=DB1
PB2=DB2
PB3=DB3
В прошивку внесены соответсвенно изменения:
***************lcd4.asm********************
.equ DATA_PORT = PORTB ; LCD Data Port
.equ DATA_PIN = PINB
.equ DATA_DDR = DDRB
.equ CMD_PORT = PORTD ; LCD Control Port
.equ CMD_PIN = PIND
.equ CMD_DDR = DDRD
.equ E = 0
.equ RW = 1
.equ RS = 2
.equ SPEED = 14
*****************************************************
Даже инициализацию повторил дважды (вдруг с ервого раза не раздуплиться)
***********************Сама программа****************
.include»tn2313def.inc»
.include»lcd4_macro.inc»
.include»lcd4.asm»
INIT_LCD
INIT_LCD
WR_CGADR 0
WR_DATA 0b00000001
WR_DATA 0b00000010
WR_DATA 0b00000100
WR_DATA 0b00011111
WR_DATA 0b00000010
WR_DATA 0b00000100
WR_DATA 0b00001000
WR_DDADR 0
WR_DATA 0
*****************************************************
При прошивке фусы по дефолту, компиллер не ругается, контроллер шьется без ошибок и замечаний.
При включении без признаков жизни. Попрежнему горит только верхний ряд (при управлении контрасностью). Что сделал не так? Бьюсь третий день -понять немогу. Прошу помощи!
Странно. У меня тоже именно WH0802A и работает. INIT_LCD дважды повторять не надо. Это бессмысленно, лучше попробуй изменить этот макрос, дважды подав команду перехода на четырехпроводный режим.
Попробуй добавить строку:
WR_CMD (1<<LCD_F)|(0<<LCD_F_8B)
Еще один раз. По всем признакам дисплей у тебя не может понять, что мы с ним общаемся по 4м проводам. И поиграй параметром SPEED
Разве при использовнии четырехбитной шины не старшую тетраду нужно использовать?
DB4-PB4
DB5-PB5
DB6-PB6
DB7-PB7
наверное так должно быть у тебя.
«Порт данных и порт данных указывай те…»
Очепятка :)
Доброго времени суток!
Вроде делаю все по статье, а не получается на макете. LCD не инициализируется.
У меня atmega8535, юзаю потр C для управления и D для данных. Решил попробовать на эмуляторе в аврстудио + hapsim — в логе повалило:
AVR Simulator: Stack Overflow at 0×0028
AVR Simulator: Stack Overflow at 0×0000
Думал трабла с аврстудио, поставил на другом компе — тожесамое.
Вот конфиг:
=========== LCD Define =======================
.equ DATA_PORT = PORTD ; LCD Data Port
.equ DATA_PIN = PIND
.equ DATA_DDR = DDRD
.equ CMD_PORT = PORTC ; LCD Control Port
.equ CMD_PIN = PINC
.equ CMD_DDR = DDRC
.equ E = 2
.equ RW = 1
.equ RS = 0
.equ SPEED = 14
Вот сам файл:
.device atmega8535
.include «D:\AVR\PROJ\LCD123\m8535def.inc»
.include «D:\AVR\LCD\WH\LCD4_macro.inc»
; INIT_LCD
INIT_LCD ; Инициализируем
WR_CGADR 0 ; Указатель на начало знакогенератора.
WR_DATA 0b00000001 ; Запись данных нового знака
WR_DATA 0b00000010
WR_DATA 0b00000100
WR_DATA 0b00011111
WR_DATA 0b00000010
WR_DATA 0b00000100
WR_DATA 0b00001000
WR_DDADR 0 ; Указатель на начало видео памяти (ячейка с координатми 0,0)
WR_DATA 0 ; У новоиспеченного символа код 0 напечатем его
.include «D:\AVR\LCD\WH\LCD4.asm»
Судя по
AVR Simulator: Stack Overflow at 0×0028
AVR Simulator: Stack Overflow at 0×0000
Косяк не в моем коде, а в твоем. Похоже ты где то забыл стек инициализировать или сорвал его ненароком. Так бывает :)
А куда посмотреть, чтоб понять где набочил?
Запусти в студии на эмуляцию и пошагово протрассируй. Скорей всего у тебя нет вот этого в начале:
OUTI SPL,low(RAMEND)
OUTI SPH,High(RAMEND)
Ну, а дальше, если этого не вписать, у тебя будет краш на первом же вызовае RCALL или RET
Да, на первом шаге переполнение стека повалило.
вставил эти 2 строки перед INIT_LCD при компиляции вывалило:
D:\AVR\PROJ\LCD123\LCD123.asm(2): error: OUTI: Unknown instruction or macro
D:\AVR\PROJ\LCD123\LCD123.asm(2): error: SPL: Unknown instruction or macro
D:\AVR\PROJ\LCD123\LCD123.asm(2): error: syntax error, unexpected ‘,’
Может я чтото еще пропустил?
Ну то и значит, что OUTI это макрос который ты не описал. Разберись вначале с макроязыком и средствами ассемблера. А потом уже пробуй чужие либы подключать, а то надолго застрянешь на детских ошибках.
.MACRO OUTI
LDI R16,@1
OUT @0,R16
.ENDMACRO
Спасибо! Уже нашел этот макрос в предидущих статьях.
[quote]Запись байта в дисплей осуществляется макросами1
2 WR_CMD xx
WR_DATA xx
Где вместо хх вписываем наш байт.[/quote]
в каком формате xx подставлять? 00010 00100 или два числа в 16-тиричной?
Один байт, в любой удобной форме. Компилятору без разницы.
SHIFT SCR_L ; сдвиг экрана влево
SHIFT SCR_К ; сдвиг экрана вправо
SHIFT CUR_L ; сдвиг курсора влево
SHIFT CUR_R ; сдвиг курсора вправо
Опечатку нашел вместо SCR_К надо CSK_R :)
Ошибся SCR_R
“Порт данных и порт данных указывай те…”
Опечатка же)
замечание:
все команды, начиная с инициализации, у вас реализованы через функцию CMD_WR, а она в свою очередь, использует BusyWait!
В даташите на дисплей особое внимание уделено тому, что при инициализации флаг занятости не проверяют, но требуется выждать не менее 40 мкс после каждой команды.
А так даже протеус глючит…
Хм. Тем не менее уже 4ре разных дисплея отнеслись к этому адекватно и работают.
возможно, это и необязательное условие. В железе еще не проверял, у меня МЭЛТ.
Но протеус выдает предупреждение «попытка чтения после записи одного полубайта»…
А где это в даташите? Вчера смотрел доку на HD44780 ничего подобного не увидел.
http://www.sparkfun.com/datasheets/LCD/HD44780.pdf
страница 46.
«BF cannot be checked before this instruction.»
В Procyon AVRlib (откуда я передрал инициализацию дисплея) при инициализации тоже используется тот же самый BusyWait на ожидании флага.
Привет!
У меня вопрос — ежели я использую только часть функций, находящихся в инклюд-файле — остается ли «лишний» код за бортом при компилляции?
Нет, его надо закомментить.
Скачал уже давно твою библиотеку для ЛСД и юзал её не мог нарадоваться, однако сегодня благодаря ей любимой бился головой об стенку 2 дня пока не откопал багу. думаю будет всем полезно иметь ввиду мой горький опыт.
При срабатывании прерывания от АЦП, запрещаю все прерывания и вытаскиваю результат и разрешаю прерывания. При срабатывании прерывания от таймера (3Гц) запрещаю все прерывания, и вывожу значение АЦП на экран. На экран вылазит лажа, и близко не похожая на то, что должно быть (сразу оговорюсь, речь идёт о переменном напряжении).
Запускаю отладчик , комментирую все экранные функции(т.к. там есть ожидание ответа от дисплею, а оно меня кумарит да и времени много занимает) и всё работает как часы.
Решение оказалось смешным до слёз, в библиотеках есть функции которые сначала запрещают, а потом разрешают прерывания, то есть посредине обработки прерывания от таймера вдруг включались все прерывания и начинался мегаприкол на экране.
не знаю как кому, а я рекомендовал бы перед использование библиотеки с прерываниями комментировать SEI в коде библиотек
Это ошибка планирования архитектуры программы. Такие процедуры как моя лсдшка в прерываниях не гоняют!!! В прерывании ты должен был поставить какой нибудь флажок, мол надо обновить дисплей, а главном цикле по этому флажку прогнать библиотечную функцию.
Ну или на примере моей любимой RTOS в прерывании пихнуть задачу обновления дисплея в очередь и выйти.
Короче, прерывания не для того, чтобы туда что либо тяжелей десятка строк пихали, да еще и с кучей вызовов и ожиданием готовности.
Наверное логично, я как раз от разработки программы перешёл к её оптимизации, попробую поменять структуру. Хотя в любом случае, большинство тут учится, и меня ,например, на этапе мучения с прерываниями было абсолютно пофигу в какой части программы они обрабатывются, хотя я даже подумать не мог что из-за этого грабли могут быть такие большие )
так что пусть это будет мини хелпом для тех у кого есть перспектива попасть на эти грабли.
День добрый.вопрос новичка.неподскажите как можно организовать меню
управления чтобы можнобыло как блакнот листать.знаю что это делается
спомощью счотчика а представить немогу.немоглибы показать под
SiSy-AVR здесь загоняется немного подругому.
заране премного благодарен.
Что такое SiSy AVR?
Это тоже самое как AVR Studio но более продвинута для ЧАЙНИКОВ
Я покупал пакет с учебниками програматором и другими прелестями.
просто я занимаюсь ремонтом електроники а мир нестоит на месте
вот решил заняться самообразованием.линк моего пакета
http://shop.myavr.de/Komplettpakete/myAVR%20Einsteigerset%20MK2%20USB%20PLUS.htm?sp=article.sp.php&artID=45
Как правильно подключать екран при 4 битном подключении свободние 4 оставлять в воздухе?
А то ща имею трабл на 8 пашет гуд а при подключении на 4 ни в какую… либо пустой екран либо крякозяблики…
Да. пусть висят
Инициализация Winstar WH1602A-YGH-CTK# убил два дня на то чтоб разобраться как инициализируеться даний ЛСД поетому мож кому пригодиться :)
инициализация для 4 бит используя либу автора статьи:
WR_CMD 0b00110011 ; Важно!!!
WR_CMD 0b00110010 ; Вместо WR_CMD (1<<LCD_F)|(0<<LCD_F_8B) !!!
WR_CMD (1<<LCD_F)|(0<<LCD_F_8B)|(1<<LCD_F_2L)
WR_CMD (1<<LCD_CLR)
WR_CMD (1<<LCD_ENTRY_MODE)|(1<<LCD_ENTRY_INC)
WR_CMD (1<<LCD_ON)|(1<<LCD_ON_DISPLAY)|(0<<LCD_ON_CURSOR)|(0<<LCD_ON_BLINK)
WR_CMD (1<<LCD_HOME)
При переходе на 8 битний режим перед 8 битной инициализацией по мануалу нада добавить 3 команди WR_CMD (1<<LCD_F)|(1<<LCD_F_8B)
Хотя исходя из практики можна пропустить…
У меня такой же дисплей, я его инициализирую так:
RCALL InitHW ; Настроить контрольный порт RCALL LCD_DELAY ; Подождать WR_CMD (1<<LCD_F)|(0<<LCD_F_8B) ; Выдать функции в порт. Команда инициализации адресации ДВА РАЗА!!! WR_CMD (1<<LCD_F)|(0<<LCD_F_8B)|(1<<LCD_F_2L) ; Так как на 4 байтах нельзя передать сразу второй байт WR_CMD (1<<LCD_CLR) ;0x01 WR_CMD (1<<LCD_ENTRY_MODE)|(1<<LCD_ENTRY_INC) ;0x06 WR_CMD (1<<LCD_ON)|(1<<LCD_ON_DISPLAY)|(0<<LCD_ON_CURSOR)|(0<<LCD_ON_BLINK) ;0x0C WR_CMD (1<<LCD_HOME)Хз в моём случае такое не проходило хз почему… (для проверки пробовал и так и сяк…)
Вот онлайн эмулятор LCD кому интересно поэкспериментировать =)
http://www.dinceraydin.com/djlcdsim/djlcdsim.html
Ребята помогите, мучаюсь вторую неделю. LCD: WH1602A-YYK-CTK (Winstar), шина 4 бит, использую библиотеки автора, но при инициализации еще добавил строки Name4me:
WR_CMD 0b00110011 ; Важно!!!
WR_CMD 0b00110010 ; Вместо WR_CMD (1<<LCD_F)|(0<<LCD_F_8B) !!!
(без них не работал)
В Протеусе все работает, в железе нет. (Загорается только верхний ряд черных квадратов)Читал\смотрел\разбирал даташиты коментарии других. Судя по всему нужно добавить в начале инициализации задержки или как то по другому инициализировать. Опыта нет,не могу должным образом вклинить в код эти задержки (по даташиту 15 мс,4,1 мс,100мкс), компилятор ругается и прочее…
Вообщем помогите пожалуйста с инициализацией.
Кто нибудь можеть кинуть программу которая у вас точно работает, с использованием библиотек DI HALT, и указанием на каком именно LCD работает. А то закипаю….
Друзья! Простите меня, все заработало. Проблема , как всегда, была в прокладке.
Очень и всеми руками поддерживаю Kefir_Danon о просьбе размещения кода. Я пытаюсь заставить работать шестнадцатизнаковый двухстрочник, и чтоб он огнем горел! Я его скоро не паяльником, а молотком прибивать к АВР-у буду, чтобы не вредничал.Или на почту мне скиньте плиз исходник попроще. Дальше сам разберусь. Для полного подключения.
Мыло: april_26(собачка)ukr.net Спасибо заранее и с Новым Годом!
DI HALT, очередной респект.
Сегодня свинтил ЖК c RoboPICA поиграться. Сзади на нем надпись «JHD 162A» однако интерфейс был такой же. Попробовал твою библиотечку и все получилось. Песня!
april26, а что не понятно?
Простейший вариант:
===========================================================
.include «m8def.inc»
.include «LCD_macro.inc»
.MACRO outi
LDI R16,@1
OUT @0,R16
.ENDMACRO
.ORG INT_VECTORS_SIZE
Reset:
OUTI spl,LOW(RAMEND)
OUTI sph,HIGH(RAMEND)
INIT_LCD
LCDCLR
WR_DATA ‘A’
WR_DATA ‘n’
WR_DATA ‘t’
WR_DATA ‘o’
WR_DATA ‘n’
Loop:
RJMP Loop
.include «LCD.asm»
===========================================================
Сорри за MACRO outi. Лень было причесывать.
А чего бы оно не заработало то :) Дисплей то такой же.
А можно узнать как в ассемблере написать код который бы из шестнадцетиричного числа делал десятичное? Или кинуть простой пример.
Это тебе делить надо или как у меня без делителя
onADC: cli
ldi r16,0b01000000 ; Port, Referenzspannung und Auflösung
out ADMUX,r16
;— Interrupts erlauben —
in r26, ADCL
in r27, ADCH
sbi ADCSRA,6
sei
reti
lcdZahl:
mov r1,r26 ; Zwischenspeicher und Einer-Stelle
mov r4,r27
ldi r17,6
ldi r18,5
ldi r19,2
clr r2
clr r3
hunderte:
ldi r16,100 ; solange die 100 in die Restzahl (r1) passt
cp r1,r16
brlo zehner
sub r1,r16 ; 100 abziehen und
inc r3 ; Hunderter-Stelle erhöhen
rjmp hunderte
zehner:
ldi r16,10 ; wie bei den Hundertern
cp r1,r16
brlo addiren
sub r1,r16
inc r2
rjmp zehner
addiren:
ldi r16,1 ; solange die 100 in die Restzahl (r1) passt
cp r4,r16
brlo ein
sub r4,r16 ; 100 abziehen und
add r1,r17
add r2,r18
add r3,r19
rjmp addiren
ein:
ldi r16,10 ; wie bei den Hundertern
cp r1,r16
brlo zehn
sub r1,r16
inc r2
rjmp ein
zehn:
ldi r16,10 ; wie bei den Hundertern
cp r2,r16
brlo einer
sub r2,r16
inc r3
rjmp zehn
einer: ; der_Rest_sind_die_Einer
ldi r21,0×30 ; 30 hex für Zahl
mov r16,r3
add r16,r21 ; hunderter + 30 hex
rcall lcdData
; ldi r16,’.’
; rcall lcdData
mov r16,r2
add r16,r21 ; zehner + 30 hex
rcall lcdData
mov r16,r1
add r16,r21 ; einer + 30 he
rcall lcdData
ret
;————————————————————————
я то вообще новичок в етом деле.может кто лучше посоветует
Всё отлично работает спасибо!, вот только не могу понять, как мне вывести на дисплей не константу , а с какого нибудь регистра данные, в который я буду класть информацию с UART?????
и что вот это такое: (ниже код) ??? на дисплей ничего не выводится… и без этих строчек всё прекрасно работает:
WR_DATA 0b00000001 ; Запись данных нового знака
WR_DATA 0b00000010
WR_DATA 0b00000100
WR_DATA 0b00011111
WR_DATA 0b00000010
WR_DATA 0b00000100
WR_DATA 0b00001000
Так это, предварительно то идут команды записи в память знакогенератора. Т.е. мы сначала этот символ врисовываем, а потом только отсылаем его наружу.
а как быть с выводом на дисплей информации из регистра????
Всё, с 10-го прочтения разобрался. спасибо!
Уважаемый DI-HALT
Включил Вашу библиотеку в свою тестовую прогу, все работает.
Подскажите пож. как же все таки вывести значение регистра в десятичном виде на экран!
(т.е. не символ с кодом …., а именно этот код!)
Так же нет ли какой подпрограммы или макроса для вывода текстовой строки, что бы не мучатся посимвольно???
П.С. Продолжаю разбираться с ассемблером, пока более или менее понятно, нет ли у Вас статьи по работе с данными типа INT, LONG INT и т.п. Интересует арифметические операции и опрации с сохранением этих данных в памяти. Если есть — ткните носом плиз! -)))
Заранее спасибо!!!
пытался сам написать код для инициализации по даташиту на wh0802a
нифига мой код не заработал.
подключил твою либу, заработало.
захотел сделать без чтения готовности а только с заденржкой, везде поставил по 40мс.
перестало работать.
но стало похоже на то что я писал.
какие задержки выставить чтобы все зафурычило без чтения состояния???
А ХЗ. Вообще 40мс это дофига. Он работает почти как память, так что должно хватить и 1мс. Может что то еще забыл?
да ХЗ
[code]
Вот как переделал LCD4.asm
;=========================================================================================
; Запись команды в дисплей. Код команды в R17
CMD_WR: CLI ; Запрет прерываний
;RCALL BusyWait ; Ждем готовности
ldi Razr1,40
rcall Delay_ms
CBI CMD_PORT,RS ; Идет команда!
RJMP WR_END ; Переход на запись
;-----------------------------------------------------------------------------------------
; Запись данных в дисплей. Код данных в R17
DATA_WR: CLI ; Запрет прерываний
;RCALL BusyWait ; Ждем готовности
ldi Razr1,40
rcall Delay_ms
SBI CMD_PORT,RS ; Идут данные!
WR_END: CBI CMD_PORT,RW ; Запись!
функция Delay_ms:
Delay_ms:
ldi Razr2,32
lp1:
ldi temp,254
lp2:
dec temp
brne lp2
dec Razr2
brne lp1
dec Razr1
brne Delay_ms
reti
[/code]
>reti<
А это что за хуета?
c BusyWait все работает
неправильно я сказал,с задержкой тоже работает но если подключать ногу RW
хочу без нее
Хм, так у тебя только нужный уровень выставить на RW и все. Не оставлять его болтаться в воздухе. Выстави его всегда в WRITE и все.
это значит к земле прижать?
да!!!! по ходу заработало! спасибо!
Доброго времени суток!
Использую Atmega8 и wh0802a дисплей, как я понял он собран на аналоге HD44780 контроллера. Собрал я простую схемку с управлением по 4 пинам. Набросал программку в CodeVisonAVR и построил схему в Proteus но wh0802a поэтому использовал LM016L похожий индикатор.
Итог:
В proteus симуляторе всё работает, а когда зашил код в схему ничего не отображается.
Код:
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.8 Standard
Automatic Program Generator
© Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 23.02.2010
Author : F4CG
Company : F4CG
Comments:
Chip type : ATmega8
Program type : Application
Clock frequency : 3.684400 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 256
*****************************************************/
#include
// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0×12 ;PORTD
#endasm
#include
// Declare your global variables here
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0×00;
DDRB=0×00;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0×00;
DDRC=0×00;
// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTD=0×00;
PORTB=0xFF;
DDRD=0xFF;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0×00;
TCNT0=0×00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0×00;
TCCR1B=0×00;
TCNT1H=0×00;
TCNT1L=0×00;
ICR1H=0×00;
ICR1L=0×00;
OCR1AH=0×00;
OCR1AL=0×00;
OCR1BH=0×00;
OCR1BL=0×00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0×00;
TCCR2=0×00;
TCNT2=0×00;
OCR2=0×00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0×00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0×00;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0×80;
SFIOR=0×00;
// LCD module initialization
lcd_init(8);
while (1)
{
// display the message
if (!PINB.0)
{
// display the message
lcd_gotoxy(0,0);
lcd_putsf(«KEY «);
lcd_gotoxy(0,1);
lcd_putsf(«PUSH_1 «);
} else
{
lcd_gotoxy(0,0);
lcd_putsf(«NO KEY «);
lcd_gotoxy(0,1);
lcd_putsf(«PRESSED «);}
};
}
На LCD видно только немного подсвеченные пустые символы первой строки контраст которых можно регулировать через V0 резистором. (т.е. драйвер управления работает).
Вопрос:
В каие состояния необходимо выставить фьюзы контроллера что бы он работал от встроенного тактового генератора? (на мой взгляд проблема в этом).
Ну или какие могут быть Ваши предположения?
P.S. Не пинайте если чё не так написал это мой первый проект.
А при чем тут тактовый генератор? Дисплей полностью синхронный и скорость работы МК тут совершенно не играет роли. Протеусовская модель тоже далека от реальности. особенно в плане инициализации.
Как мне кажется AtMega вобще стоит и не работает. Сейчас думаю как это проверить.
добавь в главный цикл мигание светодиодом.
Схема почти такая http://forum.qrz.ru/attachment.php?attachmentid=7685&d=1182537241 . только LCD подключён на порт B.
подскажите куда подключены неиспользуемые D0-D3 у LCD
просто заземлить .минус питания
Оставь висеть.
Я незнаю точно что лучше ,но у меня на заводском борту они на земле.
http://www.myavr.info/download/produkte/lcd/techb_schaltplan-lcd.png
Смотри что может произойти:
ПО ошибке не так инициализировал. Сделал случайно READ и получил высокие уровни на этих выводах со стороны дисплея. А они на земле. Опа и выгорели.
Спасибо за подсказку.Я просто пользуюсь готовым кодом и об этих токостях
незнал.
Никак разобраться не могу: подключил дисплей на Pinboard 1.1 по 4-х битной шине на порт С mega16 (библиотеку использовал здешнюю), шлю данные — тишина. Подключаю точно по такой же схеме на порт B — все отлично работает. С портом A тоже работает, вешаю на порт D — опят тишина. Что не так? На будущей плате свободен только порт C, все остальные забиты под завязку. Выручайте
Дело в том, что у всех старших мег по умолчанию включен JTAG, а значит четыре линии порта С нельзя использовать как порт. Чтобы выключить жтаг нужно зайти программатором в режим прошивки FUSE и выключить там бит JTAGEN
Здрасьте. Прикупил я значит себе дисплейчик на контроллере Sumsung KS0066U. Даташит на первый взгляд идентичен даташиту HD44870. После тестового подключения дисплея показалась одна строка, контраст регулировался четко и ясно. Далее, естественно, решил попробовать вывести символ, подключил библиотеку, скопипастил код. Дисплей не заработал. Даже контрастность перестала регулироваться. (Правда в полной темноте можно заметить, что места символов начинают чуть-чуть светиться при выкручивании резистора на полную.) Все перепроверил — результата нет. Подскажите пожалуйста, при таких симптомах в чем может быть мой косяк? (Мерял прибором: RS=1, RW=0, E=0)
Извини, DI HALT. Не сразу обратил внимание на твой пост от 2 апреря. Порт данных был портом С. Сообщение можешь удалить. Так или иначе, спасибо за статьи и библиотеку.
Что то замучался я совсем с подключением WH2004А.
вот код программы инициализации и вывода нескольких чисел:
initLCD: rcall delay50ms
ldi r28,0b111100 ;
rcall icom
rcall delay50ms
ldi r28,0b111100 ;
rcall icom
rcall delay50ms
ldi r28,0b111100 ;
rcall icom
rcall delay50ms
ldi r28,0b1100 ;
rcall icom
rcall delay50ms
ldi r28,0b1 ;
rcall icom
rcall delay50ms
ldi r28,0b110 ;
rcall icom
rcall delay50ms
ldi r28,0b111100 ;
rcall icom
rcall delay50ms
ldi r28,$80
rcall icom
ldi r28,’1′
rcall idat
ldi r28,’1′
rcall idat
ldi r28,’1′
rcall idat
ldi r28,’1′
rcall idat
ldi r28,’1′
rcall idat
ldi r28,’1′
rcall idat
loop:
rjmp loop
icom: rcall delay ;задержка ~1,8 ms
CBI portd,4
rcall delay
out porta,r28
out portc,r28
rcall delay
SBI portd,5
RJMP step
idat: rcall delay
SBI portd,4
rcall delay ;
out porta,r28
out portc,r28
rcall delay
SBI portd,5
step: rcall delay
CBI portd,5
ret
что то не так, не выводит единици вместо них что попало пишет и куда попало.
WR на массе сидит, уже и задержки зверские прикрутил.
Что я сделал не так?
А у 2004 там вроде бы все сложней, ЕМНИП там два контроллера HD44780. Надо почитать доку попоподробней.
Контроллер один там. скурил штуки 4 даташита.
примерно нашел где ошибка. пины D2 и D3 почемуто всегда на + висят. пробовал в конце кода на этот порт где пины 0 посылать один фиг + там висит, а не должно.
инициализацию портов уже проверил раз на 5 тока Эти пины что то гонят остальные в норме вроде.
Я в шоке. битый контроллер мега ? лсд на разъеме, отключал, таже хрень.
А какой контроллер? И какой порт юзаешь? Часом не PC?
Выводы TMS и TCK — JTAG в ATMEGA16 на этих пинах.
я его не инитил. мб фусы кривые ?
У меня hfuse=9A lfuse=E3.
Ну так если ты фузы не трогал, то по дефолту жтаг включен и эти пины заняты им. Надо выключить фуз JTAGEN
я зашивал и ща проверил hfuse=9A lfuse=E3.
бит JTAGEN=0 вроде как
В нотации атмел 0=включен. Сделай его 1 :)
Можно и через мкускр его программно вырубить, но фуз сбросить проще :)
выключил фуз JTAGEN и все получилось.
Спасибо за помощь.
в книге написано ешо надо сбросить разряд JTD регистра MCUCSR.
мб в этом дело. проверю ща.
сократил задержки до приемлимых, да и код подправил.
А так контроллер такойже как HD44780 вобщемто.
У меня видеовопрос http://www.youtube.com/watch?v=8-p5Sm4AWDM
Вкратце:
Светодиод до инициализации дисплея должен гореть, после вывода на экран — мигать.
Он мигает, но экран не инициализируется. Я грешу на задержки, так как после сброса контроллера все работает.
Кстати, оффтопик: (к теме о подключении МК) я притянул РЕЗЕТ к питанию через 10к, а он все равно сбрасывается если тычешь в него щуп осциллографа (включенного или нет — без разницы) — как же мерить уровни на ногах, если осцилл так просаживает напругу?
Да, забыл добавить — фузы никакие не менял (значит внутренний генератор на 1 Мгц), в библиотеке поменял только порты (D-данные, В-управление), задержка так и стоит 14
По поводу видео. Нормальное явление. Дисплеи часто стартую медленней чем МК. И может получиться так, что значительня часть инициализации уйдет в пустоту. Поставь небольшую задержку (тактов на 200) перед инитом дисплея и должно помочь.
Поставил задержку 2FFFF вычитаний, и даже 2 раза INIT_LCD. Грешил на блок питания — у него медленно поднимается напряжение, а мега с индексом L может, думаю, мега стартует раньше из-за этого, поставил выключатель — все равно та же фигня. Заметил особенность — когда проходит инициализация и вывод букв (суда по задержке) на экране слегка моргают засвеченные (полуконтрастные) строки.
Короче, пошел читать внимательнее даташит на WH2004D-YGH-CP.
Вроде зарабртало. Переписал часть кода ближе к даташиту.
[CODE]
; Init Config
.MACRO INIT_LCD ; Инициализация LCD
RCALL InitHW ; Настроить контрольный порт
RCALL LCD_DELAY ; Подождать
;——— здесь 0b00110000 3 раза с задержками ————
CBI CMD_PORT,RS
CBI CMD_PORT,RW ; Запись!
LDI R16,0b00110000
OUT DATA_PORT,R16
SBI CMD_PORT,E ; Поднять строб WR_CMD (1<<4)|(1<<5)|(0<<6)|(0<<7)
RCALL LCD_DELAY ; Подождать
CBI CMD_PORT,E ; Опустить строб WR_CMD (1<<4)|(1<<5)|(0<<6)|(0<<7)
RCALL LCD_DELAY ; Подождать
RCALL LCD_DELAY ; Подождать
RCALL LCD_DELAY ; Подождать
SBI CMD_PORT,E ; Поднять строб
RCALL LCD_DELAY ; Подождать
CBI CMD_PORT,E ; Опустить строб
RCALL LCD_DELAY ; Подождать
SBI CMD_PORT,E ; Поднять строб
RCALL LCD_DELAY ; Подождать
CBI CMD_PORT,E ; Опустить строб
WR_CMD(1<<LCD_CLR) ;0×01
WR_CMD (1<<LCD_ENTRY_MODE)|(1<<LCD_ENTRY_INC);0×06
WR_CMD (1<<LCD_ON)|(1<<LCD_ON_DISPLAY)|(0<<LCD_ON_CURSOR)|(0<<LCD_ON_BLINK);0x0C
WR_CMD (1<<LCD_HOME)
.ENDM
[/CODE]
и еще в конце InitHW поменял RCALL PortIn на PortOut, иначе команды не уходили.
Только курсор теперь мигает (раньше его не было).
Конечно, по уму надо рассчитать задержки (благо в даташите они есть), а не тыкать наобум несколько ЛСД_Делэй и причесать код, но если у кого такой дисплей не работает, может быть поможет.
Да он не просаживает напругу. Просто у щупа осцилла есть емкость, вот эта емкость и дает импульсный бросок вниз. Попробуй через резистор в 1к подключать щуп осцилла. У него входное напряжение в гигаомы, ему этот 1к что мертвому припарки, а вот кондер перезаряжаться не будет так быстро
Пробовал через 1к и через 200к все равно сбрасывает.
Странно, не должен он сбрасывать. У тебя там точно подтяжка нормально пропаяна? 1К подтяжку сделай, она будет куда надежней.
Если запитывать через дракона от USB то не сбрасывает %) Видать что-то с БП все-таки не так.
Сначала хотелось бы сказать большое спасибо за этот курс. Нашел много интерсного а главное полезного мне.
Прошу не судить строго за вопросы я лишь недавно начал интересоваться микроконтроллерами.
Недавно купил дисплей SC1601A на 1 строку и 16 символов. Подлючил к Меге 16. Порты: RS к PD4;RW к PD5;E к PD6;DB0-DB7 к порту B.
Вопрос 1: Дисплей работает и выводит,но лишь на первые восемь позиции. Остальные мервые. Я неправильно инициализировал или дисплей не работает?(если дисплей то как проверить?)
Вопрос 2: Мучаюсь с написание процедуры для вывода строки. Продедура выводящая символ работает отлично. Можете подсказать?
Вопрос 3: Очень хотелось бы почитать про разные датчики(с примерами на Си). Например датчики расстояния(хочу собрать робота а с датчиками пока не определился). Можете кинуть пару ссылок?
Код:
А там адресация поди чрезжопная. Суть в том, что первые 8 символов это одна строка, вторые 8 символов они как бы вторая строка.
Попробуй выводить аски коды по очереди, медленно, скажем раз в секунду, меняя выводимый аскии код. Тупо по порядку адресов дисплея, начиная с нуля. Вначале заполнится первые 8 символов, потом, спустя какое то время полезут и остальные. Вот по номеру аски кода узнаешь в каких адресах видеопамяти у тебя вторые 8 символов. ЕМНИП они начинаются с 0х40 адреса.
А чем проблема с выводом строки?
Выложите пожалуйста рабочий пример для протеуса, выше были комментарии, что в протеусе все работало. Спасибо.
http://ifolder.ru/19047000
мой хелло ворлд) На протеусе все робит. Как в железе не знаю
Спасибо. А то уже успел забить на этот дисплей.
Привет, DI! Есть 2 вопроса6
1) А почему при переключении портов МК на приём данных от LCD, они преключаются на вход с подтяжкой, а не с высоким входным сопротивлением? По идее, с высоким входным было бы лучше — меньше энергии бы потреблялось…
2) Не мог бы ты поподробней раскрыть смысл такого макроса:
.MACRO LCD_PORT_IN
RCALL PortIn
.ENDM
???
Почему плохо сразу писать в программе
RCALL PortIn
???
Ведь и логически и по смыслу понятно что и макрос и подпрограмма переключат порт на вход.
Не все дисплеи умеют тянуть вверх.
Для красоты :)
Я посмотрел библиотеку для LCD. Почему при вызове макросов допустим на чтение или запись данных в дисплей запрещаются прерывания? Ведь в прерываниях все равно рабочие регистры сохраняются в стеке?
Можно разрешить. Я тогда это делал чтобы тайминги не сбивались, но протокол там синхронный, так что это не влияет, а багов добавляет дай боже :)
И еще, чем принципиально отличаются файлы с расширением .asm и .inc. Почему не забабахать все в один файл?
С точки зрения компилятора — ничем, хоть как называй. Текстовый файл он и есть текстовый файл. Просто как то так прижилось, что в инклюдах библиотеки сидят.
Спасибо.
SHIFT SCR_K; опечатка, нужно R.
Отсутствует в библиотеке LCD_macro.inc макрос RD_CGADR xx который описывается в статье.
Cлушай DI, сейчас пробую использовать твою библиотеку для lcd панели, а ведь работает же. Все пучком. Правда сперва ее исследовал часа 4 пока вник в суть. Оказалось не сильно все сложно. Составлена логика грамотно. Мне это понравилось. И в использовании в проекте удобно реально. Макросы это сила, ничего не скажешь. Спасибо. Хорошо что ты есть на свете.
Добрый вечер парни!
3 дня парюсь c этой библиотекой, и не получается =((
проверил пошаговое выполнение: заходит в LCD_macro.inc, там проходит по двум меткам, выходит, проходит INIT_LCD и опять возвращается в LCD_macro.inc и вот такие циклы наворачивает и все…
ппц загнобила меня LCD =))
Отправьте кому не сложно рабочие схемы в Протеусе на мега16.(для 8ми и 4х битной шинки)
И исходник на асме.
Заранее благодарен.
Оно в протеусе и не должно работать. В протеусе дисплей соответствует реальным с сильно большими упрощениями. ЕМНИП протеусовский дисплей не ставит флаг готовности, а моя либа требует проверки этого флага. В живую должно все работать.
З.Ы.
Протеус маздай!
Ясно…
Просто делается проект и хотелось бы сначала удостовериться в работоспособности модели на эмуляторе а потом уже на железе!!!
Я кстати нашел «забугровую» библиотеку на LCD.
Если интересует посмотри =)
http://www.embedds.com/the-introduction-for-hd44780-based-lcds-with-avr-microcontroller/
http://www.avrbeginners.net/interfacing/44780_lcd/4bit.html
Ой да их дофига. Я свою писал когда хотел разобраться с этим протколом.
Не знаю не знаю…на русских порталах на асме нашел только 2е (включая твою).
На зарубежных вот только эти которые указал =))
Дорогие друзья. Обе библиотеки как для 8, так и для четырёх бит рабочие. В протеусе не работают, т.к. я думаю, что там для LCD необходимо выдерживать строгие времменые интервалы при инициализации. Кстати до сих пор не могу понять, как у DIHalt’a он инициализируется если в описании на HD 44780 чётко написано, что проверять бит готовности не нужно при старте, а нужно соблюдать временные задержки. Но оно работает!!!
Всем у кого не получилось советую посмотреть к каким выводам подключен LCD (данные и управляющие выводы) и при необходимости внести изменения в библиотеку.
Спасибо DIHalt. Продолжай в том же духе!!!
Не знаю помогут ли кому мои мысли, но, в любом случае лишним не будет. Возможно в протеусе просто не успевает эмулироватся дисплей. Т.к. частота контроллера к примеру 8МГЦ а дисплея (в настройках дисплея) у меня по дефолту стояла 250кГц. Выставил 10МГц и все стало очень даже прекрасно работать и в протеусе и в железе. И не нужно кучу раз в коде прописывать инициализацию дисплея и задержки вставлять. У меня протеус 7.7
Столкнулся вот с какой проблемой при работе LCD в 4-битном режиме. Допустим вбиваю подряд несколько символов, программирую и они появляются на экране. Но после того, как выключаю питание, и потом включаю на экран ничего не выводится. При последующей перепрошивке опять появляются символы. Ума не приложу что может быть. Добавлял задержку при старте перед инициализацией lcd — не помогает. Контроллер ATmega8, тактовая 1 МГц. На восьмибитной шине всё работает замечательно.
Может кто-то умную мысль подкинет)
Хм. Может дисплей не стирается и сохраняет настройки? ПОпробуй инициализацию дважды делать.
Парни подскажите кто знает!!!
Не могу сделать чтобы курсор двигался по экрану с помощью кнопки(один раз нажал, курсор сдвинулся на одно деление влево/вправо).
Получается только сдвинуть его один раз, при втором и последующих нажатиях не чего не происходит…
Если написать цикл то все ОК, передвигает курсор столько сколько раз проходит цикл, а через кнопку не хочет (((
в чем прикол не пойму ?_?
Прерывание внешнее делал через INT0.
Писал так:
.CSEG
.org $000
rjmp reset
.ORG $002 ;(INT0) External Interrupt Request 0
rjmp sdvig_cursora
reset:
ldi temp1, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse
out SPL, temp1
ldi temp1, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
out SPH, temp1
ldi r20,0b00001111 ;настройка прерывания
out MCUCR,r20
ldi r20,0b11000000
out GICR,r20
sei
ldi temp1, 0xFF ; Port D = Ausgang
out DDRB, temp1
rcall lcd_init ; Display initialisieren
rcall lcd_clear ; Display loschen
ldi temp1, 0b00001110 ; Display on, Cursor on
rcall lcd_command
ldi temp1, ‘T’
rcall lcd_data
ldi temp1, ‘e’
rcall lcd_data
ldi temp1, ‘s’
rcall lcd_data
sdvig_cursora: ; метка по внешнему прерыванию
ldi temp1, 0b00010100 ; курсор сдвинуть вправо
rcall lcd_command
reti
loop: rjmp loop
У тебя прерывание категорически неправильно оформлено :) Хотя тут и не влияет, но потом вылезет в полный рост. Не сохранены регистры и флаги. Читать главу курса про подпрограммы и прерывания. И вообще неправильно такие тяжелые вещи (как работа с дисплеем) пихать в прерывания.
А по факту проверь вызывается ли у тебя прерывание вообще. По входу в прерывание сделай инверсию какого либо бита и повесь туда светодиод. Скорей всего будет какой нибудь ад :)
Прерывание вызывается один раз(курсор двигается один раз вправо), потом больше не вызывается…
С буквами пробовал, так же один раз напишет ее при нажатии и все,при втором и последующих потом больше не пишет =))
Все разобрался))) не внимательность подвела =)
Появилась другая проблема)) как инстализировать 4х строчный дисплей???
привет всем. Ruslan, ты наверное имел в виду «инициализировать», т.е. обьяснить ему самому, кто он (монитор) в этом мире? Я даташите видел, что 4 строчечники инициал. также как и 2-строчники 2х16, только поле знакомест идет так: первая строка — адрес первых 8 мест ( с 00 по 07)первой строки двустрочника, вторая строка-адрес первых 8 мест ( с 00 по 07)второй строки двустрочника ( т.е. арреса с 40 по 47) третья строка — вторая половина первой строки двустрочника(с 08 по 0F), четвертая, соответственно, втроая половина втрой строки (адреса с 48 по 4F).
Ура!! Наконец-то решил проблему с пропаданием символом после перезагрузки.
Переписал инициализацию «по даташиту». Сначала пихаю команду перехода в режим 8 бит. Затем 4.1мс пауза. После этого опять 8 бит, пауза 100мс. После этого идёт команда перехода на 4-битный режим, потом пауза 200мс. В этих трёх действиях не проверяется флаг занятости и запись команды производится как в 8-битном режиме (за 1 такт). Потом уже с проверкой флага снова устанавливается 4-битный режим, но уже за 2 такта. А далее как в исходной библиотеке…
Подскажите можно ли как нибудь извлечь адрес места нахождения курсора на LCD?
И как записывать символы в определенные ячейки с помощью указания адреса ячейки?
Привет, подскажи в чем может быть причина, дублируются символы при выводе на дисплей
к примеру
беру из таблицы символы
начинающиеся все на 0×3
первые 0×30 — 0×33 такие же как и 0×38 — 0x3B
и другая пара одинакова, не могу понять в чем может быть проблема, библиотека твоя,
дисплей WH1602M
Здраствуйте.
Для нормальной работы в протеусе по 4 битной шине, нужно при подаче команды 20Н подавать только старшую часть байта. Т.е. 2. А младший не передавать вообще. А начинать второй байт. И уже передача идет обех частей байта.
для этого нужно в LCD4_macro в макросе Init_Lcd дописать команду WR_CMD 0×32.
Тогда протеус отрабатывает все нормально.
День добрый.Не подскажете что такое холодный или горячий старт дисплея.В чём разница
приемущества или недостатки.небольшие изменения в LCD_Init.
DI у тебя при чтении флага занятости в 4х битном подключении считывается еще и младшая тетрада. Зачем? Ведь флаг находится в старшей тетраде. Младшая тетерада при этом не используется.
Спроси че полегче. Я уже не помню. ВРоде бы сначала выдается младшая, потом старшая. Либо наоборот, но ее клинит и надо считать еще и младшую, чтобы в следующий раз получить адекватный результат. Либо просто чтобы не плодить ветвей в коде, а заюзать уже отработаный кусок.
Я сейчас все проверил в реали. Да ты правильно сделал. Нужно потом читать и младшую тетраду, обязательно, хотя она и не используется. Тоесть нужен полный цикл чтения всего байта из lcd. Но! Я не использовал задержку lcd_delay. Она вообще не нужна, так как по даташиту время на считывание флага 0 мкс. получилось вот что.
порт на вход
sbi portC,0 // RW=1 (чтение из LCD)
cbi portD,7// RS=0 (команда)
BYSY: sbi portC,1// E=1
cbi portC,1// E=0
in r16,pinc
sbi portC,1// E=1
cbi portC,1// E=0
andi r16,0b00100000
brne BYSY
порт на выход
В принципе спорить не буду. Этот дисплей подключается по схеме внешней памяти, а она по определению должна быть быстрой. Но если вдруг при высоких частотах возникнет глюк — ищи его в отсутствии выдержки.
а у меня вот возник тупой вопрос — почему .include «LCD4.asm» надо проставлять в конец кода? я этот момент упустил и ставил его следом за .include «LCD4_macro.inc» — ну и затем полночи разбирался, почему дисп не инициализируется.. :)
Что такое инклюд? Это значит лишь что мы берем содержимое инклюднутого файла и вставляем его вместо строчки .include LSD4.asm содержит код. Соответственно вставить его надо туда, где он мешать не будет. Т.е. в конец.
LCD4_macro содержит всякие наименования и макросы. Их надо ставить ДО того как они хотя бы один раз встретятся, по этому его в начало.
Здравствейте. Целый день уже мучаюсь и никак не могу заставить в ПРОТЭУСЕ дисплэй хоть что-то показывать. Использовал дисплэи LM_016L,LM_020L — безрезультатно. Выставил одинаковые частоты на микроконтроллер и на дисплэй.
Пробовал оба варианта подключения как 4, так и 8. При подключении с 4 ногами в протеусе вообще вываливается ошибка. При подключении с 8 ногами ошибки нет, но ничего и не выводит.
В основную программу я только инициализирую стек и все. основная программа состоит из след. кода:
.org 0×0000
rjmp RESET
RESET:
ldi r16, High(RAMEND)
out SPH, r16
ldi r17, Low(RAMEND)
out SPL, r17 ;init steka
rjmp MAIN
MAIN:
INIT_LCD ; Инициализируем
WR_CGADR 0 ; Указатель на начало знакогенератора.
WR_DATA 0b00000001 ; Запись данных нового знака
WR_DATA 0b00000010
WR_DATA 0b00000100
WR_DATA 0b00011111
WR_DATA 0b00000010
WR_DATA 0b00000100
WR_DATA 0b00001000
WR_DDADR 0
WR_DATA 0
Ничего не выводит. Версия протеуса 7.7 SP2 (вроде последняя).
В комментариях выше был выложен проект в протеусе и проект в AVR_STUDIO. Но при запуске в протеусе вывалилась ошибка Invalid opcode 0xFFFF at PC=0×0168. Такая же ошибка вываливается и у меня когда я пытаюсь использовать LCD_4.asm.
Уже начинаю подозревать что проблема может быть как-то в самой версии в протеусе.
Что посоветуете?
Проверял в 7.6. Результат тот же
А она в протеусе и не работала никогда.
Только в железе.
Но в протеусе ведь есть примеры с работающими экранчиками?
Есть. Но заморачиваться и подгадывать свою прогу еще и к протеусу (которым я не пользуюсь, ибо УГ) мне было совершенно вломы.
Ну я так посмотрел на вскидку и винили, то место где ожидался ответ lCD на готовность. Я это условие убрал, но безрезультатно. Не подскажите хотя бы направление куда копать?
Собери уже в железе и не мучайся. Нафига тебе еще разбираться с глюками протеуса?
Куда там копать я даже понятия не имею. Откуда я знаю что они там навертели и насколько точно работает эмуляция интерфейса. Может он флаг готовности вообще не ставит, т.к. расчитан на быдлокодинг, когда на флаг готовности тупо забивают, делая ожидание в десяток ms тупым циклом (90% примеров работы с дисплеем)
В конце концов в том же протеусе есть и отладчик и можешь посмотреть на каком месте у тебя все затыкается
{brother77 30 мая 2010 19:38
Что то замучался я совсем с подключением WH2004А}
в итоге было написано что все удачно решилось…
Выложите пожалуйста у кого есть работающую библиотеку для такой модельки!
Может быть такое что эта моделька WH2004A (а если точнее то WH2004A-YYB-CT) не может работать на 4 битах ??? т.е. только на 8 битной шине.
Все они могут. Это стандарт контроллера.
Блин даже с «сишной» библиотекой не выводит ничего =(((
DI HALT используя твою библиотеку, подскажи какой командой можно узнать место нахождение курсора на LCD в данный момент…
если для этого надо добавить пару строк в библиотеку, подскажи пожалуйста куда и как…
Никак. Контроллер не позволяет это узнать. Только самому где то запоминать
Чтение регистра команд возвращает 8 значащих разрядов. Старший разряд — busy flag ,а остальные 7 — значение счётчика АС(если адресуется DDRAM). Это и есть положение курсора.Один важный момент. После появления BF=0, прочитанное в этом же цикле АС не будет достоверным. Для получения достоверного значения АС нужно совершить повторную операцию чтения регистра команд через 4 мкс.(время указано для 270 кГц)
если можно тут сохраню «финт ушами» я вот так избавился от Push/Pop при посылке данных/команды:
[code]
IN R16,PORTB // читаем состояние
// финт ушами: биты[7..4] в R16 заменяем на биты из R17 (R17- остаётся без изменений)
EOR R16,R17
ANDI R16,0b00001111
EOR R16,R17
// готово
OUT PORTB,R16 // записали в порт
[/code]
код тут геморно вставлять, и коменты из АВР на русском не перекидываются :(
Как можно вывести значение переменной на LCD, в avr-lib.
Привет.
В твоей библиотеке есть косяк.
Во-первых, чем отличается проверка флага занятости от чтения команды?
На самом деле ничем: читать команду нельзя, вместо неё читается флаг занятости и счетчик адреса.
Во-вторых, задержки выдачи сигналов слишком большие.
Возможно, у меня более быстрый контроллер ЖКИ.
Сигнал E удерживаю 3 такта при частоте 8 МГц и всё прекрасно работает.
В Даташите HD44780 написано — min 230 наносекунд.
Ну це не косяк, скорей избиточность. В целом да, чтение команды равносильно чтению флага занятости.
Протокол там синхронный, поэтому задержка не может быть сильно большой. И сильно зависит от типа дисплея. Например МЭЛТы тупят.
Добрый день.
Зметил такую странность.Бит Busy читается только тогда когда высокий E.Если сбросить E то читается всегда 1. Длительность E у меня 750ns.По даташиту 400ns.
Да еще хочу спросить такую вещь.Есть ли в препроцессоре компилятора которым ты собирал библиотеку возможность сделать что то типо такого : print(«string»); который препроцессор развернет в последовательный вызов процедур записи данных для кажлого символа.Построчно вводить каждую букву очень не удобно.
Нет. Это СПАРТА!!!
Но ты можешь разместить строку во флеше (итак придется) и написать дополнительную функцию которая их будет выводить.
Где проверял?
А меня дисплей подключен к микроконтроллеру PIС по 8 битной шине.Кварц 16 мегагерц.Я в при первом запуске вывожу в дисплей символ.(Не использую busy wait а ставлю большую паузу большой длительности).Потом перепрошиваю контроллер где просто делаю busy wait.Так вот контроллер висит.Всегда 1 выдает.Сегодня еще проверю вечером.
Подсккажите пожалуйста, как при помощи этих библиотек вывести содержимое регистра целяком? то есть выводить не каждый символ отдельно, а содержимое регистра, например я хочу вывести код АЦП на дисплей. как это сделать?
ЗЫ: ассамблер только учу
Преобразовать код в символы и вывести. Гугли алгоритм bin2bcd он без проблем находится. После него у тебя будут три числа, которые несложно превратить в ascii код который легко поймет знакогенератор дисплея
Поиски готовой библиотеки для RC1602B привели меня на этот сайт.
Я не понял как выводятся символы хранящиеся в CGROM.
В макросах плохо разбираюсь, поэтому не всё понял.
Неужели для каждого символа нужно писать его цифровой код в ячейке памяти ?
Я в своей библиотеке ввёл понятные для меня обозначения каждого символа через .equ
Или есть способ проще ?
Просто записываешь в видео память символы и они согласно таблице (RAM и ROM) выводятся. Если надо своих символов нарисовать, то вначале в 8 знакомест загоняешь нужные байты, для формирования их. А дальше просто по номерам вызываешь.
Да это понятно.
Но если я пишу код, не не имея перед глазами таблицу. Как мне знать, какой номер соответствует какому символу.
Я делаю это так:
В шапке пишу.
…
.equ l_point = 0x2E ;.
.equ l_comma = 0x2C ;,
.equ l_colon = 0x3A ;:
…
.equ l_0 = 0×30 ;0
.equ l_1 = 0×31 ;1
.equ l_2 = 0×32 ;2
…
.equ lrb_a = 0×41 ;А
.equ lrb_b = 0xA0 ;Б
.equ lrb_v = 0×42 ;В
…
а в теле программы
ldi Data,lrb_a
rcall out_letter
В вашей библиотеке подобные перекодировки есть ?
Или нужно указывать цифрами:
типа
ldi Data,0×41
rcall (вывод символа)
Нет у меня таблицы нет. Если надо, то я строки перекодирывал специальной утилиткой на компе ,а потом вставлял в исходник. Плюс ASCII коды для английского языка вроде бы совпадают с табличной раскладкой.
Делать эквайшены подобные вашим, имхо, смысла не имеет. Т.к. строки все равно берутся из памяти, а посимвольно «вручную» выводить их неудобно. Разве что вывести один два символа, но это несложно и в таблицу поглядеть.
Понятно. В памяти хранить, тоже вариант.
У меня просто другой подход.
Я их не в виде данных храню, прописываю командами, как в примере. И мне удобно сразу заменять их обозначениями. Особенно русские символы, без перекодировки.
Так можно хранить только короткие сообщения. А попробуйте загнать абзац текста — замучаетесь, да и памяти потратите в десять раз больше, чем один цикл обработки строки.
Согласен.
Но я не книгу пишу, у меня несколько строк, и памяти остаётся достаточно.
Хотя 4 байта на символ это роскошь, но мне хватает. А менять надписи я могу быстро, без никаких перекодировок.
Но если пойдёт много текста , то придётся кардинально переписывать библиотеку.
Спасибо за совет.
Здравствуйте.Я все сделал ка надо и у меня вышла на LCD эта закарючка.Подсккажите пожалуйста, как настроить и где чтоб бегущая строка побежала?Пишу слово,а у меня только в одном квадрате меняетса.Заранее спасибо.
Для бегущей строки надо перезаписывать весь экран, сдвигая текст. Либо двигать экранную область, но это большй гемор.
Вот код.Но AVR ругаетса где ;Write Data
Подскажите пожалуйсто где косяк?
.include file «C:\AVR\AvrAssembler2\Appnotes\m8515def.inc»
.include file «C:\AVR\WH\LCD_macro.inc»
.def temp =r16
.def temp1 =r17
.cseg
.org 0
InitAvr:
;Initialize stack pointer
ldi temp, LOW(RAMEND)
out SPL, temp
ldi temp, HIGH(RAMEND)
out SPH, temp
rcall LCD_Delay ; Пауза перед включением
INIT_LCD
INIT_LCD
SHIFT CUR_R ; Сдвиг курсора в право
LCDCLR
WR_DATA «A»
WR_DATA ‘n’
WR_DATA ‘t’
WR_DATA ‘o’
WR_DATA ‘n’
; WR_DATA 0
.include file «C:\AVR\WH\LCD.asm»
Loop:
RJMP Loop
Лучше бы показал как ругается. По идее раз схавал WR_DATA ‘A’ то должен схавать и WR_DATA 0 т.к. с точки зрения компилятора это одно и то же.
вот что пишет:C:\AVR\WH\LCD_macro.inc(48): error: syntax error, unexpected STRING
Ну так все правильно, кавычки должны быть одинарные, а не двойные.
Все равно ругаетса именно на LDI R17,@0
Значит не те кавычки стоят. Их одинарных существует как минимум два вида. Копипастил поди код? ;) А надо ручками вводить.
А когда есть макросы, то он сильно тупит и может ругаться не на ту строку или ваще затупить.
Все разобрался написал в 16-и рич. форме)))СПАСИБО!!!
;Write Data
.MACRO WR_DATA
LDI R17,@0;Что тут надо подставить?
RCALL DATA_WR
.ENDM
Ничего там не надо подставлять
Подскажите пожалуйсто,а что надо сделать чтоб написать во второй строчке LCD?Я только учусь не судите строго))
Передвинуть курсор на другой адрес. Для этого есть макрос LCD_COORD X,Y
Вам для начала надо прочитать как работает дисплей HD44780 тогда большая часть глупых вопросов просто отпадет.
http://easyelectronics.ru/avr-uchebnyj-kurs-podklyuchenie-k-avr-lcd-displeya-hd44780.html
Я прочел просто не пойму как это зделать.
Стоит прочитать еще раз. Особенно часть про адресное пространство видео памяти. Тогда поймешь, что каждому знакоместу соответствует свой адрес. И чтобы написать в определенное место экрана надо вычислить адрес этого места и выставить его командой. А потом писать. Исключение составляет последовательная запись, когда пишешь с нулевого адреса, а он автоматически увеличивается на 1. Но для перевода на вторую сторку надо либо написать очень много символов в теневой части (за пределами видимого окна), чтобы адрес сам достиг второй строки, либо вручную, командой, его перенести куда надо. Через макрос LCD_COORD X,Y
Все это понятно КАК это с помощью кода отобразить я не знаю)))пример привести можно?
Какой курсор?куда его двигать?)))
Курсор дисплея, а конкретней текущий адрес в памяти куда пойдет запись. Курите матчасть. Пока не разберетесь досконально в том как дисплей устроен, как у него разложена память, что из памяти видно, а что нет вы его не осилите.
Судя по вопросу нихрена вам не понятно :)))))
LCD_COORD 0,1 — перевести каретку на вторую строку нулевой символ.
Так сразу бы и сказал))))
http://easyelectronics.ru/repository.php?act=view&id=65 — тут код только на один байт т.е. значения от 0 до 255. А если мне нужно конвертировать больше разрядов??? (сам пока не смог придумать что либо простое и эффективное).
Добрый день!
пытаюсь использовать Вашу библиотеку:
.include «m8def.inc»
.include «LCD4_macro.inc»
BEGIN: INIT_LCD
rjmp BEGIN
.include «LCD4.asm»
при компиляции такие ошибки:
AVRASM: AVR macro assembler version 1.77.3 (Aug 25 2011 20:29:36)
Copyright (C) 1995-2005 ATMEL Corporation
Creating ‘test2.eep’
Creating ‘test2.hex’
Assembling ‘test2.asm’
Including ‘C:\avrtools\AvrAssembler\Appnotes\m8def.inc’
Including ‘LCD4_macro.inc’
LCD4_macro.inc(38) : error : Unknown instruction opcode
LCD4_macro.inc(39) : error : Unknown instruction opcode
LCD4_macro.inc(40) : error : Unknown instruction opcode
LCD4_macro.inc(41) : error : Unknown instruction opcode
LCD4_macro.inc(42) : error : Unknown instruction opcode
LCD4_macro.inc(43) : error : Unknown instruction opcode
test2.asm(8) : error : Macro within macro not supported
Assembly complete with 1 error
Deleting ‘test2.eep’
Deleting ‘test2.hex’
строки 38-43 в LCD4_macro.inc это WR_CMD в макросе INIT_LCD
если их закоментировать — то всё компилится, даже если использовать WR_CMD в основном файле.
подскажите, в чём проблема?
спасибо!
Макросы вызываются раньше чем они обьявлены. Прописал либу неверно. Инк файлы описывающие макросы не должны быть позже появления этих макросов в коде.
ругань идёт на Ваш файл LCD4_macro.inc
я пробовал в нём переставить описание макроса WR_CMD до макроса INIT_LCD — это ничего не дало.
я так понимаю, что такая проблема с вашей библиоткой только у меня, потому и спросил, в чём может быть проблема…
Не надо в нем ничего переставлять. Надо в вашем исходнике место прописки файла LCD4_macro.inc поставить ПОСЛЕ того как будут описаны макросы WR_CMD и прочие.
макрос WR_CMD описан в LCD4_macro.inc
и в самом же LCD4_macro.inc WR_CMD используеться до того, как он будет описан.
не могли бы Вы выслать мне на shilow@ukr.net любой проект, который использует LCD4, и который у вас компилиться? спасибо.
А где он у вас в тексте программы вообще? и где в тексте моего примера? Сделайте также, ругаться должен перестать
Разобрался:
— компилятор 1-ой верси: avrasm32.exe version 1.77.3 не компилирует эту библиотеку
— компилятор второй версии: avrasm2.exe version 2.1.43 замечательно всё компилирует.
В proteus-е заработало после этого:
http://electronix.ru/forum/index.php?showtopic=52609&view=findpost&p=469720
в lcd_macro.inc в макросе INIT_LCD после строки
RCALL LCD_DELAY
добавил строку
WR_CMD 0×02
и заработало.
Доброго дня.
Прошу подсказать новичку.
Пишу программу (AVR Studio v.4) для ATmega8515 подключенному к 2-х строчному LCD по 8-ми битной шине. Использовал файлы выложенные автором. В файле LCD.asm подправил блок инициализации: порт данных — порт А (8 бит), порт управления — порт Е и очередность битов иная: E=2, RW=1, RS=0.
LCD_macro.inc не менял там все биты соответствуют.
Вот исходный код:
.include «m8515def.inc»
.include «LCD_macro.inc»
.include «LCD.asm»
;Инициализация стека
ldi r16, high(ramend)
out sph, r16
ldi r16, low(ramend)
out spl, r16
;r16, r17 РОН используются
;Порты B, C, D не используются
ldi r16, 0b00000000
out DDRB, r16
ldi r16, 0b00000000
out PORTB, r16
ldi r16, 0b00000000
out DDRC, r16
ldi r16, 0b00000000
out PORTC, r16
ldi r16, 0b00000000
out DDRD, r16
ldi r16, 0b00000000
out PORTD, r16
INIT_LCD ; Инициализируем
WR_CGADR 0 ; Указатель на начало знакогенератора.
WR_DATA 0b00000001 ; Запись данных нового знака
WR_DATA 0b00000010
WR_DATA 0b00000100
WR_DATA 0b00011111
WR_DATA 0b00000010
WR_DATA 0b00000100
WR_DATA 0b00001000
WR_DDADR 0 ; Указатель на начало видео памяти (ячейка с координатми 0,0)
WR_DATA 0 ; У новоиспеченного символа код 0 напечатем его
После прошивки на экран ничего не выводится, почему не могу разобраться!?
Может что-то упустил.
А где инициализация порта A и E?
Инициализацию портов А и Е в основной программе я не делал, поскольку она должна выполняться после вызова макроса «INIT_LCD», в подпрограммах «InitHW» и «PortIn».
Фрагмент кода из «LCD_macro.inc»:
; Init Config
.MACRO INIT_LCD
RCALL InitHW
WR_CMD (1<<LCD_F)|(1<<LCD_F_8B)|(1<<LCD_F_2L)
WR_CMD(1<<LCD_CLR)
WR_CMD (1<<LCD_ENTRY_MODE)|(1<<LCD_ENTRY_INC)
WR_CMD (1<<LCD_ON)|(1<<LCD_ON_DISPLAY)|(0<<LCD_ON_CURSOR)|(0<<LCD_ON_BLINK)
WR_CMD(1<<LCD_HOME)
.ENDM
; Set DATA Port IN
.MACRO LCD_PORT_IN
RCALL PortIn
.ENDM
Фрагмент кода из «LCD.asm»:
;=========== LCD Define =========
.equ DATA_PORT = PORTA ;Объявление порта данных
.equ DATA_PIN = PINA
.equ DATA_DDR = DDRA
.equ CMD_PORT = PORTE ;Объявление порта управления
.equ CMD_PIN = PINE
.equ CMD_DDR = DDRE
.equ E = 2 ;Объявление битов порта управления, в соот. со схемой подключения
.equ RW = 1
.equ RS = 0
.equ SPEED = 6
;=========== LCD Proc ==============
InitHW:
CBI CMD_PORT,RS ; Инициализация порта Е
CBI CMD_PORT,RW
CBI CMD_PORT,E
SBI CMD_DDR,RS
SBI CMD_DDR,RW
SBI CMD_DDR,E
LCD_PORT_IN
RET
;===================================
PortIn: ; Инициализация порта А
LDI R16, 0 ; LCD Data Port
OUT DATA_DDR, R16 ; Выставить на вход
LDI R16, 0xFF ; Установить подтяжку
OUT DATA_PORT, R16
RET
Правильно ли я все понял?
Да, все верно вроде бы.
Добрый день!
DI HALT кажись я нашел у тебя ошибку в п/п BusyWait.
BusyWait: ;LCD_PORT_IN
CBI CMD_PORT,RS
SBI CMD_PORT,RW
BusyLoop: SBI CMD_PORT,E
RCALL LCD_Delay
CBI CMD_PORT,E //рано сбрасываешь единичку
IN R16,DATA_PIN //прочитает непонять что (у меня в таком случае на этой ноге весит всегда единица)
ANDI R16,0×80
BRNE BusyLoop
CBI CMD_PORT,E // надо бы тут
RET
Т.е. чтение инфы с ЖК-модуля корректно тогда, когда на RW и на E единицы. А у тебя не так. И получается что перехода на BusyLoop у тебя не происходит.
Проверь полуйста!
С увжением.
Да и выход из п/п необходимо осуществлять если флаг BF=0 а не 1.
В документации к hd447 написано, что BF=1 в случае когда модуль занят, а 0 — соответственно наоборот.
Работает же.
Ну в принципе модуль может работать и без проверки флага занятости, если выдерживается какая-то пауза. Так и получается в твоем случае. Но производитель все-же рекомендует проверять его. Хотя, конечно это мелочи :)
Ну я не проверял досконально, мож оно и так. Но на всех дисплеях работало на ура.
.include «LCD4_macro.inc»
.include «LCD4.asm»
.include «m16def.inc»
INIT_LCD
WR_CGADR 0
WR_DATA 0b00000001
WR_DATA 0b00000010
WR_DATA 0b00000100
WR_DATA 0b00011111
WR_DATA 0b00000010
WR_DATA 0b00000100
WR_DATA 0b00001000
WR_DDADR 0
WR_DATA 0
Компилирую заливаю и на экране вижу только 1 ряд черных квадратиков. Подскажите что не то делаю.