Báo cáo thí nghiệm Vi xử lý Đại học Bách Khoa Đại học Quốc Gia thành phố Hồ Chí Minh.Bài thí nghiệm 3: Thí nghiệm giao tiếp LCD và ADC.Thí nghiệm 1: Mục tiêu: Nắm được cách thức xuất giá trị lên LCD.Yêu cầu: Download chương trình mẫu LCD.A51 trên trang web bộ môn điện tử hoặc trên elearning. Biên dịch và chạy thử chương trình. Sửa chương trình để hiển thị tên sinh viên lên hàng đầu.
Trang 1MỤC TIÊU
Nắm được cách điều khiển LCD
Nắm được cách giao tiếp với ADC
Nắm được cách phối hợp lấy dữ liệu từ ADC và hiển thị lên LCD
CHUẨN BỊ
Đọc chương 1, chương 5 và chương 9 của tài liệu hướng dẫn
Viết chương trình và mô phỏng các bài thí nghiệm trên Proteus dựa trên bài thí nghiệm 0
Trang 2THÍ NGHIỆM 1
Mục tiêu: Nắm được cách thức xuất giá trị lên LCD
Yêu cầu:
Download chương trình mẫu LCD.A51 trên trang web bộ môn điện tử hoặc trên elearning
Biên dịch và chạy thử chương trình
Sửa chương trình để hiển thị tên sinh viên lên hàng đầu
Kiểm tra:
Kiểm tra kết quả thực hiện của chương trình
Giải thích ý nghĩa và cách sử dụng các chương trình con trên project mẫu
Chương trình con dùng để viết lệnh và viết dữ liệu lên LCD khác nhau như thế nào?
Các mã lệnh 38H, 0EH, 06H và 01H mang ý nghĩa như thế nào?
Muốn viết chuỗi lên LCD, ta có các cách làm như thế nào?
Tại sao trong đoạn code: MESSAGE: DB “HELLO WORLD!”,0
Số 0 được thêm vào để làm gì?
BÁO CÁO:
1 Chương trình:
LCD_E BIT P3.4 ; Định nghĩa LCD_E là chân P3.4 LCD_RS BIT P3.5 ; Định nghĩa LCD_RS là chân P3.5 LCDADDR EQU 6000H ; Định nghĩa LCDADDR là 6000H ORG 2000H
MAIN:
MOV @R0, 30H
Trang 3ACALL CLEAR ACALL INIT_LCD ACALL DISPLAYSTRING SJMP $
INIT_LCD: ; Các dòng lệnh cấu hình LCD ban đầu
MOV A, #38H ACALL WRITECOM MOV A, #0EH ACALL WRITECOM MOV A, #06H ACALL WRITECOM RET
MOV A, #01H ACALL WRITECOM RET
MOV DPTR, #LCDADDR SETB LCD_E
CLR LCD_RS MOVX@DPTR, A CLR LCD_E ACALL WAIT_LCD RET
Trang 4MOV DPTR, #LCDADDR SETB LCD_E
SETB LCD_RS MOVX@DPTR, A CLR LCD_E ACALL WAIT_LCD RET
DISPLAYSTRING: ; Hàm con xuất chuỗi ký tự bằng cách tra bảng
MOV A,#0 LOOP:
MOV DPTR, #MESSAGE MOV R0,A
MOVC A,@A+DPTR
JZ EXIT ACALL WRITETEXT MOV A,R0
INC A DJNZ B, LOOP EXIT:
RET WAIT_LCD: ; Hàm con delay cho LCD
MOV R6,#10 DL1:
MOV R7, #250 DJNZ R7, $
Trang 5DJNZ R6,DL1 RET
MESSAGE:
DB "HELLO WORLD!",0 END
2 Kết quả thí nghiệm
a Kết quả mô phỏng:
b Trả lời câu hỏi
1) Giải thích ý nghĩa và cách sử dụng các chương trình con trên project mẫu
INIT_LCD: Thiết lập các chế độ hiển thị trên LCD
Trang 6 WRITETEXT: Cho phép truy suất và truy suất dữ liệu của LCD.
2) Chương trình con dùng để viết lệnh và viết dữ liệu lên LCD khác nhau như thế nào?
Chương trình dùng để viết lệnh và viết dữ liệu lên LCD khác ở nhau ở chương trình viết lệnh thì cho chân RS xuống mức 0 còn chương trình viết dữ liệu lên LCD thì ngược lại.
3) Các mã lệnh 38H, 0EH, 06H và 01H mang ý nghĩa như thế nào?
4) Muốn viết chuỗi lên LCD, ta có các cách làm như thế nào?
Muốn viết chuỗi lên LCD, ta xuất lần lượt từng ký tự trong chuỗi lên LCD
5) Tại sao trong đoạn code: MESSAGE: DB “HELLO WORLD!”,0
Số 0 được thêm vào để làm gì?
Trong đoạn code MESSAGE: DB "HELLO WORLD!",0 kí tự 0 dùng để
nhận biết kết thúc chuỗi.
Trang 7THÍ NGHIỆM 2
Mục tiêu: Nắm được cách thức điều khiển con trỏ trong LCD
Yêu cầu:
Viết thêm chương trình con CLRSCREEN để xóa màn hình LCD
Viết thêm chương trình con GOTOXY để di chuyển con trỏ của LCD đến hàng x, cột y, với X chứa trong R0 và Y chứa trong R1
Sửa chương trình ở thí nghiệm 1 để hiển thị căn chỉnh tên sinh viên ở chính giữa hàng thứ 1 và thêm số nhóm ở hàng thứ 2 (cũng căn giữa)
Kiểm tra:
Kiểm tra kết quả thực hiện của chương trình
Địa chỉ để hiển thị trên hàng 1 và hàng 2 của LCD bắt đầu và kết thúc bằng bao nhiêu? LCD có hiển thị được hết vùng địa chỉ đó không? Tại sao?
Muốn bật hay tắt con trỏ trên LCD, ta phải nạp mã lệnh bao nhiêu?
Muốn hiển thị con trỏ kiểu blinky, ta phải nạp mã lệnh bao nhiêu?
BÁO CÁO:
1 Chương trình:
EN BIT P3.3 ; Định nghĩa EN là chân P3.3
RS BIT P3.5 ; Định nghĩa RS là chân P3.5 LCDADDR EQU 6000H ; Định nghĩa LCDADDR là 6000H ORG 2000H
MAIN:
ACALL INIT_LCD ACALL CLRSCREEN
Trang 8MOV R0, #1 ; Hàng 1 MOV R1, #5 ; Cột 5 ACALL GOTOXY ; Đặt cursor tại hàng 1 cột 5 ACALL DISPLAY_TEN ; Gọi hàm con hiển thị tên DISPLAY_GROUP:
MOV R0, #2 ; Hàng 2 MOV R1, #5 ; Cột 5 ACALL GOTOXY ; Đặt cursor tại hàng 2 cột 5 ACALL DISPLAY_NHOM; Gọi hàm con hiển thị nhóm SJMP $
GOTOXY:
CJNE R0, #1, G_R2 ; Gotoxy_Row2 G_R1: MOV A, R1
SJMP G_S ; Gotoxy_Skip G_R2: MOV A, R1
ADD A, #40H G_S: ADD A, #80H
ACALL COMD RET
DISPLAY_TEN: ; Hàm còn xuất chuỗi ký tự TEN
MOV R2, #0 LOOP_TEN:
MOV DPTR, #TEN MOV A, R2
MOVC A, @A+DPTR
Trang 9JZ EXIT ACALL DISP INC R2 SJMP LOOP_TEN EXIT: RET
DISPLAY_NHOM: ; Hàm con xuất chuỗi ký tự NHOM
MOV R2, #0 LOOP_NHOM:
MOV DPTR, #NHOM MOV A, R2
MOVC A, @A+DPTR
JZ EXIT ; EXIT ở hàm con DISPLAY_TEN ACALL DISP
INC R2 SJMP LOOP_NHOM INIT_LCD: ; Các dòng lệnh cấu hình LCD ban đầu
MOV A, #38H ACALL COMD MOV A, #0EH ACALL COMD MOV A, #06H ACALL COMD RET
CLRSCREEN: ; Hàm con xóa màn hình LCD
MOV A, #01H
Trang 10ACALL COMD RET
COMD: ; Hàm con ghi lệnh
MOV DPTR, #LCDADDR SETB EN
CLR RS MOVX @DPTR, A CLR EN
ACALL WAIT_LCD RET
DISP: ; Hàm con ghi kí tự
MOV DPTR, #LCDADDR SETB EN
SETB RS MOVX @DPTR, A CLR EN
ACALL WAIT_LCD RET
WAIT_LCD: ; Hàm con delay cho LCD thực thi lệnh
MOV R6, #16 DL: MOV R5, #144
DJNZ R5, $ DJNZ R6,DL RET
TEN: DB "DUONG!", 0 ; Dấu ! thêm vào cho chẵn ký tự
Trang 11NHOM: DB "NHOM4!", 0
END
2 Kết quả thí nghiệm
a Kết quả mô phỏng:
b Trả lời câu hỏi
1) Địa chỉ để hiển thị trên hàng 1 và hàng 2 của LCD bắt đầu và kết thúc bằng bao nhiêu?
LCD có hiển thị được hết vùng địa chỉ đó không? Tại sao?
Vùng nhớ chứa dữ liệu cần hiển thị của LCD ở hàng 1 là 00H – 13H Tuy nhiên vì LCD chỉ hiển thị được 16 ký tự nên vùng địa chỉ có thể hiển thị được trên LCD của hàng 1
Trang 12Mã lệnh: 0EH để bật con trỏ và mã lệnh: 0CH để tắt con trỏ
3) Muốn hiển thị con trỏ kiểu blinky, ta phải nạp mã lệnh bao nhiêu?
Muốn hiển thị con trỏ kiểu blinky, mã lệnh cần phải nạp là 0FH
Trang 13THÍ NGHIỆM 3
Mục tiêu: Nắm được cách thức hiển thị LCD một cách thuần thục
Yêu cầu:
Viết chương trình hiển thị lên dòng thứ 1 và canh giữa tên của thành viên thứ nhất trong nhóm Sau
đó 1s, xóa dòng 1 và hiển thị lên dòng thứ 2 và canh giữa tên thành viên thứ hai của nhóm Tiếp tục sau đó 1s, xóa dòng 2 và hiển thị đồng thời tên hai thành viên ở hai dòng
ACALL INIT_LCD MAIN:
ACALL CLRSCREEN ACALL DISPLAY_AN ACALL DL1s
ACALL CLRSCREEN ACALL DISPLAY_DUONG ACALL DL1S
ACALL CLRSCREEN ACALL DISPLAY_AN
Trang 14ACALL DISPLAY_DUONG ACALL DL1s
SJMP MAIN DISPLAY_AN: ; Hàm con hiển thị “AN”
MOV R0, #1 ; Hàng 1 MOV R1, #7 ; Cột 7 ACALL GOTOXY ; Đặt cursor tại hàng 1 cột 1 MOV R2, #0
LOOP_AN:
MOV DPTR, #AN MOV A, R2
MOVC A, @A+DPTR
JZ EXIT ACALL DISP INC R2 SJMP LOOP_AN EXIT: RET
DISPLAY_DUONG: ; Hàm con hiển thị “DUONG!”, 6 ký tự cho chẵn
MOV R0, #2 ; Hàng 2 MOV R1, #5 ; Cột 5 ACALL GOTOXY ; Đặt cursor tại hàng 2 cột 5 MOV R2, #0
LOOP_DUONG:
MOV DPTR, #DUONG MOV A, R2
Trang 15MOVC A, @A+DPTR
JZ EXIT ; EXIT ở hàm con DISPLAY_AN ACALL DISP
INC R2 SJMP LOOP_DUONG INIT_LCD:
MOV A, #38H ACALL COMD MOV A, #0EH ACALL COMD MOV A, #06H ACALL COMD RET
CLRSCREEN:
MOV A, #01H ACALL COMD RET
COMD:
MOV DPTR, #LCDADDR SETB EN
CLR RS MOVX @DPTR, A CLR EN
ACALL WAIT_LCD RET
Trang 16DISP:
MOV DPTR, #LCDADDR SETB EN
SETB RS MOVX @DPTR, A CLR EN
ACALL WAIT_LCD RET
GOTOXY:
CJNE R0, #1, G_R2 ; Gotoxy_Row2 G_R1: MOV A, R1
SJMP G_S ; Gotoxy_Skip G_R2: MOV A, R1
ADD A, #40H G_S: ADD A, #80H
ACALL COMD RET
MOV R7, #8 DL2: MOV R6, #240
DL1: MOV R5, #240
DJNZ R5, $ DJNZ R6, DL1 DJNZ R7, DL2 RET
Trang 17WAIT_LCD:
MOV R6, #16 DL: MOV R5, #144
DJNZ R5, $ DJNZ R6,DL RET
Trang 19THÍ NGHIỆM 4
Mục tiêu: Nắm được cách thức giao tiếp với ADC
Yêu cầu:
Viết chương trình con READADC thực hiện đọc giá trị của kênh 0 và trả về giá trị trong R0
Viết chương trình hiển thị giá trị của kênh 0 của ADC lên LCD dùng chương trình con READADC đã viết
Kiểm tra:
Biên dịch và kiểm tra hoạt động của chương trình
Để giao tiếp với ADC, ta phải ghi ra ngoại vi ở vùng nhớ (giá trị nạp vào thanh ghi DPTR) bao nhiêu?
Khoảng thời gian chờ ADC chuyển đổi giá trị được chọn là bao nhiêu?
Giá trị này có phải giá trị thực của điện áp đặt vào kênh 0 hay không?
Để hiển thị giá trị thực tế của mức điện áp đặt vào kênh 0 ta phải làm như thế nào?
BÁO CÁO:
1 Chương trình:
EN BIT P3.3
RS BIT P3.5 LCDADDR EQU 6000H ADCADDR EQU 4000H ORG 2000H
MAIN:
CALL READADC PUSH 0
Trang 20MOV DPTR, #LCDADDR CALL CLRSCREEN
CALL INIT_LCD CALL DISPLAYSTRING POP ACC
CALL SPLIT_A ; Tách giá trị hiển thị thành từng hàng MOV A, 20H ; Hàng trăm
CALL DISP MOV A, 21H ; Hàng chục CALL DISP
MOV A, 22H ; Hàng đơn vị CALL DISP
SJMP $ READADC:
MOV DPTR,#ADCADDR ;Start ADC MOV A,#0
MOVX @DPTR,A CALL WAIT_LCD ;EOC MOVX A,@DPTR ;OE MOV R0,A
MOV P1,A ;Hiển thị A lên các LED tại port 1 để quan sát RET
DISPLAYSTRING:
MOV R2, #0 LOOP:
Trang 21MOV DPTR, #MESS MOV A, R2
MOVC A, @A+DPTR
JZ EXIT ACALL DISP INC R2 SJMP LOOP EXIT: RET
SPLIT_A:
MOV B, #10 DIV AB ORL B, #30H ; Đổi sang mã ASCII MOV 22H, B ; Hàng đơn vị
MOV B, #10 DIV AB ORL B, #30H ; Đổi sang mã ASCII MOV 21H, B ; Hàng chục
ORL A, #30H ; Đổi sang mã ASCII MOV 20H, A ; Hàng trăm
RET INIT_LCD:
MOV A, #38H ACALL COMD MOV A, #0EH ACALL COMD
Trang 22MOV A, #06H ACALL COMD RET
CLRSCREEN:
MOV A, #01H ACALL COMD RET
COMD:
MOV DPTR, #LCDADDR SETB EN
CLR RS MOVX @DPTR, A CLR EN
ACALL WAIT_LCD RET
DISP:
MOV DPTR, #LCDADDR SETB EN
SETB RS MOVX @DPTR, A CLR EN
ACALL WAIT_LCD RET
WAIT_LCD:
Trang 23MOV R6, #16 DL: MOV R5, #144
DJNZ R5, $ DJNZ R6,DL RET
Trang 24LCD
b Trả lời câu hỏi
1) Để giao tiếp với ADC, ta phải ghi ra ngoại vi ở vùng nhớ (giá trị nạp vào thanh ghi
DPTR) bao nhiêu?
Để giao tiếp với ADC, ta phải ghi ra ngoại vi ở vùng nhớ 4000H – 5FFFH, giá trị nạp vào thành ghi DPTR là 4000H
2) Khoảng thời gian chờ ADC chuyển đổi giá trị được chọn là bao nhiêu?
Khoảng thời gian chờ ADC chuyển đổi giá trị được chọn là
3) Giá trị này có phải giá trị thực của điện áp đặt vào kênh 0 hay không?
Giá trị của kênh 0 hiển thị lên LCD là giá trị sau khi quy đổi
4) Để hiển thị giá trị thực tế của mức điện áp đặt vào kênh 0 ta phải làm như thế nào?
Để hiển thị giá trị thực tế của mức điện áp đặt vào kênh 0, ta sử dụng công thức:
Trong đó, A là giá trị sau khi quy đổi
Trang 25THÍ NGHIỆM 5
Mục tiêu: Nắm được cách thức giao tiếp với ADC
Yêu cầu:
Viết chương trình con CALADC tính toán giá trị điện áp thực tế đặt vào kênh 0 ADC từ giá trị
đo được của ADC
Chương trình nhận giá trị ngõ vào chứa trong R0 (là kết quả của chương trình con READADC) Giá trị trả về chứa trong R0 và R1, R0 chứa giá trị nguyên và R1 chứa giá trị thập phân
Hiển thị giá trị đo được lên LCD theo cấu trúc: "Voltage: x.xx V" với x.xx là giá trị điện áp đo được, với hai số sau dấu chấm
Kiểm tra:
Biên dịch và kiểm tra hoạt động của chương trình, so sánh giá trị hiển thị với giá trị đo được dùng VOM
Khoảng thời gian dùng để cập nhật giá trị của ADC là bao nhiêu?
Giải thích quá trình tính toán để chuyển đổi giá trị đọc được từ ADC sang giá trị Volt?
BÁO CÁO:
1 Chương trình:
EN BIT P3.3
RS BIT P3.5 LCDADDR EQU 6000H ADCADDR EQU 4000H ORG 2000H
MAIN:
CALL READADC PUSH 0
Trang 26MOV DPTR, #LCDADDR CALL CLRSCREEN
CALL INIT_LCD CALL DISPLAYSTRING POP ACC
CALL CALADC ; Tính giá trị điện áp MOV 20H, R0
ORL 20H, #30H ; Lấy mã ASCII phần nguyên MOV A, R1
CALL SPLIT_A ; Tách giá trị hiển thị thành từng hàng CALL DISPLAY_GIATRI ; Hiển thị giá trị
SJMP $ READADC:
MOV DPTR,#ADCADDR ;Start ADC MOV A,#0
MOVX @DPTR,A CALL WAIT_LCD ;EOC MOVX A,@DPTR ;OE MOV R0,A
MOV P1,A ;Hiển thị A lên các LED tại port 1 để quan sát RET
CALADC:
INC A ; Trả về giá trị tính toán
JZ C_S ; A = 256D (0B), skip MOV B, #5
Trang 27MUL AB MOV R0, B ; Giá trị phần nguyên MOV B, #10
MUL AB MOV 31H, B ; Chữ số hàng chục phần thập phân MOV B, #10
MUL AB MOV 32H, B ; Chữ số hàng đơn vị phần thập phân MOV A, 31H
MOV B, #10 MUL AB ADD A, 32H ; Giá trị phần thập phân MOV R1, A
RET C_S: MOV R0, #5 ; Nếu A = 256 thì Vin = 5.00 V
MOV R1, #0 RET
MOV A, 22H ; Hiển thị hàng đơn vị phần thập phân
Trang 28CALL DISP MOV A, #' ' ; Hiển thị khoảng trống CALL DISP
MOV A, #'V' ; Hiển thị đơn vị CALL DISP
RET DISPLAYSTRING: ; Hiển thị “Voltage: “
MOV R2, #0 LOOP:
MOV DPTR, #MESS MOV A, R2
MOVC A, @A+DPTR
JZ EXIT ACALL DISP INC R2 SJMP LOOP EXIT: RET
SPLIT_A: ; Tách A thành hàng chục và hàng đơn vị
MOV B, #10 DIV AB ORL B, #30H ; Mã ASCII hàng đơn vị MOV 22H, B
ORL A, #30H ; Mã ASCII hàng chục MOV 21H, A
RET
Trang 29INIT_LCD:
MOV A, #38H ACALL COMD MOV A, #0EH ACALL COMD MOV A, #06H ACALL COMD RET
CLRSCREEN:
MOV A, #01H ACALL COMD RET
COMD:
MOV DPTR, #LCDADDR SETB EN
CLR RS MOVX @DPTR, A CLR EN
ACALL WAIT_LCD RET
DISP:
MOV DPTR, #LCDADDR SETB EN
SETB RS
Trang 30MOVX @DPTR, A CLR EN
ACALL WAIT_LCD RET
WAIT_LCD:
MOV R6, #16 DL: MOV R5, #144
DJNZ R5, $ DJNZ R6,DL RET
Trang 31LCD
b Trả lời câu hỏi
1) Khoảng thời gian dùng để cập nhật giá trị của ADC là bao nhiêu?
Khoảng thời gian dùng để cập nhật giá trị của ADC là 5ms
2) Giải thích quá trình tính toán để chuyển đổi giá trị đọc được từ ADC sang giá trị Volt?
Giá trị quy đổi có tầm 1 – 256 mà giá trị trả về từ ADC0809 vào thanh ghi A có tầm giá trị từ 0 – 255 nên trước khi tính toán, ta tăng giá trị thanh ghi A lên 1 Giá trị cần hiển thị Vin có công thức:
Lệnh nhân hai số 8 bit A, B là MUL AB có kết quả là một số 16 bit BA = A * B, trong
đó 8 bit trọng số cao sẽ được lưu trong B, 8 bit trọng số thấp sẽ được lưu trong A Phép chia cho 256 tương ứng với phép dịch trái 8 bit
Về thuật toán thực hiện biểu thức Vin trên, ta có thể làm như sau: Thực hiện phép nhân 5*A trước, kết quả trả về B sẽ chứa trọng số cao, A sẽ chứa trọng số thấp Sau đó hình dung phép chia cho 256 là phép dịch trái dấu chấm thập phân, dịch qua 8 bit Khi đó B sẽ
Trang 32chính là phần nguyên của biểu thức Vin, A sẽ là phần thập phân của biểu thức Vin
Để xử lý phần thập phân của biểu thức Vin chứa trong A, ta tiếp tục lấy A*10 và
sẽ có một chữ số tràn qua B, đó chính là số thứ nhất sau dấu chấm thập phân Tiếp tục thực hiện A*10, ta được số thứ 2 sau dấu chấm thập phân.