Hướng dẫn làm Lab 1: Cấu trúc chương trình đề xuất cho các bài thí nghiệm | Đại học Bách Khoa, Đại học Đà Nẵng
Hưỡng dẫn làm Lab 1: Cấu trúc chương trình đề xuất cho các bài thí nghiệm | Đại học Bách Khoa, Đại học Đà Nẵng giúp sinh viên tham khảo, ôn luyện và phục vụ nhu cầu học tập của mình cụ thể là có định hướng, ôn tập, nắm vững kiến thức môn học và làm bài tốt trong những bài kiểm tra, bài tiểu luận, bài tập kết thúc học phần, từ đó học tập tốt và có kết quả cao cũng như có thể vận dụng tốt những kiến thức mình đã học
Môn: Cấu trúc máy tính và vi xử lí
Trường: Trường Đại học Bách khoa, Đại học Đà Nẵng
Thông tin:
Tác giả:
Preview text:
Hướng dẫn TN VXL
Cấu trúc chương trình đề xuất cho các bài thí nghiệm.
Phần này đưa ra đề xuất cấu trúc chương trình cho TN VXL, từ đó đưa ra gợi ý về việc sắp xếp
code sao cho hợp lý để thực hiện bài TN. Khi code một yêu cầu nào đó, tốt nhất là phân tích và
sắp xếp chương trình gọn gàn, hợp lý, bài 1 còn dễ qua mấy bài sau thì @@. .ORG 0 RJMP MAIN
//Khai báo các vector ngắ t. /* Từ 0x00 đế
n 0x3C là nơi khai báo các vector ngắ
t, không nến viết code trong
vùng này, vì vậy chương trình chính nến bắ t đầ4 u từ 0x40*/ .ORG 0X40 MAIN:
/*Trong MAIN khai báo những gì chỉ ; chạy 1 lầ4 n, ví dụ: Cầ u hình PORT INPUT, OUTPUT Khơ ;i động LCD 16x2, Khơ ;i tạo hiế; n thị LCD ...*/ LOOP:
/*Chương trình trong vòng lập chạy liến tục, ví dụ kiế; m tra nút nhầ n, quét led ma
trận, quét led 7 đoạn, đọc giá trị ADC liến tục rô4 i hiế; n thị lến LCD...*/ /*...*/ JMP LOOP
//-------------------------------------------------------- //Các Chương trình con
//-------------------------------------------------------- CTRINH_CON_1:
//Nội dung Chương trình con thứ 1 RET
//-------------------------------------------------------- CTRINH_CON_2:
//Nội dung Chương trình con thứ 2 RET
//-------------------------------------------------------- //Các chương trình xư; lý ngắ t
//-------------------------------------------------------- TIMER1_ISR:
//Nội dung đoạn chương trình xư; lý ngắ t TIMER1 RETI Ví dụ LAB1_1 Bài 1.
Trước khi làm bài này, SV cần hiểu được thiết kế trong board TN. Dưới đây là thiết kế khối DIP
SWITCH. DIP SWITCH là linh kiện có mã số U21 trong hình, (các bạn đã gặp nó trong TN KTS), và
được kết nối với hàng header 8x2 J41, thiết kế này giúp linh động trong việc kết nối với VXL, có
thể kết nối cả 8 DIP SW vào PORT A, B, C hoặc D tùy ý.
Giả sử DIP SW kết nối với PORT A thì DIP SW ở trạng thái OFF thì PORT A có giá trị là gì?
Giá trị High-Z (thả nổi). Vì DIP SW off, mạch hở.
Vì vậy PORT A phải khai báo thêm điện trở kéo lên, nếu vậy thì lúc này port A mức 1.
Tương tự khối BAR LED, tín hiệu điều khiển từ vxl mức 1 => đèn sáng.
Tóm lại: DIP SW OFF => PORT A mức 1 => Đèn phải tắt (theo đề) => Tức tín hiệu điều khiển đèn
mức 0, nó bị ngược lại so với tín hiệu đọc được.
Vì vậy tín hiệu đk đèn port b= tín hiệu đọc được từ port A XOR 0xFF. (Để đảo bit lại) Chương trình đề xuất: .ORG 0 RJMP MAIN
//-------------------------------------------------------- .ORG 0X40 MAIN: /*PORT A kế
t nôi vào DIP SWITCH => PORT A cầ4 n pha ;i là input, input thì pha ;i khai báo thếm điện trơ
; kéo lến. Không khai báo kéo lến sẽ bị nhiế[ u, lúc TN thư; bo; khai báo điện trơ ; kéo lến rô4 i đưa tay lại gầ4 n dầy port sẽ biế t. PORT B kế t nôi với LED đế;
hiế;n thị => PORT B là output, sau khi khai báo B là output thì cầ4 n đặt giá trị ban đầ4
u cho đèn là sáng hay tắ t. ...*/ LDI R16,0x00 OUT DDRA,R16 LDI R16,0XFF OUT PORTA,R16 LDI R16,0XFF OUT DDRB,R16 LDI R16,0X00 OUT PORTB,R16 LOOP:
/* SWITCH OFF -> đèn tắ t, chương trình cầ4 n làm là: Đọc giá trị từ Port A Lầ y bù giá trị đã đọc Xuầ
t giá trị đã bù ra PORT B */ IN R19,PINA LDI R17,0XFF EOR R19,R17 OUT PORTB,R19 JMP LOOP LAB1_1 Bài 2. Gợi ý, mầ y dầu ... là phầ4
n code các bạn tự bô; xung vô, bài này có thế; bị tràn sô khi hiế; n thị, kệ đi hiế; n thị 8 bit cuô i là đc rô4 i. /* Kế t nôi dầy DIP SW -> PORT A BARLED -> PORT B */ .ORG 0 RJMP MAIN
//-------------------------------------------------------- .ORG 0X40 MAIN: /* Khai báo */ //PORT A input, PULL-up. LDI R16,0x00 OUT DDRA,R16 LDI R16,0XFF OUT PORTA,R16
//PORT B OUTPUT, gán giá trị ban đầ4 u bằng 0. LDI R16,0XFF OUT DDRB,R16 LDI R16,0X00 OUT PORTB,R16 LOOP: /* Vòng lập liến tục */
// Đọc giá trị PORT A, lưu vào R19 IN R19, PINA LDI R17, 0XFF EOR R19, R17
// Cộng thếm 5, xem lại các lệnh ADC, ADD, ADIW. ADIW R19, 5 // Xuầ t giá trị ra PORT B OUT PORTB, R19 JMP LOOP LAB1_1 Bài 3 Gợi ý, mầ y dầu ... là phầ4
n code các bạn tự bô; xung vô. Đế4
ví dụ bị nhầ4m nhé, đúng là 0011_1111. Kế t qua; tô
i đa là 15*15 = 225 => 8 bit cuôi cu ;a kết qua ; là được. /* Kế t nôi dầy DIP SW -> PORT A BARLED -> PORT B */ .ORG 0 RJMP MAIN
//-------------------------------------------------------- .ORG 0X40 MAIN: /* Khai báo */ //PORT A input, PULL-up. LDI R16,0x00 OUT DDRA,R16 LDI R16,0XFF OUT PORTA,R16
//PORT B OUTPUT, gán giá trị ban đầ4 u bằng 0. LDI R16,0XFF OUT DDRB,R16 LDI R16,0X00 OUT PORTB,R16 LOOP: /* Vòng lập liến tục */
// Đọc giá trị PORT A, lưu vào R19 IN R19, PINA LDI R17, 0XFF EOR R19, R17
// Tách 4 bit cao trong R19 lưu vào R20, 4 bit thầ p đế; trong R19
//VD: R20 = 0000 0011 và R19 = 00001111 MOV R20, R19 SWAP R20 ANDI R20, 0X0F ANDI R19, 0X0F
// Thực hiện phép nhần ko dầ u bằng hàm MUL, kế t qua
; phép nhần là mầy bit, lưu
trong đầu, cái nào trong? (tự xem lại) MUL R19, R20 // Xuầ t giá trị 8 bit thầ p ra PORT B OUT PORTB, R0 JMP LOOP LAB1_1 Bài 4 Gợi ý, mầ y dầu ... là phầ4
n code các bạn tự bô; xung vô. Sô có dầ4u bù 2 nhé các bạn. /* Kế t nôi dầy DIP SW -> PORT A BARLED -> PORT B */ .ORG 0 RJMP MAIN
//-------------------------------------------------------- .ORG 0X40 MAIN: /* Khai báo */ //PORT A input, PULL-up. LDI R16,0x00 OUT DDRA,R16 LDI R16,0XFF OUT PORTA,R16
//PORT B OUTPUT, gán giá trị ban đầ4 u bằng 0. LDI R16,0XFF OUT DDRB,R16 LDI R16,0X00 OUT PORTB,R16 LOOP: /* Vòng lập liến tục */
// Đọc giá trị PORT A, lưu vào R19 IN R19, PINA LDI R17, 0XFF EOR R19, R17
// Tách 4 bit cao trong R19 lưu vào R20, 4 bit thầ p đế; trong R19
// VD: R20 = 0000 0011 và R19 = 00001111 MOV R20, R19 SWAP R20 ANDI R20, 0X0F ANDI R19, 0X0F // Kiế;
m tra bit 3 trong R20 và R19 có là bit 1 (sô
ầm không), nếu là sô ầm, chèn 1111 vào 4 bit trọng sô cao.
// VD: R20 = 0000 0011 và R19 = 1111 1111 LDI R22, 0X02 LDI R21, 0X08 AND R21, R19 SBRC R21, 3 // kt bit dầ u nế u ầm thì cộng thếm 1111 ADIW R19, 0XF0 SBRS R21, 3 // kt bit dầ u nế
u dương thì trừ thanh ghi R22 đi 1 DEC R22 LDI R21, 0X08 AND R21, R20 SBRC R21, 3 ADIW R20, 0XF0 SBRS R21, 3 DEC R22
// Thực hiện phép nhần bằng lệnh MUL, MULS, MULSU.
SBRC R22, 1 // R22 = 2 => 2 sô có dầ u MULS R19, R20
SBRC R22, 0 // R22 = 1 => 1 sô có dầ u 1 sô không dầu MULSU R19, R20 DEC R22 BRCC SKIP MUL R19 R20 // Xuầ t giá trị 8 bit thầ p ra PORT B SKIP: OUT PORTB, R0 JMP LOOP LAB1_1 Bài 5 Gợi ý, mầ y dầu ... là phầ4
n code các bạn tự bô; xung vô. Bài này mục đích là làm
việc trến từng bit trong port. SW trong board thí nghiệm 1 chần xuô ng đầt rô4i, chần điế4 u khiế; n nô
i VXL, vậy nhần nút sẽ là mức 0, không nhầ n sẽ là mức 1 (pha;i
khai báo input pull-up). Lúc làm TN coi chừng nhầ4
m với bàn phím ma trận 4x4 nhé. /* Kế t nôi dầy DIP SW0 -> PA0 LED đơn -> PA1 */ .ORG 0 RJMP MAIN
//-------------------------------------------------------- .ORG 0X40 MAIN: /* Khai báo */ //PA0 input, PULL-up. CBI DDRA, 0 SBI PORTA, 0
//PA1 OUTPUT, gán giá trị ban đầ4 u bằng 0. SBI DDRA, 1 CBI PORTA, 1 LOOP: /* Vòng lập liến tục */
// Tự làm nha, nhớ chú thích đầ4 y đu ;. IN R19, PORTA SBRC R19, 0
ANDI R19, 0X00 // PA0 = 1 => ko nhầ
n => AND thanh ghi với 0 đế; PA1 = 0 SBRS R19, 0
ORI R19, 0x02 // PA0 = 0 => nhầ
n => OR thanh ghi với 2 đế; PA1 = 1 JMP LOOP LAB1_2 Bài 1
Bài này sinh viên đổi đoạn code đã cho thành dạng theo cấu trúc đã trình bày ở trên, đổi đi, xài
cho quen sau này học mấy bài sau đỡ viết lộn. /* Kế t nôi dầy TEST STATION -> PA0 */ .ORG 0 RJMP MAIN
//-------------------------------------------------------- .ORG 0X40 MAIN: /* Khai báo */ //PA0 OUTPUT SBI DDRA, 0 LOOP: /* Vòng lập liến tục */ SBI PORTA, PINA0 CBI PORTA, PINA0 rjmp loop LAB1_2 Bài 2
Bài này đụng đến chương trình con rồi. Khi viết chương trình con, tốt nhất là viết chú thích cho
chương trình con đó, để sau này có gì dùng lại, đặc biệt là khi đi thi TN. Trong báo cáo phải viết
chú thích chương trình con.
Ví dụ: Đề bài yêu cầu viết chương trình con CONG5 có nhiệm vụ cộng 3 số 8 bit lưu trong R19,
R20, R21, kết quả trả về R23:R22. Gợi ý viết chú thích:
//-------------------------------------------------------- //CONG5
//-------------------------------------------------------- /* INPUT: R19, R20, R21 OUTPUT: R22, R23
Description: R23:R22 = R19 + R20 + R21 */ CONG5:
//Đoạn chương trình thực hiện yếu cầ4 u. RET .ORG 0 RJMP MAIN .ORG 0X40 MAIN:
//Khai báo PA0 OUTPUT, gán giá trị ban đầ4 u bằng 1 LDI R16, 0XFF OUT DDRA, R16 OUT PORTA, R16 LOOP: //Đa ;o bit PA0 IN R19, PORTA COM R19
//Gọi lại chương trình con Delay1s RCALL Delay1s JMP LOOP
//-------------------------------------------------------- //Các Chương trình con
//-------------------------------------------------------- /* Delay1ms INPUT: None OUTPUT: None
Description: Delay bằng vòng lập 1ms, với thạch anh 8MHz, hệ sô chia 8. */ Delay1ms: LDI R20, 250 LP: NOP DEC R20 BRNE LP RET
//-------------------------------------------------------- Delay10ms: LDI R20, 10 LP10: RCALL Delay1ms DEC R20 BRNE LP10 RET
//-------------------------------------------------------- Delay100ms: LDI R20, 100 LP100: RCALL Delay1ms DEC R20 BRNE LP100 RET
//-------------------------------------------------------- Delay1s: LDI R21, 10 LDI R20, 100 LP1000: RCALL Delay1ms DEC R20 BRNE LP1000 DEC R21 BRNE LP1000 RET LAB1_2 Bài 3
Thanh ghi dịch sử dụng là 74HC595.
Các chân quan trọng cần nhớ 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ầ4 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ầ4n cứng lại kế t nôi port B thì chỉ ; cầ4n đô;
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é. ... 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 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 đầ4 u như sau: Data = 0, RS=0, RW=1, EN=0. */ ...
//Gọi chương trình con khơ
;i tạo nguô4n (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 tro ; con tro; vế4 vị trí DDRAM 0x00 ...
//Dưới đầy là đoạn code tra ba ;ng, xuầ
t ký tự hàng thứ 1 ra LCD cho đế n khi gặp ký
tự 0x00LDI 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ì ca ;, vì mọi thứ chỉ ; cầ4n chạy 1 lầ4 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 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 đầ4 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 đầ4 u như sau: Data = 0, RS=0, RW=1, EN=0. */ ...
//Gọi chương trình con khơ
;i tạo nguô4n (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. ...