Применение знакосинтезирующих индикаторов фирмы Data Vision

№ 7’2001
При разработке микроконтроллерных устройств перед разработчиком ставится задача, какую микросхему использовать при проектировании. Выбор микроконтроллеров (МК) довольно широк, а возможности, как правило, примерно одинаковы.

При разработке микроконтроллерных устройств перед разработчиком ставится задача, какую микросхему использовать при проектировании. Выбор микроконтроллеров (МК) довольно широк, а возможности, как правило, примерно одинаковы. Автор использовал МК PIC16F873 фирмы Microchip, а также ЖКИ DV-16230 фирмы Data Vision. Описание этого микроконтроллера можно найти на www.microchip.com. При проектировании использовалась среда разработки MPLAB с ее базовым языком ассемблером. Нередко можно услышать, что этот язык устарел и что предпочтительнее использовать современный язык программирования — С. Но, как мы увидим далее, используя макросы и подпрограммы, ассемблер не так уж плох. Причем, можно создавать вполне читаемый текст, если сформировать для себя «правила» программирования и придерживаться их.

Рис 1. Схема подключения МК и ЖКИ

На рис. 1 представлена схема подключения МК и ЖКИ. На схеме видна разбросанность выводов на МК, которые соединяются с ЖКИ. Это связано только с тем, что микросхема на макетной плате отрабатывалась для другого устройства и временно была переориентирована на работу с ЖКИ. Для связи МК с контроллером ЖКИ используется семь выводов. Три из них (RS, R/W, E) — управляющие, они настроены на вывод. Остальные (DB4-DB7) служат для передачи данных — эти выводы в процессе работы программа настраивает и на ввод, и на вывод. Для работы используется 4-разрядная шина. Для более детального ознакомления с командами контроллера ЖКИ можно обратиться к литературе [2].

Обозначим параметры:

#define LCD_E PORTA, 5 ;Сигнал разрешения

#define LCD_RW PORTB, 0 ;Запись/Чтение

#define LCD_RS PORTC, 0 ;Выбор режима работы

#define LCD_DB0 PORTC, 1 ;Шина данных 4

#define LCD_DB1 PORTC, 3 ;Шина данных 5

#define LCD_DB2 PORTC, 4 ;Шина данных 6

#define LCD_DB3 PORTC, 5 ;Шина данных 7

;

LevelLCDLine1 EQU 0xA0; массив данных, отображенных в LCD индикаторе линия 1

LevelLCDLine2 EQU 0xB0; массив данных, отображенных в LCD индикаторе линия 2

LevelLCDLine3 EQU 0xC0

;

#define bLCDWrite theLCDVector, 0 ; (1) — запись данных (0) — команды

#define bLCD_BF theLCDVector, 1 ; флаг занятости LCD

#define bLCD_Work theLCDVector, 2 ; готовность LCD к работе

;

; — параметры входа в «Метод Записи Информации в Область Отображения»

#define bCreateLine theLCDVector1Create, 0

; (0) — линия вывода 1

; (1) — линия вывода 2

;

; — параметры «Сдвиг выведенной информации»

#define bLCDGoWindowActiv theLCDGoWindowVector, 0

; (1) — включено

#define bLCDGoWindowTwo theLCDGoWindowVector, 1

; (0) — информация выводится только в конкретную строчку

; (1) — информация с первой строчки переходит на вторую

#define bLCDGoWindowLine theLCDGoWindowVector, 2

; (0) — линия вывода 1

; (1) — линия вывода 2

#define bLCDGoWindowCircle theLCDGoWindowVector, 3

; (0) — смещение информации

; (1) — циклический вывод информации в заданной области

#define bLCDGoWindowGoing theLCDGoWindowVector, 4

; (0) — направление — ВПРАВО

; (1) — направление — ВЛЕВО

На рис. 2 показана структура памяти, выбранная автором. В контроллере ЖКИ расположена память ОЗУ, содержимое которой непосредственно отображается на поле ЖКИ. При желании из нее всегда можно считать и в нее можно записывать, создавая, таким образом, процедуры для работы с ЖКИ.

В настоящей статье использован следующий метод работы с памятью. В области памяти МК, в банке 1, отводится буфер, который содержит точную копию данных ОЗУ контроллера ЖКИ. Методы изменяют информацию в буфере, а по окончании выполнения преобразований, перезаписывают ОЗУ контроллера ЖКИ, когда он свободен. Может возникнуть вопрос: зачем так нерационально расходовать память. Расход памяти составляет 2ґ16 байт (размер поля ЖКИ). Автор исходил из того, что время выполнения методов (например, при смещении данных) значительно меньше, чем при работе непосредственно с памятью ОЗУ контроллера ЖКИ. Всю работу по преобразованию данных МК берет на себя, не затрагивая контроллер ЖКИ. За ним остается только задача вовремя выводить требуемую информацию.

Обозначим память в банке 0:

Cblock 0x20

; — переменные Метода Записи Информации в Область Отображения

theLCDUkazatelCreateH ; — указатель начала строки

theLCDUkazatelCreateL ; — указатель начала строки

theLCDVector1Create ; — параметры метода

; — внутренние переменные

theLCDDataCreateH ; high указателя предложения

theLCDDataCreateL ; low указателя предложения

theLCDDataAdresCreate ; указатель для косвенной записи информации в ОЗУ

theLCDDataCreatePosition ; отступ позиции от начала строчки

; — Сдвиг выведенной информации

theLCDGoWindowVector

theLCDGoWindowDataEnd

theLCDGoWindowAdrBegin

theLCDGoWindowAdrEnd

endc

Когда начинаешь считать последние оставшиеся байты в памяти программ, возникает мысль, что память используется неразумно и что код программы насыщен «водой». Возможный выход из такой ситуации — создание подпрограмм, которые уменьшают код, но загружают стек. Еще один способ — использование макросов, которые по своему образу и подобию создают код, незначительно отличающийся от исходного. Ниже приведены обозначения макросов.

1. Выбор банков. Этот макрос предназначен для простоты восприятия кода программы и часто оберегает от лишних ошибок.

bank0 macro

bcf STATUS, RP0

bcf STATUS, RP1

endm

bank1 macro

bsf STATUS, RP0

bcf STATUS, RP1

endm …

2. Вывод текста. Макрос предназначен для позиционного вывода информации в область памяти буфера. Ниже приведен макрос вывода слов в строку 1, по аналогии строится макрос вывода в строку 2.

Вывеcти_текст_в_строку_1 macro LabelH, LabelL, position

bcf bCreateLine

Вывести_текст position

endm



Вывести_текст macro position

movlw position

movwf theLCDDataCreatePosition

movlw LabelH

movwf theLCDUkazatelCreateH

movlw LabelL

movwf theLCDUkazatelCreateL

Call CreateWindowLCD

endm

3. Запись команды, константы, рабочего регистра в ЖКИ. Эти три макроса непосредственно посылают управляющие слова либо данные в контроллер ЖКИ.

Записать_команду_в_LCD macro command

movlw command

movwf theLCDdata

bcf bLCDWrite

call WriteLCD

endm

Записать_константу_в_LCD macro const

movlw const

movwf theLCDdata

bsf bLCDWrite

call WriteLCD

endm

Записать_W_в_LCD macro

movwf theLCDdata

bsf bLCDWrite

call WriteLCD

endm

Ниже обозначены подпрограммы.

1. Запись тетрады с предварительной проверкой загруженности контроллера ЖКИ. Процедура выводит младшие четыре бита на порты ввода-вывода, проверив предварительно, что контроллер ЖКИ готов к приему данных.

WriteLCDnibblov call ReadLCD_BF

bcf LCD_DB3

bcf LCD_DB2

bcf LCD_DB1

bcf LCD_DB0

btfsc theLCDdata, 0

bsf LCD_DB0

btfsc theLCDdata, 1

bsf LCD_DB1

btfsc theLCDdata, 2

bsf LCD_DB2

btfsc theLCDdata, 3

bsf LCD_DB3

bsf LCD_E

bcf LCD_E

Return

2. Запись данных/команд в ЖКИ. Данная процедура выводит байт в контроллер ЖКИ, предварительно разбив на тетрады.

WriteLCD btfsc bLCDWrite

bsf LCD_RS

swapf theLCDdata, F

call WriteLCDnibblov

swapf theLCDdata, F

call WriteLCDnibblov

bcf LCD_RS

Return

3. Формирование флага занятости контроллера ЖКИ. Процедура перенастраивает выводы DB4-DB7 на прием и производит опрос бита занятости контроллера ЖКИ. После прочтения бита занятости выводы DB4-DB7 восстанавливаются на вывод информации. Если контроллер ЖКИ готов к приему данных, то происходит выход из процедуры. В противном случае происходит повторный цикл опроса. Таким образом, если контроллер ЖКИ не работает, то будет иметь место бесконечный цикл.

ReadLCD_BF bcf bLCD_BF

clrf PORTC

bank1

movlw b’01111010′ ; 1, 3, 4, 5 — изменяются

movwf TRISC

bank0

bcf LCD_RS

bsf LCD_RW

bsf LCD_E

bcf LCD_E

btfsc LCD_DB3

bsf bLCD_BF

bsf LCD_E

bcf LCD_E

bcf LCD_RW

clrf PORTC

bank1

movlw b’01000000′

movwf TRISC

bank0

btfsc bLCD_BF

goto ReadLCD_BF

btfsc bLCDWrite

bsf LCD_RS

Return

4. Очистка поля ЖКИ (ОЗУ МК). Процедура очищает память буфера, записывая в него код символа, который соответствует пустому полю в фонтах контроллера ЖКИ.

ResetLCD movlw LevelLCDLine1

movwf FSR

ResetLCDNext bank1

movlw __

movwf INDF

bank0

incf FSR, F

movf FSR, W

sublw LevelLCDLine3

btfss STATUS, Z

Goto ResetLCDNext

Return

5. Очистка поля ЖКИ (ОЗУ контроллера ЖКИ). Эта процедура загружает указатель контроллера ЖКИ в начало блока памяти первой строки и далее записывает в него код символа, который соответствует пустому полю в фонтах контроллера ЖКИ. Не стоит забывать о том, что контроллер ЖКИ настроен на инкрементацию указателя после записи байта данных. Для второй строки нужно создать аналогичный макрос, перезаписав команду на b’11000000′.

Рис. 2. Распределение памяти

RewriteLCDLine1 Записать_команду_в_LCD b’10000000′

clrf theLCDschet

RewriteLCDLine1Next Записать_константу_в_LCD __

incf theLCDschet, F

btfss theLCDschet, 4

goto RewriteLCDLine1Next

Return

6. Перерисовка поля ЖКИ (ОЗУ МК => ОЗУ контроллера LCD). Данная процедура очень похожа на RewriteLCDLine1, различие состоит лишь в том, что байт данных берется из соответствующей ячейки памяти буфера. Тем самым эти процедуры производят непосредственную передачу данных из буфера в память контроллера ЖКИ.

UpdateLCDLine1 Записать_команду_в_LCD b’10000000′

movlw LevelLCDLine1

movwf FSR

clrf theLCDschet

UpdateLCDLine1Next bank1

movf INDF, W

bank0

Записать_W_в_LCD

incf FSR, F

incf theLCDschet, F

btfss theLCDschet, 4

goto UpdateLCDLine1Next

Return

7. Инициализация ЖКИ (выполняется непосредственно после загрузки МК). Она настраивает системный интерфейс контроллера ЖКИ на работу с 4-разрядной шиной. Таким образом, с 1 по 4 шаг работает 8-разрядная шина, а начиная с 5-го — 4-разрядная.

InitLCD

; — передается старшая часть байта команды

bcf LCD_RS ; — говорит о записи команды

; — 1

movlw 0x03

movwf theLCDdata

call WriteLCDnibblov

; — 2

call WriteLCDnibblov

; — 3

call WriteLCDnibblov

; — 4

; — установка 4-битной передачи

movlw 0x02

movwf theLCDdata

call WriteLCDnibblov

; — далее команды передаются байтами

; — 5 — установка размерности интерфейса

Записать_команду_в_LCD b’00101000′

; — 6 — выключение LCD

Записать_команду_в_LCD b’00001000′

; — 7 — очистка экрана

Записать_команду_в_LCD b’00000001′

; — 8 — адресный регистр установлен в 0x00

Записать_команду_в_LCD b’00000010′

; — 9 — установка направления движения курсора

Записать_команду_в_LCD b’00000110′

; -10 — включение экрана

Записать_команду_в_LCD b’00001110′

bsf bLCD_Work

В памяти ПЗУ контроллера ЖКИ прошиты фонты — рис. 3. Также существует возможность записи своих символов в ОЗУ контроллере ЖКИ (CG RAM) и использование их в дальнейшем. Коды ASCII символов не совпадают с кодировкой фонтов, прошитых в контроллере ЖКИ. Создадим свою таблицу интерпретации символов.

; — русский алфавит

_А_ EQU 0x31

_а_ EQU 0x61

_Б_ EQU 0xA0

_б_ EQU 0xB2



; — латинский алфавит

_A_ EQU 0x41

_a_ EQU 0x61

_B_ EQU 0x42

_b_ EQU 0x62



; — окончание фразы

__end_ EQU 0x2000

Запишем в память программ МК фразы, которые необходимо выводить в процессе работы программы.

Hello_World data _H_, _e_, _l_, _l_, _o_, __, _W_, _o_, _r_, _l_, _d_, _воскл_+__end_

Проверка data _П_, _р_, _о_, _в_, _е_, _р_, _к_, _а_+__end_

Для того чтобы вывести на ЖКИ строчку «Проверка» с отступом в три символа, необходимо записать следующую команду.

Вывести_текст_в_строку_1 high Проверка, low Проверка, .3

Ниже приведена классификация методов работы с информацией.1. Метод записи информации из памяти программ МК в буфер отображения на поле ЖКИ является механизмом выборки текстовой информации из области памяти программ. На начало строки источника указывают theLCDUkazatelCreateH и theLCDUkazatelCreateL. На начало строки приемника указывает theLCDDataCreatePosition и бит указателя строки bCreateLine. Конец строки определяется кодом __end_ , который извлекается из памяти программ вместе с данными.

;———————————————————————————

; вх. параметры:

; theLCDUkazatelCreateH ; — указатель начала строки high

; theLCDUkazatelCreateL ; — указатель начала строки low

; theLCDVector1Create ; — параметры метода

; используемые переменные:

; theLCDDataCreateH

; theLCDDataCreateL

; theLCDDataAdresCreate

; theLCDDataCreatePosition

;———————————————————————————

CreateWindowLCD movf theLCDDataCreatePosition, W

btfss bCreateLine

goto $+3

addlw LevelLCDLine2

goto $+2

addlw LevelLCDLine1

movwf FSR

CreateWindowLCDEnd movf theLCDUkazatelCreateH, W

bank2

movwf EEADRH

bank0

movf theLCDUkazatelCreateL, W

bank2

movwf EEADR

bank3

bsf EECON1, EEPGD

bsf EECON1, RD

nop

nop

bcf STATUS, C

bank2

movf EEDATA, W

bank0

movwf theLCDDataCreateL

bank2

movf EEDATH, W

bank0

movwf theLCDDataCreateH

;

movf theLCDDataCreateL, W

bank1

movwf INDF

bank0

incfsz theLCDUkazatelCreateL, F

goto $+2

incf theLCDUkazatelCreateH, F

incf FSR, F

btfss theLCDDataCreateH, 5

goto CreateWindowLCDEnd

;

btfss bCreateLine

goto $+3

Call UpdateLCDLine2

goto $+2

Call UpdateLCDLine1

bcf bCreateLine

Return ; Все, сообщение выведено.

2. Метод сдвига выведенных данных. При вызове этого метода осуществляется проверка битов настройки, которые расписаны выше в параметрах. Этот метод удобно использовать в обработчике прерываний, включая его в тот момент, когда он необходим. Он реализует механизм сдвига информации либо влево, либо вправо, работает с одной-двумя строками, может сдвигать информацию за экран, либо замыкать циклически ее вывод на ЖКИ. Все эти параметры определяются битами настройки метода.

;———————————————————————————

; вх. параметры

; theLCDGoWindowVector

; theLCDGoWindowDataEnd

; theLCDGoWindowAdrBegin

; theLCDGoWindowAdrEnd

;———————————————————————————

GoWindow btfss bLCDGoWindowActiv

goto GoWindowLineEnd

btfss bLCDGoWindowTwo

goto GoWindowOne

goto GoWindowTwo

; — для перерисовки одной строки

GoWindowOne btfss bLCDGoWindowLine

goto GoWindowLine1

goto GoWindowLine2

GoWindowLine1

Call RewriteLCDLine1

movlw LevelLCDLine1

movwf theLCDGoWindowAdrBegin

movlw LevelLCDLine2

movwf theLCDGoWindowAdrEnd

goto GoWindowLineGoing

GoWindowLine2

Call RewriteLCDLine2

movlw LevelLCDLine2

movwf theLCDGoWindowAdrBegin

movlw LevelLCDLine3

movwf theLCDGoWindowAdrEnd

goto GoWindowLineGoing

; — для перерисовки двух строк

GoWindowTwo

Call RewriteLCDLine1

Call RewriteLCDLine2

movlw LevelLCDLine1

movwf theLCDGoWindowAdrBegin

movlw LevelLCDLine3

movwf theLCDGoWindowAdrEnd

goto GoWindowLineGoing

; — Какое направление перерисовки ?

GoWindowLineGoing

btfss bLCDGoWindowGoing

goto GoWindowLineRIGHT

goto GoWindowLineLEFT

GoWindowLineLEFT

; — Как выводить информацию? Циклически или нет?

btfsc bLCDGoWindowCircle

goto GoWindowLineCircleLEFT

movlw __

goto GoWindowLineLEFT_A

GoWindowLineCircleLEFT

movlw .1

subwf theLCDGoWindowAdrEnd, W

movwf FSR

bank1

movf INDF, W

bank0

goto GoWindowLineLEFT_A

; — тело модуля

GoWindowLineLEFT_A

movwf theLCDGoWindowDataEnd

movf theLCDGoWindowAdrEnd, W

movwf FSR

decf FSR, F

GoWindowLineLEFT_B

decf FSR, F

bank1

movf INDF, W

incf FSR, F

movwf INDF

bank0

decf FSR, F

movf FSR, W

subwf theLCDGoWindowAdrBegin, W

btfss STATUS, Z

goto GoWindowLineLEFT_B

movf theLCDGoWindowDataEnd, W

bank1

movwf INDF

bank0

goto GoWindowLineall

GoWindowLineRIGHT

; — Как выводить информацию? Циклически или нет?

btfsc bLCDGoWindowCircle

goto GoWindowLineCircleRIGHT

movlw __

goto GoWindowLineRIGHT_A

GoWindowLineCircleRIGHT

movf theLCDGoWindowAdrBegin, W

movwf FSR

bank1

movf INDF, W

bank0

goto GoWindowLineRIGHT_A

; — тело модуля

GoWindowLineRIGHT_A

movwf theLCDGoWindowDataEnd

movf theLCDGoWindowAdrBegin, W

movwf FSR

GoWindowLineRIGHT_B

incf FSR, F

bank1

movf INDF, W

decf FSR, F

movwf INDF

bank0

incf FSR, F

movf FSR, W

addlw .1

subwf theLCDGoWindowAdrEnd, W

btfss STATUS, Z

goto GoWindowLineRIGHT_B

movf theLCDGoWindowDataEnd, W

bank1

movwf INDF

bank0

goto GoWindowLineall

; — перенести информацию на LCD-индикатор

GoWindowLineall

btfss bLCDGoWindowTwo

goto $+4

call UpdateLCDLine1

call UpdateLCDLine2

goto GoWindowLineEnd

btfsc bLCDGoWindowLine

goto $+3

call UpdateLCDLine1

goto $+2

call UpdateLCDLine2

goto GoWindowLineEnd

GoWindowLineEnd

Return

Рис 3. Русско-английские фонты

Как использовать данный метод. Пусть нам необходимо вывести строчку «Hello World!» с отступом в один символ и через 1 с смещать ее слева направо через весь экран в цикле. Необходимо выполнить следующую последовательность действий:

1. После инициализации ЖКИ (процедура InitLCD) вывести строку:

Call InitLCD

Вывести_текст_в_строку_1 high Hello_World, low Hello_World, .1

2. Настроить модуль метода сдвига. Биты конфигурации расписаны в параметрах.

movlw b’00011011′

movwf theLCDGoWindowVector

3. Организовать прерывания от любого таймера через 1. с и вызвать метод GoWindow.

Call GoWindow

Рис. 4

Таким образом, мы будем наблюдать перемещение фразы, как это показано на рис. 4.В данной статье затронут всего один способ вывода информации на ЖКИ. Можно придумать большое количество разнообразных вариантов. Чем оригинальнее производится вывод информации, тем приятнее работать с прибором. Ведь недаром западные разработчики уделяют столь большое внимание оформлению приборов, расходуя драгоценное время на «мелочи». Но именно на этих «мелочах», по мнению автора, и формируется отношение и к прибору, и, следовательно, к его разработчикам.

Литература

  • PIC16F87X. Data Sheet., Microchip Technology Inc., 1999.
  • Библиотека Электронных Компонентов. Жидкокристаллические индикаторы фирмы Data International. — М.: ДОДЭКА, 1999. — 64 c.
  • Электронные Компоненты. Каталог. — М.: Платан, 2000. С. 120.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *