Trong ví dụ này có 2 lệnh mới được dùng, cp và setm. Lệnh cp dùng để so sánh
giữa hai giá trị, một trong hai giá trị đó phải được lưu trong một thanh ghi làm việc Wn,
đặc biệt là phải được lưu trong thanh ghi WREG (W0)nếu toán hạng thứ hai là một
thanh ghi (ô nhớ) bình thường nằm trong 8192 địa chỉ RAM đầu tiên. Toán hạng thứ hai
có thể là một toán hạng tức thời (có độ lớn 5-bit) hay một thanh ghi làm việc khác.
Lệnh setm thực hiện thao tác ngược lại với lệnh clear. Lệnh setm được dùng để
bật(đặt bằng 1)tất cả các bit của một thanh ghi làm việc hay một thanh ghi bình thường
nằm trong 8192 địa chỉ RAM đầu tiên.
15 trang |
Chia sẻ: lylyngoc | Lượt xem: 2913 | Lượt tải: 1
Bạn đang xem nội dung tài liệu Đề tài Chương trình hợp ngữ giao tiếp nút nhấn/công tắc và LCD với dsPIC, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
Người báo cáo: Nguyễn Quang Nam Tài liệu: TUT04.01
Ngày: 8/3/2006 Trang: 1/15
Tutorial no 04.01
Gửi đến: Đoàn Hiệp, www.picvietnam.com
Nội dung: Chương trình hợp ngữ giao tiếp nút nhấn/công tắc và LCD với dsPIC
MICROSOFT WORD
Tóm tắt:
Đây là tutorial 3 về lập trình hợp ngữ với dsPIC. Tutorial này hướng dẫn viết chương trình hợp
ngữ giao tiếp với các nút nhấn/công tắc và LCD cho dsPIC: minh hoạ cách đọc tín hiệu ngõ vào số,
điều khiển LCD bằng phương pháp định thời và kiểm tra cờ bận (busy flag). Một số lệnh và kỹ thuật
lập trình mới cũng được giới thiệu.
1. Giới thiệu
Trong tutorial 2, việc xuất dữ liệu ra các ngõ ra số đã được giới thiệu. Tutorial này
giới thiệu thêm thao tác đọc các ngõ vào số, với các ví dụ cụ thể là đọc trạng thái các
công tác và trạng thái cờ bận của LCD. Một số lệnh mới thuộc các nhóm lệnh di chuyển
dữ liệu, lệnh luận lý, và lệnh so sánh được giới thiệu ở đây. Ngoài ra, macro và kỹ thuật
định thời dùng ngắt ở mức tối thiểu cũng được giới thiệu.
2. Các quy ước trong tài liệu
Mô tả Biểu thị Ví dụ
Font Palatino Linotype:
In nghiêng Tài liệu tham khảo
dsPIC30F/33F
Programmer’s Reference
Manual
Viết hoa chữ đầu Một menu, hộp thoại Chọn Project Wizard
Đặt trong dấu nháy kép
Tên riêng (của tập tin,
project, …) “Vidu3”
Font Courier:
Mã nguồn mov #0x8010, W0
Courier thường
Tên tập tin Vidu3-1.s
3. Các ví dụ về công tắc và LCD
Bạn hãy chép các tập tin nguồn được đính kèm vào một thư mục nào đó mà bạn sẽ
dùng để tạo ra project “Vidu3”. Hình 3.1 thể hiện sơ đồ nguyên lý của mạch phần cứng
Người báo cáo: Nguyễn Quang Nam Tài liệu: TUT04.01
Ngày: 8/3/2006 Trang: 2/15
được dùng với tutorial này, chú ý là chân RF3 cùng với mạch điều khiển đèn nền
(backlight) của LCD không được thể hiện trong sơ đồ nguyên lý. Cũng tương tự như
trong tutorial 2, bạn không cần thực hiện phần mạch nằm trong khung nét đứt nếu bạn
dùng bộ dao động nội của dsPIC.
RE[0..3]
RB[0..4]
RB0
RB1
RB2
RB3
RB4
R
B
0
R
B
0
R
B
1
R
B
1
R
B
2
R
B
2
R
B
3
R
B
3
R
B
4
R
B
4
RE0
RE1
RE2
RE3
R
D
1
R
D
0
R
E
8
RE8
RD0
RD1
R
E
0
R
E
1
R
E
2
R
E
3
CLKIN/OSC19
RC15/CLKO/OSC210
MCLR1
RB0/CN2/VREF+/AN0/EMUD32
RB1/CN3/VREF-/AN1/EMUC33
RB2/CN4/SS1/AN24
RB3/CN5/INDX/AN35
RB4/CN6/IC7/QEA/AN46
RB5/CN7/IC8/QEB/AN57
RC13/CN1/U1ATX/T2CK/SOSCI/EMUD11
RC14/CN0/U1ARX/T1CK/SOSCO/EMUC12
EMUC2/OC1/IC1/INT1/RD015
EMUD2/OC2/IC2/INT2/RD114
RE0/PWM1L 26
RE1/PWM1H 25
RE2/PWM2L 24
RE3/PWM2H 23
RE4/PWM3L 22
RE5/PWM3H 21
FLTA/INT0/RE8 16
RF2/SDA/SDI1/U1RX/EMUC/PGC 18
RF3/SCL/SDO1/U1TX/EMUD/PGD 17
AVDD 28
AVSS 27
U1
DSPIC30F4012DIP
Vdd
X1
8MHz
C1
33pF
C2
33pF
Vdd
R1 33k
1234567
141312111098
SW1
2345678 1
RP1
10k
D
7
14
D
6
13
D
5
12
D
4
11
D
3
10
D
2
9
D
1
8
D
0
7
E
6
R
W
5
R
S
4
V
SS
1
V
D
D
2
V
EE
3
LCD1
LM016L
RV1
5k
Hình 3.1: Sơ đồ nguyên lý phần cứng dùng cho tutorial 3
3.1. Ví dụ 3-1
Làm theo các bước như trong tutorial 1 để tạo ra một project có tên là “Vidu3”, sau
đó bạn thêm vào project tập tin nguồn “Vidu3-1.s” và kịch bản liên kết
“p30f4012.gld”. Để tiện theo dõi, chương trình nguồn “Vidu3-1.s” được liệt kê
dưới đây, với một số phần chú thích được cắt bỏ cho thuận tiện. Vì các lệnh đã được
chú thích khá chi tiết, tôi chỉ giải thích một số điểm mới trong chương trình, tại những
dòng lệnh mà tôi đã đánh số (để tiện giải thích).
Liệt kê mã nguồn “Vidu3-1.s”:
.include "p30fxxxx.inc"
config __FOSC, CSW_FSCM_OFF & FRC_PLL4 ;Clock = 32 MHz
config __FWDT, WDT_OFF
config __FBORPOR, MCLR_EN & PBOR_OFF
config __FGS, CODE_PROT_OFF
Người báo cáo: Nguyễn Quang Nam Tài liệu: TUT04.01
Ngày: 8/3/2006 Trang: 3/15
;-------------------------------------------------------------------------------
;Cac hang so cua chuong trinh (gia tri tuc thoi dung trong chuong trinh)
.equiv ms_count, 125 ;So dem tuong ung voi 1 ms, cho timer 1
.equiv LCD_BL, 3 ;Tin hieu Back Light cho LCD, chan RF3
.equiv LCD_EN, 8 ;Tin hieu Enable cho LCD, chan RE8
.equiv LCD_RW, 0 ;Tin hieu Read/Write cho LCD, chan RD0
.equiv LCD_RS, 1 ;Tin hieu Reset cho LCD, chan RD1
.equiv LCD_DAT, LATE ;Cac tin hieu Data cho LCD, chan RE0..RE3 (D4..D7)
.equiv LCD_TRIS, TRISE ;Tristate cua cac tin hieu Data cho LCD
.equiv LCD_clear, 0x01 ;Xoa man hinh LCD
.equiv LCD_home, 0x02 ;Tro ve dau dong
.equiv LCD_normal, 0x06 ;Che do nhap du lieu binh thuong
.equiv LCD_normal_s, 0x07 ;Che do nhap du lieu binh thuong, dich man hinh
.equiv LCD_off, 0x08 ;Tat man hinh
.equiv LCD_on, 0x0C ;Bat man hinh
.equiv LCD_on_crsr, 0x0E ;Bat man hinh va con tro
.equiv LCD_on_blink, 0x0F ;Bat man hinh va con tro (nhap nhay)
.equiv LCD_4b2l, 0x28 ;Che do 2 dong, giao tiep 4 bit du lieu
.equiv LCD_homeL1, 0x80 ;Ve dau dong 1
.equiv LCD_homeL2, 0xC0 ;Ve dau dong 2
;-------------------------------------------------------------------------------
;Cac khai bao toan cuc:
.global __reset ;Khai bao nhan bat dau chuong trinh (bat buoc)
.global __T1Interrupt;Khai bao toan cuc chuong trinh xu ly ngat Timer 1
;Khai bao bang hang so trong ROM
.section Chuoi1, psv, address(0x0300) ;Chuoi ky tu se xuat ra LCD
.asciz "Hello world!" ;Chuoi ky tu se duoc xuat ra LCD
;-------------------------------------------------------------------------------
;Khai bao cac bien trong RAM
.section .bss
.align 2 ;Chinh dia chi theo boi so cua 2
time_out: .space 2 ;Khai bao bien 'time_out' kieu word (2 byte)
;-------------------------------------------------------------------------------
;Cac macro
Người báo cáo: Nguyễn Quang Nam Tài liệu: TUT04.01
Ngày: 8/3/2006 Trang: 4/15
.macro DelayNTcy n ;Macro tao tre n chu ky lenh, n > 2
1 repeat #(\n-1)
2 nop
.endm
;-------------------------------------------------------------------------------
;Doan ma trong vung nho chuong trinh
.text ;Bat dau doan ma chuong trinh
__reset:
mov #__SP_init, W15 ;Khoi tao con tro ngan xep (stack)
mov #__SPLIM_init, W0
mov W0, SPLIM ;Khoi tao thanh ghi gioi han con tro ngan xep (stack)
nop ;Can mot lenh NOP sau khi ghi vao SPLIM
clr W0 ;Xoa thanh ghi lam viec W0
mov W0, W14 ;Xoa cac thanh ghi W1 den W14
repeat #12
mov W0,[++W14] ;Dia chi cua cac thanh ghi: 0x0002 - 0x001C
clr W14
;-------------------------------------------------------------------------------
rcall Init_TMR1 ;Khoi tao cho TMR1
rcall Init_PORTS ;Khoi tao cac cong I/O
bset CORCON, #PSV ;Cho phep dung PSV
mov #psvpage(Chuoi1), W0 ;Lay dia chi cua chuoi ky tu
mov W0, PSVPAG ;ghi vao thanh ghi trang PSV
mov #psvoffset(Chuoi1), W4 ;W4 la con tro den chuoi ky tu
mov #(ms_count*50), W0 ;Nguong tran 50 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 50 ms
rcall Init_LCD ;Het thoi gian cho, vay khoi tao module LCD
mov #(ms_count*500), W0 ;Nguong tran 500 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 500 ms
wrt_loop1:
mov.b [W4++], W0 ;Doc mot ky tu
3 cp0.b W0 ;Da het chuoi chua?
bra z, homeL2 ;Da het chuoi, vay nhay den lenh chuyen dong
rcall LCD_dat4 ;Chua het chuoi, xuat ky tu trong W0 ra LCD
mov #(ms_count*1), W0 ;Nguong tran 1 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 1 ms
Người báo cáo: Nguyễn Quang Nam Tài liệu: TUT04.01
Ngày: 8/3/2006 Trang: 5/15
bra wrt_loop1 ;Chuyen sang ky tu ke tiep
homeL2:
mov #LCD_homeL2, W0 ;Chuyen den dau dong thu hai
rcall LCD_cmd4
mov #(ms_count*1), W0 ;Nguong tran 1 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 1 ms
mov #psvoffset(Chuoi1), W4 ;W4 la con tro den chuoi ky tu
wrt_loop2:
mov.b [W4++], W0 ;Doc mot ky tu
cp0.b W0 ;Da het chuoi chua?
bra z, main_loop ;Da het chuoi, vay nhay den vong lap chinh
rcall LCD_dat4 ;Xuat ky tu trong W0 ra LCD
mov #(ms_count*1), W0 ;Nguong tran 1 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 1 ms
bra wrt_loop2 ;Chuyen sang ky tu ke tiep
main_loop:
nop
nop
bra main_loop ;Vong lap chinh, khong lam viec gi het
;-------------------------------------------------------------------------------
;Chuong trinh con khoi tao TMR1
;TMR1 duoc dung de dem so ms troi qua, o muc xung 8 Mips (fcy = 8 MHz)
;-------------------------------------------------------------------------------
Init_TMR1:
clr TMR1 ;Xoa so dem cua TMR1
mov #ms_count, W0 ;TMR1 tran moi ms
mov W0, PR1 ;Dat nguong tran vao PR1
bclr IFS0, #T1IF ;Xoa co ngat cua TMR1
mov #0x0020, W0 ;TMR1 dung fcy lam clock, prescale la 1:64,
mov W0, T1CON ;nhung chua cho phep TMR1 chay
bset IEC0, #T1IE ;Cho phep ngat khi TMR1 tran
return
;-------------------------------------------------------------------------------
;Chuong trinh con khoi tao cac cong I/O, de noi voi LCD
;-------------------------------------------------------------------------------
Init_PORTS:
Người báo cáo: Nguyễn Quang Nam Tài liệu: TUT04.01
Ngày: 8/3/2006 Trang: 6/15
mov LCD_DAT, W0
4 and.b #0xF0, W0
mov W0, LCD_DAT ;Xoa cac bit chot du lieu LCD
mov LCD_TRIS, W0
and.b #0xF0, W0
mov W0, LCD_TRIS ;Cac chan du lieu LCD la ngo ra
bset LATF, #LCD_BL ;
bclr TRISF, #LCD_BL ;RF3 la ngo ra, noi vao back light LED
bclr LATE, #LCD_EN ;
bclr TRISE, #LCD_EN ;RE8 la ngo ra, noi vao Enable cua LCD
bclr LATD, #LCD_RW ;
bclr TRISD, #LCD_RW ;RD0 la ngo ra, noi vao R/W cua LCD
bclr LATD, #LCD_RS ;
bclr TRISD, #LCD_RS ;RD1 la ngo ra, noi vao Reset cua LCD
return
;-------------------------------------------------------------------------------
;Chuong trinh con delay bang timer 1, gia tri so dem nam trong W0
;-------------------------------------------------------------------------------
Delay_ms:
mov W0, PR1 ;Dat nguong tran vao PR1
bclr time_out, #0 ;Xoa co het thoi gian cho
bset T1CON, #TON ;Bat timer 1
btss time_out, #0 ;Chua het thoi gian cho?
bra $-2 ;Dung, vay tiep tuc cho
bclr T1CON, #TON ;Tat timer 1
clr TMR1
return
;Chuong trinh con khoi tao module LCD
;-------------------------------------------------------------------------------
Init_LCD:
mov #LCD_4b2l, W0 ;Dat che do giao tiep 4-bit, man hinh 2 dong
rcall LCD_cmd4
mov #(ms_count*1), W0 ;Nguong tran 1 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 1 ms
mov #LCD_off, W0 ;Tat man hinh
rcall LCD_cmd4
mov #(ms_count*1), W0 ;Nguong tran 1 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 1 ms
mov #LCD_normal, W0 ;Che do nhap du lieu binh thuong
Người báo cáo: Nguyễn Quang Nam Tài liệu: TUT04.01
Ngày: 8/3/2006 Trang: 7/15
rcall LCD_cmd4
mov #(ms_count*1), W0 ;Nguong tran 1 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 1 ms
mov #LCD_on_blink, W0 ;Bat man hinh, hien con tro nhap nhay
rcall LCD_cmd4
mov #(ms_count*1), W0 ;Nguong tran 1 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 1 ms
mov #LCD_clear, W0 ;Xoa man hinh
rcall LCD_cmd4
mov #(ms_count*5), W0 ;Nguong tran 5 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 5 ms
bclr LATF, #LCD_BL
return
;-------------------------------------------------------------------------------
;Chuong trinh con xuat lenh o che do 4 bit
;Lenh 8-bit dat trong W0, se huy noi dung cua W1, W2
;-------------------------------------------------------------------------------
LCD_cmd4:
bclr LATD, #LCD_RW
bclr LATD, #LCD_RS ;Dat che do xuat lenh
mov LCD_DAT, W1 ;Lay trang thai hien thoi cua thanh ghi chot cong E
and.b #0xF0, W1 ;Xoa 4 bit thap nhat cua LCD_DAT
mov W0, W2 ;Giu lai lenh can xuat trong W2
5 swap.b W0 ;Lay 4 bit cao cua lenh can xuat o RE3..RE0
and.b #0x0F, W0 ;Xoa 4 bit cao cua W0
6 ior.b W1, W0, W1
mov W1, LCD_DAT ;Xuat nibble cao cua lenh ra RE3..RE0
bset LATE, #LCD_EN ;Tao xung Enable
7 DelayNTcy 8
bclr LATE, #LCD_EN ;keo dai toi thieu 1 us
mov LCD_DAT, W1 ;Lay trang thai hien thoi cua thanh ghi chot cong E
and.b #0xF0, W1 ;Xoa 4 bit thap nhat cua LCD_DAT
mov W2, W0 ;Lay lai lenh can xuat tu W2 vao W0
and.b #0x0F, W0 ;Xoa 4 bit cao cua W0
ior.b W1, W0, W1
mov W1, LCD_DAT ;Xuat nibble thap cua lenh ra RE3..RE0
bset LATE, #LCD_EN ;Tao xung Enable
DelayNTcy 8
bclr LATE, #LCD_EN ;keo dai toi thieu 1 us
return ;Xong viec, tro ve chuong trinh goi
Người báo cáo: Nguyễn Quang Nam Tài liệu: TUT04.01
Ngày: 8/3/2006 Trang: 8/15
;-------------------------------------------------------------------------------
;Chuong trinh con xuat du lieu o che do 4 bit
;Du lieu 8-bit dat trong W0, se huy noi dung cua W1, W2
;-------------------------------------------------------------------------------
LCD_dat4:
bclr LATD, #LCD_RW
bset LATD, #LCD_RS ;Dat che do xuat du lieu
mov LCD_DAT, W1 ;Lay trang thai hien thoi cua thanh ghi chot cong E
and.b #0xF0, W1 ;Xoa 4 bit thap nhat cua LCD_DAT
mov W0, W2 ;Giu lai du lieu can xuat trong W2
swap.b W0 ;Lay 4 bit cao cua lenh can xuat o RE3..RE0
and.b #0x0F, W0 ;Xoa 4 bit cao cua W0
ior.b W1, W0, W1 ;
mov W1, LCD_DAT ;Xuat nibble cao cua du lieu ra RE3..RE0
bset LATE, #LCD_EN ;Tao xung Enable
DelayNTcy 8
bclr LATE, #LCD_EN ;keo dai toi thieu 1 us
mov LCD_DAT, W1 ;Lay trang thai hien thoi cua thanh ghi chot cong E
and.b #0xF0, W1 ;Xoa 4 bit thap nhat cua LCD_DAT
mov W2, W0 ;Lay lai du lieu can xuat tu W2 vao W0
and.b #0x0F, W0 ;Xoa 4 bit cao cua W0
ior.b W1, W0, W1 ;
mov W1, LCD_DAT ;Xuat nibble thap cua du lieu ra RE3..RE0
bset LATE, #LCD_EN ;Tao xung Enable
DelayNTcy 8
bclr LATE, #LCD_EN ;keo dai toi thieu 1 us
return ;Xong viec, tro ve chuong trinh goi
;-------------------------------------------------------------------------------
;Trinh phuc vu ngat cho TMR1
;Timer 1 dung de dinh cac thoi gian cho >= 1 ms, va toi da khoang 500 ms
;-------------------------------------------------------------------------------
__T1Interrupt: ;Ten nay da duoc dinh truoc trong tap tin lien ket
bclr IFS0, #T1IF ;Truoc tien, can xoa co ngat
bset time_out, #0 ;Bat co het thoi gian cho
retfie ;Tro ve tu ngat
;-------------------------------------------------------------------------------
.end ;Ket thuc phan ma trong tap tin nay
Người báo cáo: Nguyễn Quang Nam Tài liệu: TUT04.01
Ngày: 8/3/2006 Trang: 9/15
Các dòng 1 và 2 là phần thân của macro DelayNTcy, dùng để tạo trễ n chu kỳ lệnh
(với n > 2, vì để làm trễ 1 hay 2 chu kỳ lệnh đã có lệnh nop hay bra $+2). Bạn dùng
dẫn hướng .macro để khai báo điểm bắt đầu macro, tên của macro và danh sách
các đối số (nếu có), và dùng .endm để đánh dấu điểm kết thúc macro. Nếu bạn đã
khai báo một đối số là ds với dẫn hướng .macro, bạn có thể truy xuất đối số đó
trong macro bằng cách dùng \ds hay &ds&. Dạng truy xuất thứ hai (&ds&) cho
phép bạn nối đối số với các ký tự để tạo ra một tên ký hiệu.
Trong macro DelayNTcy, tôi dùng một đối số là n, để đặt tham số cho lệnh
repeat. Do đặc điểm của lệnh repeat, chúng ta chỉ đặt tham số cho lệnh này là n-
1 nếu cần lặp lại n lần lệnh kế tiếp. Để đảm bảo thứ tự tính toán khi trình hợp dịch
khai triển macro, chúng ta viết #(\n–1) để khi khai triển thì phép trừ được thực
hiện trước, và đối số của lệnh repeat là một giá trị tức thời. Dòng 7 minh họa cách
dùng của macro này trong chương trình. Bạn hãy tham khảo thêm phần “6.11
Directives for substitution/expansion“ của tài liệu MPLAB® ASM30/LINK30 and
Utilities User’s Guide (phiên bản hiện thời là DS51317E) về macro và các dẫn hướng
tương tự dùng cho việc thay thế và khai triển khi hợp dịch.
Tại dòng 3, chúng ta gặp một lệnh mới, cp0. Lệnh này cho phép chúng ta so sánh
một thanh ghi nào đó (nằm trong 8192 địa chỉ RAM đầu tiên) với giá trị zero (0). Bạn
có thể so sánh byte hay word, bằng cách dùng phần mở rộng .B và .W tương ứng.
Bạn có thể dùng lệnh này với chế độ định vị gián tiếp, và khi đó bạn có thể cập nhật
thanh ghi con trỏ ngay trong lệnh.
Tại dòng 4 và 6 là các lệnh and và ior, dùng để thực hiện các phép toán logic AND
và OR. Bạn chú ý là từ khóa cho lệnh thực hiện phép toán OR là ior (inclusive or),
đối lập với lệnh thực hiện phép toán XOR là xor (exclusive or). Các lệnh này cũng
cho phép bạn thao tác trên byte hay word, với các phần mở rộng tương ứng được
dùng trong lệnh. Như trong chương trình đã minh họa, bạn có thể dùng các toán
hạng tức thời với thanh ghi làm việc Wn, hai toán hạng thanh ghi làm việc Wb, Ws
và ghi kết quả vào thanh ghi làm việc thứ ba Wd. Ngoài ra, bạn còn có thể dùng một
ô nhớ và thanh ghi làm việc WREG (W0), hay một thanh ghi làm việc Wb và toán
hạng tức thời, và ghi kết quả vào thanh ghi làm việc Wd.
Dòng 5 là một ví dụ về lệnh hoán đổi các nibble trong một byte, swap.b. Đương
nhiên phần mở rộng .b là để thao tác trên một byte. Nếu bạn dùng phần mở rộng
.w hay chỉ dùng swap (vì phần mở rộng .w được hiểu ngầm), bạn sẽ thực hiện hoán
đổi các byte của một word. Lệnh swap chỉ chấp nhận toán hạng là một trong các
thanh ghi làm việc Wn.
Bạn hãy để ý rằng chương trình xử lý ngắt ở đây rất ngắn, ngoài 2 lệnh bắt buộc
phải có là xóa cờ ngắt và trở về từ ngắt, tôi chỉ dùng thêm một lệnh để bật một cờ
báo hiệu hết thời gian chờ. Như vậy, chương trình xử lý ngắt chỉ chiếm một phần rất
Người báo cáo: Nguyễn Quang Nam Tài liệu: TUT04.01
Ngày: 8/3/2006 Trang: 10/15
nhỏ trong tổng thời gian thực thi của toàn chương trình, và do đó bạn sẽ có thể dễ
dàng xử lý nhiều ngắt cùng mức ưu tiên một cách nhanh chóng.
Một điểm chú ý khác trong chương trình là chương trình con khởi tạo LCD. Theo tài
liệu kỹ thuật của chip HD44780U (đa số các chip điều khiển LCD dạng văn bản
tương thích với chip này) thì việc khởi tạo chế độ giao tiếp 4 bit cần tuân theo quy
trình sau:
- Ghi giá trị hex 3x (x là một chữ số hex bất kỳ), sau đó chờ 4.1 ms
- Ghi giá trị hex 3x, sau đó chờ 100 ms
- Ghi giá trị hex 3x, rồi đến giá trị hex 2x
Kể từ thời điểm này, chip có thể giao tiếp ở chế độ 4-bit.
Tuy nhiên, thử nghiệm thực tế của tôi cho thấy có thể bỏ qua 3 lệnh ghi giá trị hex 3x
mà vẫn có thể giao tiếp với LCD ở chế độ 4-bit, nếu module LCD này đã vừa mới
làm việc ở chế độ giao tiếp 4-bit trước đó. Tôi cho rằng một số module LCD ghi nhớ
chế độ giao tiếp gần nhất. Do đó, nếu bạn không thể khởi tạo module LCD bằng
chương trình con đã đưa ra ở đây, bạn hãy bổ sung thêm các dòng lệnh sau vào
ngay trước lệnh đầu tiên của chương trình con khởi tạo LCD.
Phần bổ sung cho chương trình con khởi tạo LCD:
mov #0x33, W0 ;Ghi 0x33 lan thu nhat
rcall LCD_cmd4
mov #(ms_count*5), W0 ;Nguong tran 5 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 5 ms
mov #0x33, W0 ;Ghi 0x33 lan thu hai
rcall LCD_cmd4
mov #13, W0 ;Nguong tran 100 us cho timer 1
rcall Delay_ms ;Yeu cau cho 100 us
mov #0x33, W0 ;Ghi 0x33 lan thu ba
rcall LCD_cmd4
Ví dụ 3-2
Thực hiện các thao tác tương tự như trong tutorial 2, bạn hãy loại bỏ tập tin
“Vidu3-1.s” khỏi project, và thêm tập tin “Vidu3-2.s” vào project. Trong ví dụ này,
chương trình được thay đổi đôi chút để thực hiện việc đọc trạng thái các công tắc bên
ngoài (nối vào ) và hiển thị trạng thái của các công tắc đó ra LCD. Một số định nghĩa
cho các thanh ghi liên quan đến các công tắc được thực hiện, nhưng không thể hiện ở
đây để tránh lặp lại phần mã chương trình quá nhiều. Vì chỉ có chương trình chính và
chương trình con dùng để khởi tạo các cổng vào/ra là có thay đổi, nên tôi chỉ liệt kê các
phần mã đó ở đây.
Người báo cáo: Nguyễn Quang Nam Tài liệu: TUT04.01
Ngày: 8/3/2006 Trang: 11/15
Trích mã nguồn “Vidu3-2.s”:
. . .
;-------------------------------------------------------------------------------
;Doan ma trong vung nho chuong trinh
.text ;Bat dau doan ma chuong trinh
__reset:
mov #__SP_init, W15 ;Khoi tao con tro ngan xep (stack)
mov #__SPLIM_init, W0
mov W0, SPLIM ;Khoi tao thanh ghi gioi han con tro ngan xep (stack)
nop ;Can mot lenh NOP sau khi ghi vao SPLIM
clr W0 ;Xoa thanh ghi lam viec W0
mov W0, W14 ;Xoa cac thanh ghi W1 den W14
repeat #12
mov W0,[++W14] ;Dia chi cua cac thanh ghi: 0x0002 - 0x001C
clr W14
;-------------------------------------------------------------------------------
rcall Init_TMR1 ;Khoi tao cho TMR1
rcall Init_PORTS ;Khoi tao cac cong I/O
bset CORCON, #PSV ;Cho phep dung PSV
mov #psvpage(Chuoi1), W0 ;Lay dia chi cua chuoi ky tu
mov W0, PSVPAG ;ghi vao thanh ghi trang PSV
mov #psvoffset(Chuoi1), W4 ;W4 la con tro den dong ky hieu
mov #(ms_count*50), W0 ;Nguong tran 50 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 50 ms
rcall Init_LCD ;Het thoi gian cho, vay khoi tao module LCD
mov #(ms_count*500), W0 ;Nguong tran 500 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 500 ms
wrt_loop1: ;Vong lap nay xuat dong ky hieu ra dong 1 LCD
mov.b [W4++], W0 ;Doc mot ky tu
cp0.b W0 ;Da het chuoi chua?
bra z, sw_stat ;Da het chuoi, vay khoi tao trang thai switch
rcall LCD_dat4 ;Xuat ky tu trong W0 ra LCD
mov #(ms_count*1), W0 ;Nguong tran 1 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 1 ms
bra wrt_loop1 ;Chuyen sang ky tu ke tiep
sw_stat:
Người báo cáo: Nguyễn Quang Nam Tài liệu: TUT04.01
Ngày: 8/3/2006 Trang: 12/15
mov SW_DAT, W0 ;Doc trang thai cua cac switch
and #0x001F, W0 ;Xoa 11 bit cao nhat
mov W0, sw_old ;va ghi vao bien luu trang thai
main_loop:
mov #LCD_homeL2, W0 ;Chuyen den dau dong thu hai
rcall LCD_cmd4
mov #(ms_count*1), W0 ;Nguong tran 1 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 1 ms
mov sw_old, W3
mov #5, W5 ;So switch can cap nhat trang thai
updat_loop:
mov.b #'0', W0 ;Gia su muc '0'
btsc W3, #0 ;Kiem tra bit thap nhat
mov.b #'1', W0 ;Dang la muc '1', dat lai ky tu can xuat
rcall LCD_dat4 ;Xuat ky tu trong W0 ra LCD
mov #(ms_count*1), W0 ;Nguong tran 1 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 1 ms
mov.b #' ', W0 ;Them mot khoang trang
rcall LCD_dat4 ;Xuat ky tu trong W0 ra LCD
mov #(ms_count*1), W0 ;Nguong tran 1 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 1 ms
mov.b #' ', W0 ;Them mot khoang trang nua
rcall LCD_dat4 ;Xuat ky tu trong W0 ra LCD
mov #(ms_count*1), W0 ;Nguong tran 1 ms cho timer 1
rcall Delay_ms ;Yeu cau cho 1 ms
lsr W3, W3 ;Dich phai 1 bit (doc switch ke tiep)
dec W5, W5 ;Giam so switch can cap nhat di 1
bra nz, updat_loop ;Cap nhat tiep neu chua het
sw_chg:
mov SW_DAT, W0 ;Doc trang thai cua cac switch
and #0x001F, W0 ;Xoa 11 bit cao nhat
1 cp sw_old ;Neu khong thay doi
bra z, sw_chg ;thi kiem tra tiep
update_LCD: ;Co thay doi, cap nhat LCD
mov W0, sw_old ;Luu trang thai moi cua cac switch
bra main_loop ;va cap nhat cac switch
;-------------------------------------------------------------------------------
Người báo cáo: Nguyễn Quang Nam Tài liệu: TUT04.01
Ngày: 8/3/2006 Trang: 13/15
. . .
;Chuong trinh con khoi tao cac cong I/O, de noi voi LCD, va cac switch
;-------------------------------------------------------------------------------
Init_PORTS:
mov LCD_DAT, W0
and.b #0xF0, W0
mov W0, LCD_DAT ;Xoa cac bit chot du lieu LCD
mov LCD_TRIS, W0
and.b #0xF0, W0
mov W0, LCD_TRIS ;Cac chan du lieu LCD la ngo ra
bset LATF, #LCD_BL
bclr TRISF, #LCD_BL ;RF3 la ngo ra, noi vao back light LED
bclr LATE, #LCD_EN
bclr TRISE, #LCD_EN ;RE8 la ngo ra, noi vao Enable cua LCD
bclr LATD, #LCD_RW
bclr TRISD, #LCD_RW ;RD0 la ngo ra, noi vao R/W cua LCD
bclr LATD, #LCD_RS
bclr TRISD, #LCD_RS ;RD1 la ngo ra, noi vao Reset cua LCD
2 setm ADPCFG ;RB0..RB4 la cac chan digital
mov #0x001F, W0
mov W0, SW_TRIS ;Cac chan du lieu RB0..RB4 la ngo vao
return
;-------------------------------------------------------------------------------
Hoạt động của chương trình có thể giải thích vắn tắt như sau. Sau khi thực hiện các
khởi tạo cho các cổng vào/ra, bộ định thời Timer 1, và LCD, chương trình sẽ xuất một
dòng ký hiệu ‘S1 S2 S3 S4 S5’ ra dòng 1 của LCD. Tiếp đến, chương trình đọc trạng
thái ban đầu của các công tắc và đi vào vòng lặp chính. Vòng lặp chính sẽ xuất thông tin
về trạng thái các công tắc ra dòng 2 của LCD, sau đó kiểm tra xem có sự thay đổi trạng
thái của các công tắc hay không, và chỉ thực hiện cập nhật trạng thái của các công tắc
khi có sự thay đổi kể từ lần cập nhật trước.
Cần lưu ý là lệnh đọc trạng thái các công tắc sẽ đọc từ port B chứ không phải đọc từ
latch B. Do hoạt động read-modify-write của một số lệnh, các thanh ghi LATx được
dùng để khắc phục tình trạng các thanh ghi chốt trạng thái cổng bị ghi giá trị của chân
ngõ vào. Như vậy, việc ghi vào PORTx và LATx sẽ có cùng tác dụng, đó là ghi vào
thanh ghi chốt trạng thái cổng. Việc đọc thanh ghi PORTx sẽ đọc giá trị của chân ngõ
vào trong khi việc đọc thanh ghi LATx sẽ đọc giá trị được lưu giữ ở thanh ghi chốt
trạng thái cổng.
Người báo cáo: Nguyễn Quang Nam Tài liệu: TUT04.01
Ngày: 8/3/2006 Trang: 14/15
Trong ví dụ này có 2 lệnh mới được dùng, cp và setm. Lệnh cp dùng để so sánh
giữa hai giá trị, một trong hai giá trị đó phải được lưu trong một thanh ghi làm việc Wn,
đặc biệt là phải được lưu trong thanh ghi WREG (W0) nếu toán hạng thứ hai là một
thanh ghi (ô nhớ) bình thường nằm trong 8192 địa chỉ RAM đầu tiên. Toán hạng thứ hai
có thể là một toán hạng tức thời (có độ lớn 5-bit) hay một thanh ghi làm việc khác.
Lệnh setm thực hiện thao tác ngược lại với lệnh clear. Lệnh setm được dùng để
bật (đặt bằng 1) tất cả các bit của một thanh ghi làm việc hay một thanh ghi bình thường
nằm trong 8192 địa chỉ RAM đầu tiên.
3.2. Ví dụ 3-3
Bạn hãy loại bỏ tập tin “Vidu3-2.s” khỏi project, và thêm vào project tập tin
“Vidu3-3.s”. Ví dụ này chỉ khác ví dụ 3-2 ở điểm là cờ bận của LCD được kiểm tra
trong ví dụ này thay vì dùng một khoảng thời gian chờ như trong ví dụ 3-2. Khi thực
hiện việc kiểm tra cờ bận, các chân giao tiếp dữ liệu với LCD cần được đổi chiều truyền
thông tin, do vậy chúng ta cần chú ý trong việc thiết lập các bit TRIS (điều khiển chiều
dữ liệu) cho các chân dữ liệu này. Để cho gọn, tôi chỉ liệt kê phần mã của chương trình
con kiểm tra trạng thái cờ bận ở đây.
Trích mã nguồn “Vidu3-3.s”:
;Chuong trinh con poll bit trang thai BF cua LCD
;Se huy noi dung cua W0, W1, W2
;-------------------------------------------------------------------------------
LCD_BFpoll:
mov LCD_TRIS, W2
ior.b #0x0F, W2
mov W2, LCD_TRIS ;Cac chan du lieu LCD la ngo vao
bset LATD, #LCD_RW
bclr LATD, #LCD_RS ;Dat che do doc du lieu
DelayNTcy 8
is_busy:
bset LATE, #LCD_EN ;Tao xung Enable
DelayNTcy 4
mov LCD_PORT, W1 ;Doc nibble cao (RE3..RE0 = D7..D4)
DelayNTcy 4
bclr LATE, #LCD_EN ;keo dai toi thieu 4.5 us
DelayNTcy 8
bset LATE, #LCD_EN ;Tao xung Enable
DelayNTcy 8
bclr LATE, #LCD_EN ;keo dai toi thieu 4.5 us
DelayNTcy 4
Người báo cáo: Nguyễn Quang Nam Tài liệu: TUT04.01
Ngày: 8/3/2006 Trang: 15/15
btsc W1, #3 ;Con ban hay khong?
bra is_busy ;Con, vay tiep tuc cho
mov LATE, W0
and.b #0xF0, W0
mov W0, LATE
mov LCD_TRIS, W2
and.b #0xF0, W2
mov W2, LCD_TRIS ;Cac chan du lieu LCD la ngo ra
return ;Het ban, vay tro ve chuong trinh goi
;-------------------------------------------------------------------------------
Chương trình con này khá trực quan, ngoại trừ điểm cần chú ý là chúng ta nên đặt
trạng thái của thanh ghi LAT trước rồi mới đổi chiều các chân I/O từ ngõ vào thành ngõ
ra. Điều này sẽ giúp chúng ta tránh được các gai điện áp (glitch) có thể xuất hiện tại các
chân I/O khi đổi chiều dữ liệu.
4. Tóm tắt
Qua tutorial này, một số lệnh mới đã được giới thiệu, cùng với kỹ thuật đọc các ngõ
vào. Một số chương trình con cơ bản dùng cho giao tiếp LCD đã được cung cấp, và bạn
có thể sử dụng chúng như một tập hợp nhỏ các hàm thực hiện giao tiếp LCD trong
chương trình của bạn. Hai kỹ thuật mới: macro và định thời dùng ngắt tối thiểu cũng
đã được trình bày. Mong rằng bạn đã hiểu thêm đôi chút về phần vi điều khiển của các
dsPIC, từ đó tiến gần hơn đến việc làm chủ dòng chip rất nhiều tiềm năng này.
Chúc bạn thành công!
Các file đính kèm theo tài liệu này:
- 04_01_giao_tiep_voi_cong_tac_valcd_9588.pdf