Задача
Вывести две текстовые строки — по одной на каждую строку дисплея.
Микроконтроллер: 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 |
Алгоритм
- Разместить строки в памяти программ директивой
.dbс нулевым байтом в конце. - Установить курсор в начало строки командой 0x80.
- Читать символы командой
lpm chr, Z+до нулевого байта. - Перевести курсор командой 0xC0 и повторить для второй строки.
Листинг на ассемблере
Код проверен ассемблером и собирается без ошибок. Скачать: a15.asm · a15.hex (готовая прошивка).
;=======================================================
; Проект 15. Вывод строк на LCD из памяти программ
; ATmega8, 8 МГц. PD4..PD7 — D4..D7, PD2 — RS, PD3 — E
;=======================================================
.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
STR1: .db "AFON radio", 0, 0
STR2: .db "ATmega8 asm", 0
RESET:
ldi temp, low(RAMEND)
out SPL, temp
ldi temp, high(RAMEND)
out SPH, temp
ldi temp, 0xFC
out DDRD, temp
clr temp
out PORTD, temp
rcall DELAY20MS
rcall LCD_INIT
ldi chr, 0x80 ; начало первой строки
rcall LCD_CMD
ldi ZL, low(STR1<<1)
ldi ZH, high(STR1<<1)
rcall PRINT
ldi chr, 0xC0 ; начало второй строки
rcall LCD_CMD
ldi ZL, low(STR2<<1)
ldi ZH, high(STR2<<1)
rcall PRINT
STOP: rjmp STOP
;--- печать строки из flash, адрес в Z, конец — нулевой байт ---
PRINT:
lpm chr, Z+
tst chr
breq PR_END
rcall LCD_DATA
rjmp PRINT
PR_END: ret
LCD_INIT:
ldi temp, 0x30
rcall SEND_NIBBLE
rcall DELAY5MS
ldi temp, 0x30
rcall SEND_NIBBLE
rcall DELAY5MS
ldi temp, 0x30
rcall SEND_NIBBLE
rcall DELAY5MS
ldi temp, 0x20
rcall SEND_NIBBLE
rcall DELAY5MS
ldi chr, 0x28
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
SEND_NIBBLE:
push r20
in r20, PORTD
andi r20, 0x0F
or temp, r20
out PORTD, temp
sbi PORTD, LCD_E
nop
nop
cbi PORTD, LCD_E
pop r20
ret
DELAY5MS:
ldi d2, 52
X2: ldi d1, 255
X1: dec d1
brne X1
dec d2
brne X2
ret
DELAY20MS:
rcall DELAY5MS
rcall DELAY5MS
rcall DELAY5MS
rcall DELAY5MS
ret
Пояснения
- Автоинкремент
Z+сам продвигает указатель — цикл печати получается на три команды короче, чем на PIC. - Адреса строк HD44780 не идут подряд: первая начинается с 0x00, вторая — с 0x40, отсюда команды 0x80 и 0xC0.
- Строка в
.dbдолжна содержать чётное число байт, иначе ассемблер добавит выравнивающий ноль — это учтено дополнительным нулём.
Что дальше
Разобравшись с этим проектом, переходите к следующему в разделе проекты на PIC. Справочник по архитектуре и периферии контроллеров — на странице микроконтроллеры AVR.