Задача
Инициализировать дисплей и вывести на него текст.
Микроконтроллер: ATmega8, кварц 4 МГц. Среда: Atmel Studio / avra (или avra / Atmel Studio). Как настроить среду и прошить контроллер — в статье программирование AVR.
Что понадобится
- ATmega8
- кварц 8 МГц + 2×22 пФ
- дисплей 16×2 на HD44780
- подстроечный резистор 10 кОм (контрастность)
Схема подключения
| Вывод | Подключение |
|---|---|
| PD4…PD7 | линии данных дисплея D4…D7 |
| PD2 | вывод RS |
| PD3 | вывод E (строб) |
| RW дисплея | на GND |
| V0 дисплея | средний вывод подстроечника контрастности |
Алгоритм
- Выдержать паузу после подачи питания.
- Трижды послать 0x30, затем 0x20 — переход в четырёхбитный режим.
- Задать формат, включить дисплей, очистить экран.
- Байт передавать двумя полубайтами со стробом на линии E.
Листинг на ассемблере
Код проверен ассемблером и собирается без ошибок. Скачать: a14.asm · a14.hex (готовая прошивка).
;=======================================================
; Проект 14. LCD HD44780 в 4-битном режиме
; ATmega8, 8 МГц
; PD4..PD7 — шина данных D4..D7, PD2 — RS, PD3 — E
; Вывод RW дисплея — на GND
;=======================================================
.include "m8def.inc"
.equ LCD_RS = PD2
.equ LCD_E = PD3
.def temp = r16
.def chr = r17
.def d1 = r18
.def d2 = r19
.cseg
.org 0x0000
rjmp RESET
RESET:
ldi temp, low(RAMEND)
out SPL, temp
ldi temp, high(RAMEND)
out SPH, temp
ldi temp, 0xFC ; PD2..PD7 — выходы
out DDRD, temp
clr temp
out PORTD, temp
rcall DELAY20MS ; ждём готовности дисплея
rcall LCD_INIT
ldi chr, 'A'
rcall LCD_DATA
ldi chr, 'V'
rcall LCD_DATA
ldi chr, 'R'
rcall LCD_DATA
STOP: rjmp STOP
LCD_INIT:
ldi temp, 0x30 ; трижды 8-битная команда
rcall SEND_NIBBLE
rcall DELAY5MS
ldi temp, 0x30
rcall SEND_NIBBLE
rcall DELAY5MS
ldi temp, 0x30
rcall SEND_NIBBLE
rcall DELAY5MS
ldi temp, 0x20 ; переход в 4-битный режим
rcall SEND_NIBBLE
rcall DELAY5MS
ldi chr, 0x28 ; 4 бита, 2 строки, шрифт 5x8
rcall LCD_CMD
ldi chr, 0x0C ; дисплей вкл, курсор выкл
rcall LCD_CMD
ldi chr, 0x06 ; сдвиг курсора вправо
rcall LCD_CMD
ldi chr, 0x01 ; очистка
rcall LCD_CMD
rcall DELAY5MS
ret
LCD_CMD:
cbi PORTD, LCD_RS
rjmp SEND_BYTE
LCD_DATA:
sbi PORTD, LCD_RS
SEND_BYTE:
mov temp, chr
andi temp, 0xF0 ; старший полубайт
rcall SEND_NIBBLE
mov temp, chr
swap temp ; младший полубайт наверх
andi temp, 0xF0
rcall SEND_NIBBLE
rcall DELAY5MS
ret
;--- выдать полубайт из старших бит temp ---
SEND_NIBBLE:
push r20
in r20, PORTD
andi r20, 0x0F ; сохраняем RS и E
or temp, r20
out PORTD, temp
sbi PORTD, LCD_E ; строб
nop
nop
cbi PORTD, LCD_E
pop r20
ret
DELAY5MS:
ldi d2, 52
W2: ldi d1, 255
W1: dec d1
brne W1
dec d2
brne W2
ret
DELAY20MS:
rcall DELAY5MS
rcall DELAY5MS
rcall DELAY5MS
rcall DELAY5MS
ret
Пояснения
- Команда
swapменяет полубайты местами за один такт — в AVR это делается элегантнее, чем на PIC. - Младшие биты порта маскируются при выдаче полубайта, чтобы не сбить состояние RS и E.
- Регистр r20 в подпрограмме сохраняется через
pushиpop— стек уже инициализирован, поэтому это безопасно.
Что дальше
Разобравшись с этим проектом, переходите к следующему в разделе проекты на PIC. Справочник по архитектуре и периферии контроллеров — на странице микроконтроллеры AVR.