You are on page 1of 36

PRELAB1

DIP SWITCH:
- Khai báo INPUT: DDR = 0, điện trở kéo lên: PORT = 1
- Đọc PIN ,1:OFF | 0:ON
BARLED/ LED:
- Khai báo OUTPUT: DDR=1
- Xuất PORT: 1:ON

.ORG 0
RJMP MAIN
.ORG 0X40
MAIN: LDI R16, 0x00
OUT DDRA, R16 //PORTA -INPUT -- DIP SW
LDI R16, 0xFF
OUT PORTA, R16 //DIEN TRO KEO LEN
OUT DDRB, R16 //PORTB -OUTPUT -- BAR LED
OUT PORTB, R16
START:
IN R17, PINA //PINA = 0 --> 0N -- LED SANG --> PB = 1
COM R17 //PB = NOT(PINA)
OUT PORTB, R17
RJMP START //TIEP TUC DOC PIN A

.ORG 0
RJMP MAIN

//--------------------------------------------------------
.ORG 0X40
MAIN:
LDI R16, 0x00
OUT DDRA, R16 //PORTA -INPUT -- DIP SW
LDI R16, 0xFF
OUT PORTA, R16 //DIEN TRO KEO LEN
OUT DDRB, R16 //PORTB -OUTPUT -- BAR LED
OUT PORTB, R16
LOOP:
IN R17, PINA //R17 <-- PINA(DIPSW)
LDI R16, 0x05 //R16 <-- 00000101
ADD R16, R17 //R16 <-- R16 + R17
OUT PORTB, R16 //PB(BARLED) <-- R16
RJMP LOOP

.ORG 0
RJMP MAIN

//--------------------------------------------------------
.ORG 0X40
MAIN:
LDI R16, 0x00
OUT DDRA, R16 //PORTA -INPUT -- DIP SW
LDI R16, 0xFF
OUT PORTA, R16 //DIEN TRO KEO LEN
OUT DDRB, R16 //PORTB -OUTPUT -- BAR LED
OUT PORTB, R16
LOOP: IN R17, PINA //R17 <-- PINA(DIPSW)
LDI R16, 0x0F //R16 <-- 00001111
AND R16, R17 //R16 <-- NIBBLE THAP
LDI R18, 0xF0 //R16 <-- 11110000
AND R18, R17 //R18 <-- NIBBLE CAO(BYTE CAO)
SWAP R18 //CHUYEN VE BYTE THAP
MUL R18, R16 // R1:R0 <-- NIBBLE CAO x NIBBLE THAP (KO DAU)
OUT PORTB, R0 //PB(BARLED) <-- R0 (BYTE THAP)
RJMP LOOP
TREN O DUOI 1 ( TUY BAI )
.ORG 0
RJMP MAIN

//--------------------------------------------------------
.ORG 0X40
MAIN:
LDI R16, 0x00
OUT DDRA, R16 //PORTA -INPUT -- DIP SW
LDI R16, 0xFF
OUT PORTA, R16 //DIEN TRO KEO LEN
OUT DDRB, R16 //PORTB -OUTPUT -- BAR LED
OUT PORTB, R16
LOOP:
IN R17, PINA //R17 <-- PINA(DIPSW)
LDI R16, 0x0F //R16 <-- 00001111
AND R16, R17 //R16 <-- NIBBLE THAP
SBRC R16, 3 //MO RONG BIT NEU LA SO AM
ORI R16, 0xF0
LDI R18, 0xF0 //R16 <-- 11110000
AND R18, R17 //R18 <-- NIBBLE CAO(BYTE CAO)
SWAP R18 //CHUYEN VE BYTE THAP
SBRC R18, 3 //MO RONG BIT NEU LA SO AM
ORI R18, 0xF0
MULS R18, R16 // R1:R0 <-- NIBBLE CAO x NIBBLE THAP (CO DAU)
OUT PORTB, R0 //PB(BARLED) <-- R0 (BYTE THAP)
RJMP LOOP
VD: -5X3
.ORG 0
CBI DDRA,0; PA0 is input
SBI DDRA,1; PA1 is output
SBI PORTA,0; enable pullup resistor
CBI PORTA,1; turn off the led

MAIN: IN R17,PINA
CPI R17,$00
BREQ PRESSED
CBI PORTA,1
RJMP MAIN
PRESSED: SBI PORTA,1
RJMP MAIN
.ORG 0
RJMP MAIN

//--------------------------------------------------------
.ORG 0X40
MAIN:
LDI R16, 0x01
OUT DDRA, R16 //PA0 -OUTPUT -- LED
LDI R16, 0xFF
OUT PORTA, R16 //DIEN TRO KEO LEN
LOOP:
RCALL DELAY1MS
CBI PORTA, 0 //TAT LED
RCALL DELAY1MS
SBI PORTA, 0 //BAT LED
RJMP LOOP
;{[(4x250-1)+4]x8-1 +1 +4(CALL) +4(RET) = 8032 MC sai so 32MC
;{[(4x249-1)+4]x8-1 +1 +4(CALL) +4(RET) = 8000 MC sai so 0MC
DELAY1MS: LDI R16, 8 ;1MC
LP1: LDI R17, 249 ;1MC
LP2: DEC R17 ;1MC
NOP ;1MC
BRNE LP2 ;2/1MC
DEC R16 ;1MC
BRNE LP1 ;2/1MC
RET ;4MC; CODE NAY LA DUNG

DELAY10MS: LDI R18, 10


LP3: CALL DELAY1MS
DEC R18
BRNE LP3
RET

DELAY100MS: LDI R18, 100


LP4: CALL DELAY1MS
DEC R18
BRNE LP4
RET
;1000 = 4x250
;{[(8002x250-1)+4]x4 -1 +1 +4(CALL) +4(RET) = 8002020 MC sai so 2020MC
DELAY1S: LDI R18, 4 ;1MC
LP5: LDI R19, 250 ;1MC
LP6: RCALL DELAY1MS;7999MC
DEC R19 ;1MC
BRNE LP6 ;2/1MC
DEC R18 ;1MC
BRNE LP5 ;2/1MC
RET ;4MC
; INPUT:R16 Thơi gian delay = R16.100us
DELAY_US:

MOV R15,R16 ;1MC n?p data cho R15


LDI R16,200 ;1MC s? d?ng R16
L1: MOV R14,R16 ;1MC n?p data cho R14
L2: DEC R14 ;1MC
NOP ;1MC
BRNE L2 ;2/1MC
DEC R15 ;1MC
BRNE L1 ;2/1MC
RET ;4MC
LAB1_2 Bài 3

Thanh ghi dịch sử dụng là 74HC595.

Các chân quan trọng cần nhớ

.ORG 0
RJMP MAIN
.ORG 0X40
MAIN:
LDI R16,HIGH(RAMEND);đưa stack lên vùng đ/c cao
OUT SPH,R16
LDI R16,LOW(RAMEND)
OUT SPL,R16
LDI R16,0X07 ;PB0=DS,PB1=CK dịch,PB2=CK xuất output
OUT DDRB,R16
CBI PORTB,1 ;CK dịch (SHCP = PB1) =0
CBI PORTB,2 ;CK xuất (STCP = PB2) =0
START:
LDI R16,8
SANG:
SBI PORTB,0
SBI PORTB,1
CBI PORTB,1
SBI PORTB,2
CBI PORTB,2
RCALL DELAY500MS
DEC R16
BRNE SANG
LDI R16,8
TOI:
CBI PORTB,0
SBI PORTB,1
CBI PORTB,1
SBI PORTB,2
CBI PORTB,2
RCALL DELAY500MS
DEC R16
BRNE TOI
RJMP START
DELAY1MS:
PUSH R16
PUSH R17
LDI R16, 8 ;1MC
LP1: LDI R17, 249 ;1MC
LP2: DEC R17 ;1MC
NOP ;1MC
BRNE LP2 ;2/1MC
DEC R16 ;1MC
BRNE LP1 ;2/1MC
POP R17
POP R16
RET ;4MC
DELAY500MS:
PUSH R18
PUSH R19
LDI R18, 2 ;1MC
LP5: LDI R19, 250 ;1MC
LP6: RCALL DELAY1MS;7999MC
DEC R19 ;1MC
BRNE LP6 ;2/1MC
DEC R18 ;1MC
BRNE LP5 ;2/1MC
POP R19
POP R18
RET ;4MC

Tên STT Loại Mô tả


/CLR 10 Input Chân clear dữ liệu trong 595, tích cực thấp (0 là
clear), nếu lập trình có yêu cầu dùng chân này thì
kết nối với VXL rồi set chân này lên 1, nếu muốn
clear thì cho xuống 0. Nếu không muốn lập trình
chân này thì cắm thẳng lên 5V.
SRCLK 11 Input Clock thanh ghi dịch, lấy cạnh lên (rising edge).
Các bạn hình dung trong con IC 595 có 1 thanh
ghi 8 bit, mỗi khi có cạnh lên, dữ liệu hiện tại có
trên chân SDI sẽ được dịch vào thanh ghi này.
VD: Sau khi clear 595, giả sử chân SDI luôn bằng
1, mỗi khi có clock trên chân SRCLK này, dữ liệu
trong thanh ghi sẽ thay đổi như sau:
0000 0000
1000 0000
1100 0000…

RCLK 12 Input Đây là Clock chốt, lấy cạnh lên.


Mỗi khi có cạnh lên, dữ liệu hiện tại chứa trong
thanh ghi 8 bit trong con 595 sẽ được đưa ra ngõ
ra ở các chân QA đến QH tương ứng.
SDI 14 Input Serial Data Input muốn đưa vào.
QA->QH Output Các bit out.
Để tạo hiệu ứng theo yêu cầu bài TN3, ta viết thứ tự thực hiện như sau:
Đảm bảo các chân SRCLK và RCLK = 0 ban đầu

SDI = 1 (đèn sáng)


SRCLK = 1 ; tạo xung cạnh lên đưa SDI =1 vào 595
SRCLK = 0
RCLK = 1 ; tạo xung chốt đưa dữ liệu ra QA đến QH
RCLK = 0
Delay 500 ms
Lập lại đoạn code trên 8 lần.

SDI = 0 (đèn tắt)


SRCLK = 1 ; tạo xung cạnh lên đưa SDI =0 vào 595
SRCLK = 0
RCLK = 1 ; tạo xung chốt đưa dữ liệu ra QA đến QH
RCLK = 0
Delay 500 ms
Lập lại đoạn code trên 8 lần.
Mở rộng để tham khảo cho các bài về sau. Giả sử có 8 bit được chứa trong R17=
A7A6A5A4 A3A2A1A0, cần đặt 8 bit này ra con 595 thì ta làm thế nào. (MSB đi đầu)
Đảm bảo các chân SRCLK và RCLK = 0 ban đầu
Đặt chân SDI = A7
SRCLK = 1 ; tạo xung cạnh lên đưa A7 vào 595
SRCLK = 0

Đặt chân SDI = A6


SRCLK = 1 ; tạo xung cạnh lên đưa A6 vào 595
SRCLK = 0

Đặt chân SDI = A0


SRCLK = 1 ; tạo xung cạnh lên đưa A0 vào 595
SRCLK = 0
RCLK = 1 ; tạo xung cạnh lên đưa dữ liệu ra QA đến QH.
RCLK = 0

Trên đây là các bước cơ bản để hiểu thôi, còn các bạn viết phải dùng vòng lập để
thực hiện việc này. Tham khảo đoạn code dưới đây, sửa từ ví dụ 10.26 trong giáo
trình. Trong ví dụ 10.26, 2 chân clock SRCLK và RCLK nối với nhau, code dưới đây có
sửa lại 1 tí.
//Khúc này gán các chân port, pin bằng từ khóa, vì phần cứng thay đổi linh động
được nên định danh như vậy dễ sửa đổi. Ví dụ nay kết nối port A, hôm sau phần
cứng lại kết nối port B thì chỉ cần đổi trong định danh, nhanh gọn không thiếu
xót.
.EQU shiftPORT=PORTA
.EQU ShiftDDR=DDRA
.EQU ShiftSDI=0 ;SDI => PA0
.EQU ShiftCLK=1 ;SRCLK => PA1
.EQU ShiftLATCH=2 ;RCLK => PA2

.ORG 0
RJMP MAIN

.ORG 0X40
MAIN:
//Khai báo PA0, PA1, PA2 là output, giá trị khởi tạo là 0. Nên viết bằng từ
khóa định danh phía trên luôn nhé.

LDI R16,0XO3
OUT DDRA,R16

LOOP:

JMP LOOP

//--------------------------------------------------------
//Các Chương trình con
//--------------------------------------------------------
/* SHO_8
INPUT: R20
OUTPUT: QA đến QH trên IC595
Description:
*/
SHO_8:
LDI R20,9
SH_LOOP:
ROL R17
BRCC BIT_0
SBI shiftPORT,shiftSDI
RJMP NEXT
BIT_0:
CBI shiftPORT,shiftSDI
NEXT:
SBI shiftPORT,shiftCLK
CBI shiftPORT,shiftCLK
DEC R20
BRNE SH_LOOP
SBI shiftPORT,shiftLATCH
CBI shiftPORT,shiftLATCH
RET
LAB1_3 Bài 1

.EQU LCD_PORT=PORTA
.EQU LCD_DDR=DDRA
.EQU RS=0
.EQU RW=1
.EQU EN=2
.ORG 0
RJMP MAIN
.ORG 0X40
MAIN:
LDI R16,LOW(RAMEND) ;DUA DIA CHI RAMEND LEN VI TRI CAO NHAT
OUT SPL,R16
LDI R16,HIGH(RAMEND)
OUT SPH,R16
LDI R16,0XFF
OUT LCD_DDR,R16 ;khai báo PORTC là output
CBI LCD_PORT,RS ;RS=PCO=0
CBI LCD_PORT,RW ;RW=PC1=0 truy xuất ghi
CBI LCD_PORT,EN ;E=PC2=0 cấm LCD
RCALL POWERUP_LCD_4BIT ;reset cấp nguồn LCD 4 bit
RCALL INIT_LCD_4BIT ;ctc khởi động LCD 4 bit
CBI LCD_PORT,RS ;RS=0 ghi lệnh
LDI R17,$80 ;con trỏ bắt đầu ở dòng 1 vị trí thứ 1
RCALL WRITE_COMMAND
LDI R16,1 ;chờ 100μs
RCALL DELAY_US
//Dưới đây là đoạn code tra bảng, xuất ký tự hàng thứ 1 ra LCD cho đến khi gặp
ký tự 0x00
LDI ZH,HIGH(LINE1<<1)
LDI ZL,LOW(LINE1<<1)
DISPLAY_LINE1:
LPM R17,Z+
CPI R17,$00
BREQ NEWLINE
CALL WRITE_DATA
RJMP DISPLAY_LINE1
NEWLINE:
//Viết lệnh xuống hàng (lệnh chọn địa chỉ DDRAM tại 0x40)
CBI LCD_PORT,RS ;RS=0 ghi lệnh
LDI R17,$C0 ;con trỏ bắt đầu ở dòng 2 vị trí thứ 3
RCALL WRITE_COMMAND
LDI R16,1 ;chờ 100µs
RCALL DELAY_US
LDI ZH,HIGH(LINE2<<1)
LDI ZL,LOW(LINE2<<1)
DISPLAY_LINE2:
LPM R17,Z+
CPI R17,$00
BREQ HERE
CALL WRITE_DATA
RJMP DISPLAY_LINE2

//Tương tự, viết code xuất ra hàng thứ 2


HERE: RJMP HERE

//Chương trình con


;------------------------------------------------
//POWERUP_LCD_4BIT
//Input: None
//Output: None
//Description: Hàm con power up LCD
POWERUP_LCD_4BIT:
LDI R16,250
RCALL DELAY_US
LDI R16,250
RCALL DELAY_US
LDI R17,$30
RCALL OUT_COMMAND
LDI R16,50
RCALL DELAY_US
LDI R17,$30
RCALL OUT_COMMAND
LDI R16,2
RCALL DELAY_US
LDI R17,$20
RCALL OUT_COMMAND
RET

//Hàm con khởi tạo LCD


//Input: None
//Output: None
//Description: Khởi tạo LCD
INIT_LCD_4BIT:
LDI R17,$28
CALL WRITE_COMMAND
LDI R17,$01
CALL WRITE_COMMAND
LDI R17,$0C
CALL WRITE_COMMAND
LDI R17,$06
CALL WRITE_COMMAND
RET

//Hàm con ghi lệnh ra LCD


//Input: R17
//Output: None
//Description: Ghi lệnh chứa trong R17 ra LCD.
WRITE_COMMAND:
PUSH R17
ANDI R17,$F0 ; xuat 4 bit dau ra truoc
RCALL OUT_COMMAND
POP R17
SWAP R17
ANDI R17,$F0 ; xuat 4 bit sau ra
RCALL OUT_COMMAND
RET

//Hàm con ghi ký tự ra LCD


//Input: R17
//Output: None
//Description: Ghi kí tự ra LCD theo mã ASCII, ví dụ R17=0x41 thì LCD hiển thị
chữ A
WRITE_DATA:
PUSH R17
ANDI R17,$F0 ; xuat 4 bit dau
RCALL OUT_DATA
POP R17
SWAP R17
ANDI R17,$F0 ; xuat 4 bit sau
RCALL OUT_DATA
RET
OUT_COMMAND:
OUT LCD_PORT,R17
CBI LCD_PORT,RS
CBI LCD_PORT,RW
SBI LCD_PORT,EN
NOP
CBI LCD_PORT,EN
LDI R16,20
CALL DELAY_US
RET
OUT_DATA:
OUT LCD_PORT,R17
SBI LCD_PORT,RS
CBI LCD_PORT,RW
SBI LCD_PORT,EN
NOP
CBI LCD_PORT,EN
LDI R16,20
CALL DELAY_US
RET

/* DELAY_US
Input: R16
Output: None
Description: DELAY R16*100 MICROSEC
*/
DELAY_US:
MOV R15,R16
LDI R16,200
L1: MOV R14,R16
L2: DEC R14
NOP
BRNE L2
DEC R15
BRNE L1
RET
LINE1: .DB "TN VXL-AVR",$00
LINE2: .DB "NHOM L04",$00

Lý thuyết về LCD

Module LCD được sử dụng nhiều trong các ứng dụng nhúng hiện nay, chúng dùng để
hiển thị thông tin một cách linh hoạt và tiết kiệm năng lượng. Có nhiều loại module
LCD, trong đó thông dụng nhất là loại LCD 16x2 là loại hiển thị 2 hàng mỗi hàng 16
ký tự. Mỗi ký tự được hiển thị bởi một ma trận điểm ảnh có kích thước 5x8 điểm hoặc
5x11 điểm ảnh, tùy chế độ mà người lập trình thiết lập.
Phần lớn các module LCD sử dụng giao tiếp 16 chân trong đó có:

 8 đường dữ liệu

 3 đường điều khiển

 3 đường cấp nguồn cho module

 2 đường cấp nguồn cho LED nền trên LCD

Châ Tên Mô tả chức năng


n

1 VSS GND.

2 VDD +5 Volt.

3 VEE Tương phản (contrast): dùng để điều chỉnh độ tương phản giữ các chữ cái và đèn
nền trong LCD. Chân này sẽ được nối vào một mạch chia áp dùng biến trở để dễ
dàng thay đổi độ tương phản khi vặn biến trở.

4 RS Chọn thanh ghi (Register Select): chọn thanh ghi trong LCD để giao tiếp.

5 R/W Đọc/ghi (Read/Write): Chọn chế độ đọc hoặc ghi vào LCD. Trong kit thí nghiệm
VXL, sinh viên chỉ thực hiện chế độ ghi vào LCD nên chân này được nối đất.

Ghi chú: đối với các tín hiệu có kí hiệu bởi dấu ‘/’ thì ta hiểu phần bên trái dấu ‘/’
tương ứng với bit 1, phần bên phải dấu ‘/’ tương ứng với bit 0.

6 E Cho phép (Enable): cho phép dữ liệu đọc/ghi trên LCD. Sau khi thiết lập các tín
hiệu cần vào LCD (từ các chân RS, R/W, dữ liệu [0-7]) thì chân này kích cạnh
xuống để thực hiện lệnh.

7 D0 Bit 0 của dữ liệu

8 D1 Bit 1 của dữ liệu


9 D2 Bit 2 của dữ liệu

10 D3 Bit 3 của dữ liệu

11 D4 Bit 4 của dữ liệu

12 D5 Bit 5 của dữ liệu

13 D6 Bit 6 của dữ liệu

14 D7 Bit 7 của dữ liệu

15 LED+ Cấp nguồn + cho đèn LED nền trên LCD

16 LED- Cấp nguồn – cho đèn LED nền trên LCD

(Phần sau đây là quan trọng phải nắm vững)

Trong LCD có chứa một CGRAM và một DDRAM:

 CGRAM: Vùng RAM này khi thí nghiệm sinh viên không cần tương tác với
chúng. CGRAM có kích thước 64 Bytes chứa sẵn bảng mã hiển thị các ký tự
tương ứng theo mã ASCII. Ngoài ra nó có chứa 1 vùng trống có thể tùy ý vẽ
thêm các ký tự tùy chỉnh, vẽ 8 ký tự khác nhau khi dùng 5x8 điểm ảnh để thiết
kế (một ký tự sử dụng 8 bytes) hoặc 4 ký tự khác nhau khi dùng 5x11 điểm
ảnh để thiết kế.
 DDRAM: Vùng RAM chứa ký tự hiển thị trên màn hình LCD. Màn hình LCD
16x2 gồm có 2 hàng, mỗi hàng gồm 16 ký tự tương ứng với địa chỉ của
DDRAM được cho ở dưới. Người lập trình muốn hiển thị ký tự gì tại vị trí nào
trên màn hình LCD thì cần ghi mã số của ký tự đó vào ô nhớ tương ứng với vị
trí cần ghi trên DDRAM. Ví dụ muốn ghi ký tự O vào ô thứ 15 của hàng đầu
tiên trên LCD (Như hình 1) thì cần ghi mã số của ký tự O vào ô nhớ 0EH của
DDRAM. Mã số ký tự thì được tra tại hình 3 như sau. Ghi chú: bảng mã ký tự
tương ứng với mã ASCII.
Các mã lệnh để giao tiếp với LCD được liệt kê ở bảng sau, như ta thấy mã lệnh liên
quan đến các tín hiệu vào module LCD như RS, R/W, Data bit 0 đến bit 7. Muốn ghi
một lệnh vào LCD cần điều khiển các chân tín hiệu kể trên tương ứng với lệnh cần
ghi sau đó kích chân cho phép (Enable) của LCD (kích cạnh xuống).

Trong bo mạch thí nghiệm vi xử lý, phần giao tiếp LCD được thiết kế theo giao tiếp 4
bit DATA như hình sau.

Về lập trình ta nên chia mã lệnh ghi vào LCD thành 2 loại: ghi lệnh và ghi ký tự, ứng
với chân RS = 0 và RS = 1.

- Ghi lệnh (khi RS =0): là các lệnh cấu hình LCD, thiết lập con trỏ tắt hoặc bật,
nhấp nháy con trỏ…

- Ghi ký tự (khi RS =1): là ghi/ đọc ký tự vào DDRAM để hiển thị lên LCD.

Vì vậy ta sẽ viết 2 chương trình con WRITE_COMMAND và WRITE_DATA có nhiệm vụ ghi


mã lệnh chứa trong thanh ghi R17 ra LCD (dưới phần code gợi ý). Để sử dụng ta gán
mã lệnh hoặc mã kí tự vào R17 rồi gọi hàm này thôi, ví dụ sau.
LDI R17,$20
CALL WRITE_COMMAND

Ví dụ: Trước khi hiển thị LCD phải có một đoạn lệnh để cấu hình cho LCD như sau:
//Hàm con khởi tạo LCD
//Input: None
//Output: None
//Description: Khởi tạo LCD
INIT_LCD_4BIT:
LDI R17,$28
CALL WRITE_COMMAND
LDI R17,$01
CALL WRITE_COMMAND
LDI R17,$0C
CALL WRITE_COMMAND
LDI R17,$06
CALL WRITE_COMMAND
RET

Giờ sinh viên cần phải hiểu các mã lệnh 0x28, 0x01, 0x0C… có ý nghĩa gì.

Mã lệnh là 0x28 = 0b0010 1000 đây chính là lệnh bắt đầu với DB5 =1, khi dùng ghi
lệnh thì RS = 0, ta tra bảng, gióng xuống tìm DB5 = 1. Đây là câu lệnh Function set,
với DL = 0, N =1 và F =0. Tức là giao tiếp 4 bits, số lượng dòng hiển thị là 2 (LCD có
2 hàng trên và dưới), kích thước ký tự là 5x8.

Ghi chú: đối với các tín hiệu có kí hiệu bởi dấu ‘/’ thì ta hiểu phần bên trái dấu ‘/’
tương ứng với bit 1, phần bên phải dấu ‘/’ tương ứng với bit 0.

Tương tự mã lệnh 0x01=0b0000 0001 tương ứng với lệnh clear màn hình.

Tương tự với mã lệnh 0x0E = 0b0000 1110. Tức D = 1, C =1, B =0 có nghĩa là: cho
phép hiển thị, cho phép bật con trỏ, không cho con trỏ nhấp nháy.
Về phần ghi ký tự cũng tương tự. Gán mã ký tự mong muốn vào R17 rồi gọi hàm
WRITE_DATA.

LDI R17,$41
CALL WRITE_DATA

Ví dụ ghi ký tự V ra LCD:
LDI R17,’V’
CALL WRITE_DATA

Sau khi thực hiện lệnh ghi ký tự, mã ký tự sẽ được ghi vào ô DDRAM hiện hành. Nếu
địa chỉ DDRAM hiện hành thuộc khoản 0x00-0x0F hoặc 0x40H-0x4F thì trên LCD sẽ
hiển thị ký tự tương ứng vào ô đó, đồng thời sau đó địa chỉ DDRAM sẽ tự cộng thêm
1 và sẽ ghi ký tự ở ô tiếp theo nếu dùng thêm lệnh ghi ký tự. Trường hợp ô ký tự hiện
hành là 0F (tức ô cuối cùng của hàng 1), sau khi ghi lệnh ghi ký tự ra ô này, DDRAM
sẽ được cộng lên 1 là 0x10 chứ không phải là 0x40, nghĩa là ký tự sẽ không tự động
nhảy xuống hàng dưới. Để xuống hàng hoặc ghi vào ô ký tự cụ thể nào ta cần phải sử
dụng thêm lệnh chọn địa chỉ DDRAM như sau, mã lệnh này được tính là 0x80+địa
chỉ DDRAM cần nhảy đến.
Ví dụ: muốn ghi chữ “VXL” lên LCD tại vị trí sau thì công việc cần làm là: gọi lệnh
chọn địa chỉ DDRAM tại ô 0x46, mã lệnh của lệnh này sẽ là 0x80 + 0x46 = 0xC6.
Tiếp đó ghi các ký tự ‘V’, ‘X’, ‘L’.

Đoạn chương trình hiển thị chữ “VXL”, SV nên kết hợp với phương pháp tra bảng để
hiển thị.
LDI R17,$C6
CALL WRITE_COMMAND
LDI R17,’V’
CALL WRITE_DATA
LDI R17,’X’
CALL WRITE_DATA
LDI R17,’L’
CALL WRITE_DATA

Code gợi ý cho bài Lab1_3 bài 1.


.EQU LCD_PORT=PORTA
.EQU LCD_DDR=DDRA
.EQU RS=0
.EQU RW=1
.EQU EN=2
.ORG 0

RJMP MAIN
.ORG 0X40
MAIN:
LDI R16,LOW(RAMEND) ;DUA DIA CHI RAMEND LEN VI TRI CAO NHAT
OUT SPL,R16
LDI R16,HIGH(RAMEND)
OUT SPH,R16

/*
Kết nối port A vào LCD, RS=PA0, RW=PA1, EN=PA2, Data[4:7] = PA4:PA7
=> Khai báo PA012 4567 (không có PA3) là output, gán các giá trị ban đầu như
sau: Data = 0, RS=0, RW=1, EN=0.
*/
...
//Gọi chương trình con khởi tạo nguồn (POWERUP_LCD_4BIT) cho chế độ LCD 4 bit,
cụ thể thì xem lại giáo trình. Không gọi chương trình con này, LCD không hiển
thị được.
...
//Gọi chương trình con cấu hình LCD.
...
//Gọi lệnh trỏ con trỏ về vị trí DDRAM 0x00
...

//Dưới đây là đoạn code tra bảng, xuất ký tự hàng thứ 1 ra LCD cho đến khi gặp
ký tự 0x00
LDI ZH,HIGH(LINE1<<1)
LDI ZL,LOW(LINE1<<1)
DISPLAY_LINE1:
LPM R17,Z+
CPI R17,$00
BREQ NEWLINE
CALL WRITE_DATA
RJMP DISPLAY_LINE1
NEWLINE:
//Viết lệnh xuống hàng (lệnh chọn địa chỉ DDRAM tại 0x40)
...
//Tương tự, viết code xuất ra hàng thứ 2

LOOP:
// Bài này vòng lập không viết gì cả, vì mọi thứ chỉ cần chạy 1 lần thôi.
RJMP LOOP

//Chương trình con


;------------------------------------------------
//POWERUP_LCD_4BIT
//Input: None
//Output: None
//Description: Hàm con power up LCD
POWERUP_LCD_4BIT:
LDI R16,250
RCALL DELAY_US
LDI R16,250
RCALL DELAY_US
LDI R17,$30
RCALL OUT_COMMAND
LDI R16,50
RCALL DELAY_US
LDI R17,$30
RCALL OUT_COMMAND
LDI R16,2
RCALL DELAY_US
LDI R17,$20
RCALL OUT_COMMAND
RET

//Hàm con khởi tạo LCD


//Input: None
//Output: None
//Description: Khởi tạo LCD
INIT_LCD_4BIT:
LDI R17,$28
CALL WRITE_COMMAND
LDI R17,$01
CALL WRITE_COMMAND
LDI R17,$0C
CALL WRITE_COMMAND
LDI R17,$06
CALL WRITE_COMMAND
RET
//Hàm con ghi lệnh ra LCD
//Input: R17
//Output: None
//Description: Ghi lệnh chứa trong R17 ra LCD.
WRITE_COMMAND:
PUSH R17
ANDI R17,$F0 ; xuat 4 bit dau ra truoc
RCALL OUT_COMMAND
POP R17
SWAP R17
ANDI R17,$F0 ; xuat 4 bit sau ra
RCALL OUT_COMMAND
RET

//Hàm con ghi ký tự ra LCD


//Input: R17
//Output: None
//Description: Ghi kí tự ra LCD theo mã ASCII, ví dụ R17=0x41 thì LCD hiển thị
chữ A
WRITE_DATA:
PUSH R17
ANDI R17,$F0 ; xuat 4 bit dau
RCALL OUT_DATA
POP R17
SWAP R17
ANDI R17,$F0 ; xuat 4 bit sau
RCALL OUT_DATA
RET
OUT_COMMAND:
OUT LCD_PORT,R17
CBI LCD_PORT,RS
CBI LCD_PORT,RW
SBI LCD_PORT,EN
NOP
CBI LCD_PORT,EN
LDI R16,20
CALL DELAY_US
RET
OUT_DATA:
OUT LCD_PORT,R17
SBI LCD_PORT,RS
CBI LCD_PORT,RW
SBI LCD_PORT,EN
NOP
CBI LCD_PORT,EN
LDI R16,20
CALL DELAY_US
RET

/* DELAY_US
Input: R16
Output: None
Description: DELAY R16*100 MICROSEC
*/
DELAY_US:
MOV R15,R16
LDI R16,200
L1: MOV R14,R16
L2: DEC R14
NOP
BRNE L2
DEC R15
BRNE L1
RET
LINE1: .DB "TN VXL-AVR",$00
LINE2: .DB "10 DIEM",$00
LAB1_3 Bài 2

.EQU RS = 0
.EQU RW = 1
.EQU EN = 2

.ORG 0
RJMP MAIN
.ORG 0X40
MAIN:
LDI R16, HIGH(RAMEND)
OUT SPH, R16
LDI R16, LOW(RAMEND)
OUT SPL, R16
SER R16
OUT DDRA, R16 ;PortA is output LCD
OUT DDRC, R16 ;PortC is output Barled
CBI DDRB, 0 ;PB0 is input
SBI PORTB, 0 ;Pull-up
CBI PORTA, RS ;Recieve command
CBI PORTA, RW ;Write data
CBI PORTA, EN ;Unenable LCD
CLR R24 ;R24 to contain result
LDI R25, $30 ;Change to ascii
CALL RESET_LCD
CALL INIT_LCD4
START:
CALL DISPLAY_LCD
CALL WAIT_PRESS
CALL DISPLAY_LCD
CALL WAIT_UNPRES
RJMP START
WAIT_PRESS:
SBIC PINB, 0
RJMP WAIT_PRESS
INC R24
OUT PORTC, R24
CALL DELAY_50MS
SBIC PINB, 0
RJMP WAIT_PRESS
RET
WAIT_UNPRES:
SBIS PINB, 0
RJMP WAIT_UNPRES
CALL DELAY_50MS
SBIS PINB, 0
RJMP WAIT_UNPRES
RET
DISPLAY_LCD:
PUSH R24 ;Save R24
MOV R18, R24
LDI R21, 10
CLR R22
L1:
INC R22 ;Div10 lan 1
SUB R18, R21
BRCC L1
DEC R22
ADD R18, R21
PUSH R18 ;Cat hang don vi
MOV R18, R22 ;Lay phan nguyen chia 10 lan 2
CLR R22
L2:
INC R22 ;Div10 lan 2
SUB R18, R21
BRCC L2
DEC R22
ADD R18, R21
PUSH R18 ;Cat hang chuc
MOV R18, R22 ;Lay phan nguyen chia 10 lan 3
CLR R22
L3:
INC R22 ;Div10 lan 3
SUB R18, R21
BRCC L3
DEC R22
ADD R18, R21
PUSH R18 ;Cat hang tram
CBI PORTA, RS
LDI R17, $01 ;Clear display before
CALL OUT_LCD4_2
LDI R16, 20 ;Delay 20ms after clearing
CALL DELAY_US
CBI PORTA, RS
LDI R17, $82 ;Pointer start at line1, pos3
CALL OUT_LCD4_2
LDI R26, 3 ;Lap 3 lan lay 3 so ra
LP:
POP R17
ADD R17, R25
SBI PORTA, RS
CALL OUT_LCD4_2
DEC R26
BRNE LP
POP R24 ;Restore R24
RET

RESET_LCD:
LDI R16, 250 ;Delay 25ms
CALL DELAY_US
LDI R16, 250 ;Delay 25ms
CALL DELAY_US
CBI PORTA, RS
LDI R17, $30 ;Lan 1
CALL OUT_LCD4

LDI R16, 250 ;Delay 25ms


CALL DELAY_US
LDI R16, 170 ;Delay 17ms
CALL DELAY_US
CBI PORTA, RS
LDI R17, $30 ;Lan 2
CALL OUT_LCD4

LDI R16, 2 ;Delay 200us


CALL DELAY_US
CBI PORTA, RS
LDI R17, $32 ;Lan 3
CALL OUT_LCD4_2
RET

INIT_LCD4:
LDI R18, $28 ;Function set
LDI R19, $01 ;Clear display
LDI R20, $0C ;Display on, pointer off
LDI R21, $06
CBI PORTA, RS
MOV R17, R18
CALL OUT_LCD4_2
MOV R17, R19 ;Clear display
CALL OUT_LCD4_2
LDI R16, 20 ;Delay 20ms after clearing display
CALL DELAY_US
MOV R17, R20
CALL OUT_LCD4_2
MOV R17, R21
CALL OUT_LCD4_2
RET

OUT_LCD4:
OUT PORTA, R17
SBI PORTA, EN
CBI PORTA, EN
RET
OUT_LCD4_2:
LDI R16, 1 ;Delay 1us
CALL DELAY_US
IN R16, PORTA
ANDI R16, (1<<RS)
PUSH R16
PUSH R17
ANDI R17, $F0
OR R17, R16
CALL OUT_LCD4
LDI R16, 1 ;Delay 1us between first and second access
CALL DELAY_US
POP R17
POP R16
SWAP R17
ANDI R17, $F0
OR R17, R16
CALL OUT_LCD4
RET

DELAY_US:
MOV R15, R16
LDI R16, 200
LP1:
MOV R14, R16
LP2:
NOP
DEC R14
BRNE LP2
DEC R15
BRNE LP1
RET

DELAY_50MS:
LDI R16, 250 ;Delay 25ms
CALL DELAY_US
LDI R16, 250 ;Delay 25ms
CALL DELAY_US
RET

Code gợi ý
/*
KET NOI PHAN CUNG:
PORT A: LCD
PORT B:BAR LED
PINC0: NUT NHAN
*/
.ORG 0
.EQU LCD_PORT=PORTA
.EQU LCD_DDR=DDRA
.EQU LED_PORT=PORTB
.EQU LED_DDR=DDRB
.EQU RS=0
.EQU RW=1
.EQU EN=2

RJMP MAIN
.ORG 0X40
//MAIN----------------------------------
MAIN:
LDI R16,LOW(RAMEND) ;DUA DIA CHI RAMEND LEN VI TRI CAO NHAT
OUT SPL,R16
LDI R16,HIGH(RAMEND)
OUT SPH,R16

//Khai báo PORT gắn LED là OUTPUT, gán giá trị ban đầu bằng 0 để LED tắt.
...
//Khai báo PC0 là input, có điện trở kéo lên
...

/*
Kết nối port A vào LCD, RS=PA0, RW=PA1, EN=PA2, Data[4:7] = PA4:PA7
=> Khai báo PA012 4567 (không có PA3) là output, gán các giá trị ban đầu như
sau: Data = 0, RS=0, RW=1, EN=0.
*/
...
//Gọi chương trình con khởi tạo nguồn (POWERUP_LCD_4BIT) cho chế độ LCD 4 bit,
cụ thể thì xem lại giáo trình. Không gọi chương trình con này, LCD không hiển
thị được.
...
//Gọi chương trình con cấu hình LCD.
...
//Gọi lệnh trỏ con trỏ về vị trí DDRAM 0x00
...

;R18 luu so lan nhan nut


LDI R18,0
;R19 hang so cong them de chuyen thanh ASCII, lưu ý số đếm 0 1… khi hiển
thị lên LCD phải cộng thêm 48 (hệ 10).
LDI R19,48
;---------------------------------------------------------
;Viết code in dong chu LINE1 ra LCD
;---------------------------------------------------------
...

//LOOP----------------------------------------------------
LOOP:
//Viết lệnh chọn địa chỉ DDRAM tại 0x40, hiển thị số lần nhấn nút ở hàng 2
...

RCALL CHECK_BUTTON
CALL NUM_8_BIT_TO_BCD

CPI R22,0
BRNE HANG_TRAM
CPI R21,0
BRNE HANG_CHUC
CPI R20,0
BRNE HANG_DONVI
HANG_TRAM:
MOV R17,R22
ADD R17,R19
CALL WRITE_DATA
HANG_CHUC:
MOV R17,R21
ADD R17,R19
CALL WRITE_DATA
HANG_DONVI:
MOV R17,R20
ADD R17,R19
CALL WRITE_DATA
RJMP LOOP

;------------------------------------------------------------
;INPUT: PINC.0
;OUTPUT: R17, R18 la so lan bam nut
;DESCRIPTION:
;------------------------------------------------------------
CHECK_BUTTON:
NHAN_NUT:
SBIC PINC,0
RJMP NHAN_NUT
LDI R16,250 ;DELAY 10MS
RCALL DELAY_US
SBIC PINC,0
RJMP NHAN_NUT
/* INC R18
OUT LED_PORT,R18
MOV R17,R18
RCALL NUM_8_BIT_TO_BCD
RET*/
NHA_NUT:
SBIS PINC,0
RJMP NHA_NUT
LDI R16,250 ;DELAY 25MS
RCALL DELAY_US
SBIS PINC,0
RJMP NHA_NUT
;doan chuong trinh xu ly khi co nut nhan,
INC R18
OUT LED_PORT,R18
MOV R17,R18
RCALL NUM_8_BIT_TO_BCD
RET
;------------------------------------------------------------
;INPUT: R17
;OUTPUT: R22 hang tram, R21 hang chuc, R20 hang don vi
;DESCRIPTION: lay 3 chu so BCD cua R17
;------------------------------------------------------------
NUM_8_BIT_TO_BCD:
CLR R20
CLR R21
CLR R22

LDI R16,10
RCALL DIV10
MOV R20,R16 ;R20: HANG DON VI
LDI R16,10
RCALL DIV10
MOV R21,R16 ;R21: HANG CHUC
MOV R22,R17 ;R22: HANG TRAM
RET

;------------------------------------------------------------
;INPUT: R17, R16 = 10
;OUTPUT: R16 so du, R17 thuong so
;DESCRIPTION: chia R17 cho R16
;------------------------------------------------------------
DIV10:
CLR R15 ;R15:THUONG SO
TIEP_TUC_TRU:
SUB R17,R16
BRCS DUARA_KETQUA ;C=1 KHONG CHIA DUOC
INC R15
RJMP TIEP_TUC_TRU
DUARA_KETQUA:
ADD R17,R16
MOV R16,R17 ;R16:SO DU
MOV R17,R15 ;R17:THUONG SO
RET
;------------------------------------------------------------
POWERUP_LCD_4BIT:
LDI R16,250
RCALL DELAY_US
LDI R16,250
RCALL DELAY_US
LDI R17,$30
RCALL OUT_COMMAND
LDI R16,50
RCALL DELAY_US
LDI R17,$30
RCALL OUT_COMMAND
LDI R16,2
RCALL DELAY_US
LDI R17,$20
RCALL OUT_COMMAND
RET
INIT_LCD_4BIT:
LDI R17,$28
CALL WRITE_COMMAND
LDI R17,$01
CALL WRITE_COMMAND
LDI R17,$0C
CALL WRITE_COMMAND
LDI R17,$06
CALL WRITE_COMMAND
RET
WRITE_COMMAND:
PUSH R17
ANDI R17,$F0 ; xuat 4 bit dau ra truoc
RCALL OUT_COMMAND
POP R17
SWAP R17
ANDI R17,$F0 ; xuat 4 bit sau ra
RCALL OUT_COMMAND
RET

WRITE_DATA:
PUSH R17
ANDI R17,$F0 ; xuat 4 bit dau
RCALL OUT_DATA
POP R17
SWAP R17
ANDI R17,$F0 ; xuat 4 bit sau
RCALL OUT_DATA
RET
OUT_COMMAND:
OUT LCD_PORT,R17
CBI LCD_PORT,RS
CBI LCD_PORT,RW
SBI LCD_PORT,EN
NOP
CBI LCD_PORT,EN
LDI R16,20
CALL DELAY_US
RET
OUT_DATA:
OUT LCD_PORT,R17
SBI LCD_PORT,RS
CBI LCD_PORT,RW
SBI LCD_PORT,EN
NOP
CBI LCD_PORT,EN
LDI R16,20
CALL DELAY_US
RET
DELAY_US: ;DELAY R16*100 MICROSEC
MOV R15,R16
LDI R16,200
L1: MOV R14,R16
L2: DEC R14
NOP
BRNE L2
DEC R15
BRNE L1
RET
LINE1: .DB "SO LAN NHAN NUT",$00
LAB1_3 Bài 3

Tham khảo cách sử dụng hàm GET_KEY16 trong giáo trình để làm bài này.
.ORG 0
.EQU LCD_PORT=PORTA
.EQU LCD_DDR=DDRA
.EQU LED_PORT=PORTD
.EQU LED_DDR=DDRD
.EQU RS=0
.EQU RW=1
.EQU EN=2
RJMP MAIN
.ORG 0X40
//MAIN----------------------------------
MAIN:
LDI R16,LOW(RAMEND) ;DUA DIA CHI RAMEND LEN VI TRI CAO NHAT
OUT SPL,R16
LDI R16,HIGH(RAMEND)
OUT SPH,R16
//Khai báo PORT g?n LED là OUTPUT, gán giá tr? ban ??u b?ng 0 ?? LED t?t.
LDI R16,0XFF
OUT LED_DDR,R16
LDI R16,0
OUT LED_PORT,R16
//Khai báo input, có ?i?n tr? kéo lên
LDI R16,0X0F
OUT DDRB,R16
LDI R16,0XFF
OUT PORTB,R16
/*
K?t n?i port A vào LCD, RS=PA0, RW=PA1, EN=PA2, Data[4:7] = PA4:PA7
=> Khai báo PA012 4567 (không có PA3) là output, gán các giá tr? ban ??u nh?
sau: Data = 0, RS=0, RW=1, EN=0.
*/
LDI R16,0XFF
OUT LCD_DDR,R16 ;khai báo PORTA là output
CBI LCD_PORT,RS ;RS=PCO=0
CBI LCD_PORT,RW ;RW=PC1=0 truy xu?t ghi
CBI LCD_PORT,EN ;E=PC2=0 c?m LCD
RCALL POWERUP_LCD_4BIT ;reset c?p ngu?n LCD 4 bit
RCALL INIT_LCD_4BIT ;ctc kh?i ??ng LCD 4 bit
CBI LCD_PORT,RS ;RS=0 ghi l?nh
LDI R17,$80 ;con tr? b?t ??u ? dòng 1 v? trí th? 1
RCALL WRITE_COMMAND
LDI R16,1 ;ch? 100?s
RCALL DELAY_US
;---------------------------------------------------------
;Vi?t code in dong chu LINE1 ra LCD
;---------------------------------------------------------
LDI ZH,HIGH(LINE1<<1)
LDI ZL,LOW(LINE1<<1)
DISPLAY_LINE1:
LPM R17,Z+
CPI R17,$00
BREQ NEWLINE
CALL WRITE_DATA
RJMP DISPLAY_LINE1
//LOOP----------------------------------------------------
//Vi?t l?nh ch?n ??a ch? DDRAM t?i 0x40, hi?n th? s? l?n nh?n nút ? hàng 2
NEWLINE:
CBI LCD_PORT,RS ;RS=0 ghi l?nh
LDI R17,$C0 ;con tr? b?t ??u ? dòng 2 v? trí th? 1
RCALL WRITE_COMMAND
LDI R16,1 ;ch? 100µs
RCALL DELAY_US
RCALL KEY_RD
OUT LED_PORT,R17
LDI R19,0X30
ADD R17,R19
RCALL WRITE_DATA
LDI R16,1 ;ch? 100µs
RCALL DELAY_US
RJMP NEWLINE
POWERUP_LCD_4BIT:
LDI R16,250
RCALL DELAY_US
LDI R16,250
RCALL DELAY_US
LDI R17,$30
RCALL OUT_COMMAND
LDI R16,50
RCALL DELAY_US
LDI R17,$30
RCALL OUT_COMMAND
LDI R16,2
RCALL DELAY_US
LDI R17,$20
RCALL OUT_COMMAND
RET
INIT_LCD_4BIT:
LDI R17,$28
CALL WRITE_COMMAND
LDI R17,$01
CALL WRITE_COMMAND
LDI R17,$0C
CALL WRITE_COMMAND
LDI R17,$06
CALL WRITE_COMMAND
RET
WRITE_COMMAND:
PUSH R17
ANDI R17,$F0 ; xuat 4 bit dau ra truoc
RCALL OUT_COMMAND
POP R17
SWAP R17
ANDI R17,$F0 ; xuat 4 bit sau ra
RCALL OUT_COMMAND
RET

WRITE_DATA:
PUSH R17
ANDI R17,$F0 ; xuat 4 bit dau
RCALL OUT_DATA
POP R17
SWAP R17
ANDI R17,$F0 ; xuat 4 bit sau
RCALL OUT_DATA
RET
OUT_COMMAND:
OUT LCD_PORT,R17
CBI LCD_PORT,RS
CBI LCD_PORT,RW
SBI LCD_PORT,EN
NOP
CBI LCD_PORT,EN
LDI R16,20
CALL DELAY_US
RET
OUT_DATA:
OUT LCD_PORT,R17
SBI LCD_PORT,RS
CBI LCD_PORT,RW
SBI LCD_PORT,EN
NOP
CBI LCD_PORT,EN
LDI R16,20
CALL DELAY_US
RET
DELAY_US: ;DELAY R16*100 MICROSEC
MOV R15,R16
LDI R16,200
L1: MOV R14,R16
L2: DEC R14
NOP
BRNE L2
DEC R15
BRNE L1
RET
KEY_RD:
LDI R16,50
LDI R24,0XFF
BACK1:
RCALL GET_KEY16
BRCC KEY_RD
DEC R16
BRNE BACK1
PUSH R17
WAIT_1:
LDI R16,50
BACK2:
RCALL GET_KEY16
BRCS WAIT_1
DEC R16
BRNE BACK2
POP R17
CLR R24
RET
GET_KEY16:
LDI R17,4 ;R17 ??m s? l?n quét c?t
LDI R20,0XFE ;b?t ??u quét c?t 0
SCAN_COL: ;ho?c NOP ? delay 1MC
OUT PORTB, R20
IN R19,PINB ;??c tr?ng thái hàng
IN R19,PINB ;??c l?i tr?ng thái hàng
ANDI R19,0XF0 ;che 4 bit cao l?y mã hàng
CPI R19,0XF0 ;xem có phím nh?n?
BRNE CHK_KEY ;R19 khác FOH, có phím nh?n
LSL R20 ;quét c?t k? ti?p
INC R20 ;??t LSB=1
DEC R17
BRNE SCAN_COL ;ti?p t?c quét h?t s? c?t phím ch?a nh?n, C=0
CLC
RJMP EXIT ;thoát
CHK_KEY:
SUBI R17,4 ;tính v? trí c?t
NEG R17 ;bù 2 (s? ? 0) ? s? d??ng
SWAP R19 ;??o sang 4 bit th?p mã hàng
LDI R20,4 ;quét 4 hàng ? tìm v? trí hàng...
SCAN_ROW: ; tìm v? trí hàng có phím ???c nh?n
ROR R19 ;quay ph?i mã hàng qua C tìm bit 0
BRCC SET_FLG ;C=0 ?úng v? trí hàng có phím nh?n
INC R17 ;không ?úng hàng, t?ng v? trí hàng thêm 4
INC R17
INC R17
INC R17
DEC R20
BRNE SCAN_ROW ;quét h?t 4 hàng
SET_FLG: SEC ;có phím nh?n C=1
EXIT: RET
LINE1: .DB "NUT VUA NHAN LA ",$00
;---------------------------------------------------------
;GET_KEY16 ??c tr?ng thái các phím,
;Tr? v? R17= mã phím và C=1 n?u có phím nh?n
;Tr? v? C=0 n?u phím ch?a nh?n
;---------------------------------------------------------
GET_KEY16:
LDI R17, 4 ;R17 SO LAN QUET COT
LDI R20, 0xFE ;BAT DAU QUET COT 0
SCAN_COL:
OUT MATRIX_BTN_PORT, R20
IN R19, MATRIX_BTN_PIN ;?Oc trAng thái hàng
IN R19, MATRIX_BTN_PIN ;?Oc lAi trAng thái hàng
ANDI R19, 0xF0 ;che 4 bit cao lay ma hàng
CPI R19, 0xF0 ;xem có phím nhan?
BRNE CHK_KEY ;R19 khác F0H, có phím nhan
LSL R20 ;quét cot ke tiep
INC R20 ;?at LSB=1
DEC R17 ;giam so lan quét cot
BRNE SCAN_COL ;tiep tuc quét het so cot
CLC ;phím ch?a nhan, C=0
CLR R21 ;R2=0 KHONG CO NHAN NUT
RJMP EXIT ;thoát
;-------------------------------------------------
CHK_KEY:
SUBI R17, 4 ;tính vi trí cot
NEG R17 ;bù 2 lay so d??ng
SWAP R19 ;?ao sang 4 bit thap ma hàng
LDI R20, 4 ;R20 ?em so lon quét hàng
SCAN_ROW:
ROR R19 ;quay phai qua C tim bit 0
BRCC SET_FLG ;C=0 vi trí hàng có phím nhan
INC R17 ;không ?úng hàng t?ng vi trí hàng thêm 4
INC R17
INC R17
INC R17
DEC R20
BRNE SCAN_ROW ;quét het 4 hàng
CLC ;không có phím nhan C=0
RJMP EXIT ;thoát
SET_FLG:
SEC ;có phím nhan C=1
SER R21 ;R2 KHAC KHONG THI CO NHAN NUT
EXIT:
RET
;-----------------------------------
;------------------------------------------
;KEY_RD ??c tr?ng thái phím
;Ch?ng rung phím khi nh?n/nh? 50 l?n
;S? d?ng GET_KEY16 nh?n d?ng phím nh?n
;Ch? thoát khi có phím nh?n!!!
;-------------------------------------------
KEY_RD:
LDI R16,50 ;so lan nhan dang phím nhan
BACK1:
RCALL GET_KEY16 ;goi ctc nhan dang phím
BRCC KEY_RD ;C=0 phím ch?a nhan lap lai
DEC R16 ;?em so lan nhan dang phím
BRNE BACK1 ;lap vong cho ?u so lan ?em
PUSH R17

LDI R17,$C0 ;DONG 2 VI TRI 1


CALL WRITE_COMMAND
POP R17
MOV R24,R17 ;LUU GIA TRI VAO R24
OUT LED_PORT,R24
RCALL CHUYEN_ASCII
WAIT_1:
LDI R16,50 ;so lan nhan dang phím nha
BACK2:
RCALL GET_KEY16 ;goi ctc nhan dang phím
BRCS WAIT_1 ;C=1 phím ch?a nha
DEC R16 ;?em so lan nhan dang phím
BRNE BACK2 ;lap vong cho ?u so lan ?em
;POP R17

LDI R17,$C0 ;DONG 2 VI TRI 1


CALL WRITE_COMMAND
RCALL DISPLAY_FF
LDI R24,$FF
OUT LED_PORT,R24
RET

You might also like