Программировании дисплея на контроллере ST7920

от автора

Хочу рассказать о программировании дисплея на контроллере ST7920 с использованием ATtiny2313 контроллера.


Этот дисплей имеет 2 режима работы:

  • Графический
  • Текстовый

И имеет 3 режима подключения:

  1. Подключение по 8 битной шине
  2. Подключение по 4 битной шине
  3. Подключения по SPI (3 или 2 битной шине)

В данном посте я расскажу о:

  • Работе в текстовом режиме
  • Подключения и программирование по 8 битной шине
  • Подключения и программирование по SPI

Для того что бы подключить дисплей к контроллеру нам понадобится:

  1. Дисплей на контроллере ST7920
  2. 2 подстрочных резистора на 320 Ом.
  3. Для 8 битного режима резистор на 4.7 кОм (или больше)
  4. Контроллер ATtiny2313
  5. Источник питание на 5В.

Схема подключения

Подключение по 8 битной шине данных


Распиновка контактов:
GND — Земля
VCC — +5В
V0 — Настройка контрастности
RS — Определяет режим передачи данных (1 — это данные, 0 — это команда)
RW — Запись или чтения (1 — чтения, 0 — запись)
E — Строб
D0-D7 — Шина данных
PSB — Определяет какой протокол передачи данных будет использоваться ( 1 — 8/4 бит шина, 0 — SPI)
BLA — Анод подсветки (+)
BLK — Катод подсветки (-)

Подключение по SPI


Распиновка контактов:
GND — Земля
VCC — +5В
V0 — Настройка контрастности
RS — (CS) Разрешает и запрещает дисплею принимать данные (1 — Запрещает, 0 — Разрешает)
RW — (SID) Шина данных
E — (SCLK) Строб
PSB — Определяет какой протокол передачи данных будет использоваться ( 1 — 8/4 бит шина, 0 — SPI)
BLA — Анод подсветки (+)
BLK — Катод подсветки (-)

Подстроечные резисторы

RP1 — Регулятор контрастности
RP2 — Регулятор яркости

Описание протоколов программирования дисплея

8 битный режим

И так, с начало я расскажу о том как в общих чертах происходит работа с дисплеем.
Для того что бы работать с дисплеем нам нужно отправлять команды и данные на дисплей.
К командам относится: Включения/выключение дисплея, отображение курсора, перемещение курсора и т.д. К данным относятся например символы которые вы хотите видеть на дисплее.

Давайте рассмотрим пример того как производится инициализация для 8 битного режима.
Давайте рассмотрим пример того как производится инициализация:

  • Задержка в 50 мкс.
  • Отправляем команду установки 8 битного режима.
  • Задержка 120 мкс.
  • Отправляем команду включения дисплея ( в ней же указывается, включить ли курсор, и мигать ли курсором)
  • Задержка в 50 мкс.
  • Повторно отправляем функцию установки 8 битного режима
  • Задержка 120 мкс.
  • Отправляем команду отчистить экран
  • Задержка 20 мкс.
  • Устанавливаем ENTRY MODE (эта команда говорит о том в какую сторону сдвигать курсор после написания символа, нам соответственно нужно вправо)

Вот и все, после выполнения этих действий, если вы указали в команде включения дисплея отображать курсор, на экране вы увидите курсор.

Рассмотрим как отправить одну команду на дисплей в 8 битном режиме:

  • Устанавливаем низкий уровень E
  • Устанавливаем низкий уровень RS
  • Устанавливаем низкий уровень RW
  • Задержка 1 мкс.
  • Устанавливаем высокий уровень E
  • Отправляем в порт данных байт команды
  • Задержка 1 мкс.
  • Устанавливаем низкий уровень E
  • Задержка 50 мкс.

Для отправки одного байта данных выполняется абсолютно то же самое, только в начале устанавливается высокий
уровень RS.
RS = 0 Команда
RS = 1 Данные

Вот как отправляется один байт данных:

  • Устанавливаем низкий уровень E
  • Устанавливаем высокий уровень RS
  • Устанавливаем низкий уровень RW
  • Задержка 1 мкс.
  • Устанавливаем высокий уровень E
  • Отправляем в порт данных байт команды
  • Задержка 1 мкс.
  • Устанавливаем низкий уровень E
  • Задержка 50 мкс.

Давайте рассмотрим код отправки команды
Для начала установим константы что бы было удобнее:

.equ PCom = PORTD ; Управляющий порт к которому подключены RS, RW, E .equ PW = PORTB   ; Порт данных  .equ RS = 2       ; Контакт порта PCom к которому подключен RS .equ E = 0          ; Контакт порта PCom к которому подключен E .equ RW = 1       ; Контакт порта PCom к которому подключен RW .def Data = R18   ; Регистр используется для записи данных в порт 

Функция отправки команды:

;Перед вызовом функции в регистр Data нужно установить необходимую команду LCD12864_CommandOut:                ;Вывод команды на дисплей.        cbi  PCom,  E                ; Устанавливаем  низкий уровень E        cbi  PCom,  RS               ; Устанавливаем низкий  уровень RS        cbi  PCom,  RW		  ; Устанавливаем низкий уровень RW        LCD8_MACRO_DELAY 1, 1	  ; Задержка 1 мкс.        sbi  PCom,  E                ; Устанавливаем высокий  уровень E        out  PW,    Data             ; Отправляем в порт данных байт команды         LCD8_MACRO_DELAY 1, 1	  ; Задержка 1 мкс.        cbi  PCom,  E                ;  Устанавливаем низкий уровень E        LCD8_MACRO_DELAY 1, 50	  ; Задержка 50 мкс.        Ret 

Функция отправки данных:

;Перед вызовом функции в регистр Data нужно установить необходимую команду LCD12864_DataOut:                ;Вывод данных на дисплей.        sbi  PCom,  E                ; Устанавливаем  высокий уровень E        cbi  PCom,  RS               ; Устанавливаем низкий  уровень RS        cbi  PCom,  RW		  ; Устанавливаем низкий уровень RW        LCD8_MACRO_DELAY 1, 1	  ; Задержка 1 мкс.        sbi  PCom,  E                ; Устанавливаем высокий  уровень E        out  PW,    Data             ; Отправляем в порт данных байт команды         LCD8_MACRO_DELAY 1, 1	  ; Задержка 1 мкс.        cbi  PCom,  E                ;  Устанавливаем низкий уровень E        LCD8_MACRO_DELAY 1, 50	  ; Задержка 50 мкс.        Ret 

В коде был использован макрос LCD8_MACRO_DELAY, вот его код

; Пример макроса функции задержки в микросекундах .MACRO LCD8_MACRO_DELAY ; 1 параметр количество задержек, 2 параметр, количество микросекунд в задержки        ldi  Temp,  @0                       ldi  Temp1, @1      rcall  LCD12864_Delay .ENDM  ;Пример функции задержки для контроллера на 4 МГц. ;Функция имеет 2 параметра: ;R16 – Количество микросекунд ;R17 – Количество циклов по R16 микросекунд. LCD12864_Delay: 	push  R16     ;Сохраняем младшую задержку в ОЗУ. ES0: 	dec  R16       ;- задержка. 	cpi  R16,  0   ;Закончилась?     brne  ES0      ;Нет - еще раз. 	 	pop  R16      ;Да? Восстановить задержку. 	dec  R17      ;Отнять от "количества задержек" разряда. 	cpi  R17, 0   ;Количество задержек = 0?     brne  LCD12864_Delay                    ret 

Теперь рассмотрим команды инициализации дисплея в текстовом, 8 битном режиме:

Команда FUNCTION SET: 0 0 1 DL 0 RE 0 0
DL:

  • Если установлено 1 то устанавливаем 8 бит передачу данных
  • Если установлено 0 то устанавливается 4 бита передача данных

RE:

  • Если установлено 1 то устанавливается набор расширенных команд
  • Если установлено 0 то устанавливается набор базовых команд

Следующая команда это DISPLAY STATUS: 0 0 0 0 1 D C B
D:

  • Если установлено 1 то дисплей включен
  • Если установлено 0 то дисплей выключен

С:

  • Если установлено 1 то курсор включен
  • Если установлено 0 то курсор выключен

B:

  • Если установлено 1 то курсор будет мигать
  • Если установлено 0 то курсор не будет мигать

Следующая команда простая CLEAR – отчистка экрана: 0 0 0 0 0 0 0 1

И последняя команда это ENTRY MODE SET – установка направления движения курсора: 0 0 0 0 0 1 I/D S

  • Если I/D = 1 то курсор сдвигается вправо
  • Если I/D = 0 то курсор сдвигается влево

На основе этих четырех функций можно написать функцию инициализации дисплея:

LCD12864_Init:                      ;Инициализация дисплея. 	 LCD8_MACRO_DELAY 1, 50	; Задержка в 50 мкс. 	 Ldi Data, 0b00110000 	 rcall LCD12864_CommandOut  ; Отправляем команду установки 8 битного режима. 	 LCD8_MACRO_DELAY 1, 120    ; Задержка в 120 мкс. 	 Ldi Data, 0b00001111 	 rcall LCD12864_CommandOut ; Отправляем команду включения дисплея, включить курсор, мигать курсором          LCD8_MACRO_DELAY 1, 50    ; Задержка в 50 мкс. 	 Ldi Data, 0b00110000 	 rcall LCD12864_CommandOut  ; Отправляем команду установки 8 битного режима. 	 LCD8_MACRO_DELAY 1, 120    ; Задержка в 120 мкс. 	 Ldi Data, 0b00000001 	 rcall LCD12864_CommandOut  ; Отправляем команду отчистить экран          LCD8_MACRO_DELAY 1, 20      ; Задержка в 20 мкс. 	 Ldi Data, 0b00000110 	 rcall LCD12864_CommandOut   ; установка направления движения курсора вправо 	 LCD8_MACRO_DELAY 1, 50      ; Задержка в 50 мкс.     ret 

После выполнения инициализации на экране вы должны увидеть мигающий курсор.

Режим SPI

Теперь о функции приема передачи команды/данных по SPI.
В этом режиме участвуют 2 линии:

  • SID это контакт передачи данных, на дисплее он же RW
  • SCLK – это линия строб, на дисплее он же E

В SPI режиме передача одной команды или 1 байта данных происходит при передачи 24 бит
Протокол передачи данных таков:

  • Передаем 4 единицы подряд
  • Передаем 1 бит RW – чтения или запись
  • Передаем 1 бит RS – Команда или данные
  • Передаем 0
  • Передаем 4 бита старшей половины байта данных
  • Передаем 4 нуля
  • Передаем 4 бита младшей половины байта данных
  • Передаем 4 нуля подряд

На этом передача одного байта завершена.

После каждого переданного бита делается строб, то есть:

  • Задержка 1 мкс.
  • Устанавливаем высокий уровень SCLK
  • Задержка 1 мкс.
  • Устанавливаем низкий уровень SCLK
  • Задержка 1 мкс.

Рассмотрим функцию передачи команды/данных в режиме SPI, но сперва объявим константы:

.equ PCom = PORTD ; Управляющий порт к которому подключены SID и SCLK  .equ SID = 1 ; RW Шина данных .equ SCLK = 0; E Строб .def Data = R18   ; Регистр используется для записи данных в порт 

А теперь сама функция:

/************************************* Функции отправки команды и данных по последовательному порту 	LCD12864_CommandOut - Отправляет команду 	LCD12864_DataOut    - Отправляет данные  	Команда или данные должны находится в регистре Data **************************************/ LCD12864_CommandOut: 	ldi r20, 0 	rjmp command LCD12864_DataOut: 	ldi r20, 1	  command:	       	LCD8_MACRO_DELAY 1, 1 	sbi PCom, SID ; Устанавливаем SID В 1     ; Шлем 4 единицы 	rcall strob ; 1 	rcall strob ; 1 	rcall strob ; 1 	rcall strob ; 1 	rcall strob ; 1     ; Устанавливаем rw на запись 	cbi PCom, SID  ; rw = 0 	rcall strob      ; Выберем, команда или данные и отправим ее. 	cbi PCom, SID  ; rs = 0     cpi r20, 0 	breq command1 	sbi PCom, SID  ; rs = 1 command1: 	rcall strob      ; Отправляем 0 	cbi PCom, SID  ; 0   	rcall strob      ; Началась отправка байта 	ldi r20, 8    ; Счетчик бит for_send_data: 	cpi r20, 0  ; Смотрим не закончились ли биты? 	breq  stop_send_data ; Если закончились то переходим к отправки последних нулей 	cpi r20, 4    ; Смотрим, если было отправлено 4 бита то выполняем отправку 4 нулей. 	brne  no_strob ; Иначе переходим к отправки следующего бита      ; Отправка 4 нуля 	cbi PCom, SID 	rcall strob 	rcall strob 	rcall strob 	rcall strob      ;Отправка следующего бита no_strob: 	dec r20 ; Уменьшаем счетчик бит 	rol		Data ; Сдвигаем регистр с данными на 1 влево 	brcs  send_bit_1 ; Если сдвинутый регистр был 1, то флаг C был поднят, а значит переходим на отправку бита 1     ; Если флаг С не был поднят, отправляем 0 	cbi PCom, SID ; Данные 0 бит 	rcall strob 	rjmp for_send_data     ;Отправляем бит 1 send_bit_1: 	sbi PCom, SID ; Данные 1 бит 	rcall strob 	rjmp for_send_data stop_send_data:      ; Отправка байта закончилась, отправляем 4 нуля 	cbi PCom, SID  	rcall strob 	rcall strob 	rcall strob 	rcall strob 	cbi PCom, SID  	ret 

Функция строб:

strob: 	LCD8_MACRO_DELAY 1, 1 ; Задержка в 1 мкс 	sbi PCom, SCLK	                   ; Устанавливаем высокий уровень SCLK 	LCD8_MACRO_DELAY 1, 1 ; Задержка в 1 мкс 	cbi PCom, SCLK                     ; Устанавливаем низкий уровень SCLK 	LCD8_MACRO_DELAY 1, 1 ; Задержка в 1 мкс 	ret .endif ;****************************************************** 

Текстовый режим

Теперь после того как вы научились инициализировать дисплей вы можете выводить любые символы на экран, например вывести букву A:

     ldi  Data,  'A'      rcall  LCD12864_DataOut 

И на дисплее вы увидите букву A.

И так, теперь о том как устроенно адресное пространство в текстовом режиме:
Экран делится на 8 столбцов и 4 строки, в каждый столбец вы можете записать по 2 обычных символа или 1 иероглиф.
Адресное пространство находится от 0 до 31.

0 1 2 3 4 5 6 7
16 17 18 19 20 21 22 23
8 9 10 11 12 13 14 15
24 25 26 27 28 29 30 31

Как видите первая строчка это адреса от 0 до 7
Вторая же строчка от 16 до 23
Третья строчка от 8 до 15
То есть если вы напишете 16 букв подряд с адреса 0, то они будут в первой строчке,
но если вы напишите 17 символов, то последний символ будет не на второй строчке, а на третей!

Есть специальная функция установки адреса курсора: 1 AC6 AC5 AC4 AC3 AC2 AC1 AC0
С помощью этой команды можно поставить курсор в нужное место вписав за место AC0-AC6 адрес от 0 до 31.

Графический режим

И напоследок, для тех кто хочет использовать графический режим, есть такая статья: LCD 12864 на контроллере ST7920. Параллельный режим (8 бит)

Библиотека для работы с ST7920

Ссылка на файл библиотеки

ссылка на оригинал статьи http://habrahabr.ru/post/213459/


Комментарии

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

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