Управляем ЖК дисплеем HD44780 с помощью ассемблера

в 15:09, , рубрики: ATmega8, diy или сделай сам, hd44780, ассемблер, метки: , ,

В университете на одном профильном предмете начали изучать стенд на основе микроконтроллера МК-51, дисплея HD44780, клавиатуры. Все это дело программируется через COM порт с помощью ассемблера. На тот момент я изучат микроконтроллеры семейства AVR (а именно Atmega8), поэтому появилось желание научиться инициализировать и выводить на экран какую-нибудь информацию с помощью ассемблера без применения библиотек. После продолжительных поисков нашел только то, как дисплей запрограммировать на языке C с помощью библиотек, в которых не совсем понятно, что происходит. Поэтому было принято решение написать код самому, с использованием ассемблерных команд. Дисплей 0802, две строки.

Первым делом нужно было собрать устройство, на котором можно было потренироваться, но так как на тот момент у меня была платка от другой «игрушки», грех было не воспользоваться этой платой, так как обвязка МК в обоих схемах почти идентичная. Исходная схема платы ниже:

Управляем ЖК дисплеем HD44780 с помощью ассемблера

Дальше нужно было подключить дисплей, у нас даже остается 2 не задействованных вывода ( PD0, PD1). Все программируется через JTAG (X1). Соединял дисплей по этой схеме:
Управляем ЖК дисплеем HD44780 с помощью ассемблера
Я решил использовать 4 битный режим передачи, как я тогда думал, что его осуществить будет легче. Схему пришлось изменить ввиду отсутствия светодиодной подсветки (нет 15 и 16 вывода на дисплее), также убрал не нужный мне светодиодный индикатор (D1, R2). Питал всю схему и дисплей от аккумулятора от сотового.

В итоге у меня получилось это:

Управляем ЖК дисплеем HD44780 с помощью ассемблера

Управляем ЖК дисплеем HD44780 с помощью ассемблера

Управляем ЖК дисплеем HD44780 с помощью ассемблера
Плату изготавливал с помощью ЛУТ (лазерно утюжный метод)

Настало время программной части. Программу писал на AVRstudio

Код

.include <m8def.inc>

#define RS 2							//RS=PD2
#define E  3							//E=PD3
.def temp = r16
rjmp reset

.org 40
reset: 	
	ldi r16, HIGH(RAMEND)		;настройка стека
	out SPH,r16
	ldi r16,LOW(RAMEND)
	out SPL,r16

	ldi r16,0xfc					;настройка ножек PD2-PD7 на выход
	out ddrd,r16
	ldi r16,0x00
	out portd,r16

	rcall LCD_init
	sbi portb,6				;пишем данные
	rcall LCD_dat

	rjmp loop

LCD_init:	
	ldi temp,0x30			;управляющее слово
	rcall LCD_com1			;вызов программы ввода
	ldi temp,0x30
	rcall LCD_com1
	ldi temp,0x30
	rcall LCD_com1

	ldi temp,0x20			;4 бит режим
	rcall LCD_com1
	ldi temp,0x20			
	rcall LCD_com

	ldi temp,0x0c	
	rcall LCD_com

	ldi temp,0x06
	rcall LCD_com

	ldi temp,0x01
	rcall LCD_com
	ret

LCD_dat:
	ldi ZL, LOW(DB << 1)
	ldi ZH, HIGH(DB << 1)
	ldi r21,8					;количество элементов в массиве
m1:	lpm temp, Z+
	rcall LCD_com
	dec r21
	cpi r21,0
	brne m1	
	ret

LCD_com:	
	ldi r24,(0<<RS)|(1<<E)
	sbic portb,6
	ldi r24,(1<<RS)|(1<<E)
	out portD,r24

	mov r23,temp
	andi temp,0b11110000			;вырываем старшую тетраду

	or temp,r24						;суммируем с E и RS
	out portD,temp
	ldi r24,(0<<RS)|(0<<E)
	out portD,r24					;выводим

	rcall func_delay

	ldi r24,(0<<RS)|(1<<E)
	sbic portb,6
	ldi r24,(1<<RS)|(1<<E)
	out portD,r24

	andi r23,0b00001111				;вырываем младшую тетраду
	swap r23
	mov temp,r23

	or temp,r24						;суммируем с E и RS
	out portD,temp					;выводим
	ldi r24,(0<<RS)|(0<<E)
	out portD,r24

	rcall func_delay
	ret

LCD_com1:	
	ldi r24,(0<<RS)|(1<<E)
	out portD,r24
	or temp,r24
	out portD,temp
	ldi r24,(0<<RS)|(0<<E)
	out portD,r24
	rcall func_delay
	ret

loop: rjmp loop

func_delay: 						;задержка
	ldi r17,0x20
	ldi r18,0x00
func_delay_subb:
	subi r18,1
	sbci r17,0
	brcc func_delay_subb
	ret

DB: .db 0xA8,0x70,0x65,0xB3,0x65,0xE0,0x3A,0x29			;массив символов

Программу старался писать не отходя от алгоритма приведенного в даташите.
Пришлось сделать разделение на подпрограммы LCD_com1 и LCD_com, так как не получалось отправлять команды настройки и коды символов через одну подпрограмму.
Если нужно выводить на вторую строку тоже нужно добавить эти строки:

	cbi portb,6				;пишем команды на  вторая строку, начало строки
	ldi temp,0xc2			    
	rcall LCD_com
	sbi portb,6				;пишем данные
	rcall LCD_dat	

Однако, по непонятным мне причинам при выводе на экран информации в 2х строчный режим контрастность сильно снижается.

Коды символов нужно брать из таблицы и заносить в массив, не забывая про ограничение размеров экрана
Управляем ЖК дисплеем HD44780 с помощью ассемблера

В дальнейшем планируется применить навыки на практике, термометр на процессоре, реобас или еще где-нибудь

Исходный код проекта:
dl.dropbox.com/u/77527472/LCDasm.zip
В нем подключена кнопка на ресет, при нажатии, содержимое дисплея обновляется
Даташит на дисплей
dl.dropbox.com/u/77527472/wh1602-datasheet.pdf
Даташит на микроконтроллер, там же есть система команд на него
dl.dropbox.com/u/77527472/ATmega8(L).pdf

ps: пост первый, поэтому принимаю всю критику в свою сторону, постараюсь в дальнейшем все учесть

Автор: CryENG

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js