Tải bản đầy đủ (.pdf) (15 trang)

Báo cáo: Chương trình hợp ngữ giao tiếp nút nhấn/công tắc và LCD với dsPIC

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (124.72 KB, 15 trang )

Người báo cáo:

Nguyễn Quang Nam

Tài liệu:

Ngày:

8/3/2006

Trang:

TUT04.01
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ả
Font Palatino Linotype:

Biểu thị

In nghiêng

Tài liệu tham khảo

Viết hoa chữ đầu

Một menu, hộp thoại
Tên riêng (của tập tin,
project, …)

Đặt trong dấu nháy kép

Ví dụ
dsPIC30F/33F
Programmer’s Reference
Manual
Chọn Project Wizard

“Vidu3”

Font Courier:
Courier thường

Mã nguồn
Tên tập tin

mov #0x8010, W0
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:

Ngày:

8/3/2006

Trang:

TUT04.01
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.
LCD1

RE0
RE1
RE2
RE3

D0
D1
D2
D3
D4
D5
D6
D7
7
8
9
10
11
12
13
14

1

2
3

5k

4
5
6

RV1

RD1
RD0
RE8

VSS
VDD
VEE

Vdd

RS
RW
E

LM016L

RE[0..3]

R1


33k

U1
9
10
1
7
6
5
4
3
2
1

X1

8MHz

SW1

C2

C1
33pF

2
3
4
5

6
7

RD0 15
RD1 14
1

8
7
6
5
4
3
2

11
12

RB[0..4]

RB4
RB3
RB2
RB1
RB0

RB4
RB3
RB2
RB1

RB0

8
9
10
11
12
13
14

33pF

RB0
RB1
RB2
RB3
RB4

CLKIN/OSC1
RC15/CLKO/OSC2
MCLR

RE0/PWM1L
RE1/PWM1H
RE2/PWM2L
RE3/PWM2H
RE4/PWM3L
RE5/PWM3H
FLT A/INT 0/RE8


RB0/CN2/VREF+/AN0/EMUD3
RB1/CN3/VREF-/AN1/EMUC3
RB2/CN4/SS1/AN2
RB3/CN5/INDX/AN3
RB4/CN6/IC7/QEA/AN4
RB5/CN7/IC8/QEB/AN5
RF2/SDA/SDI1/U1RX/EMUC/PGC
RF3/SCL/SDO1/U1T X/EMUD/PGD
RC13/CN1/U1AT X/T2CK/SOSCI/EMUD
RC14/CN0/U1ARX/T1CK/SOSCO/EMUC
EMUC2/OC1/IC1/INT1/RD0
EMUD2/OC2/IC2/INT2/RD1

AVDD
AVSS

26
25
24
23
22
21
16

RE0
RE1
RE2
RE3

RE8


18
17
Vdd

28
27

DSPIC30F4012DIP

RP1
10k

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

config

__FWDT, WDT_OFF

config

__FBORPOR, MCLR_EN & PBOR_OFF

config

__FGS, CODE_PROT_OFF

;Clock = 32 MHz


Người báo cáo:

Nguyễn Quang Nam

Tài liệu:

Ngày:

8/3/2006

Trang:

TUT04.01

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

time_out: .space

;Chinh dia chi theo boi so cua 2
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:

Ngày:


8/3/2006

Trang:

.macro

DelayNTcy

1 repeat

#(\n-1)

n

TUT04.01
4/15

;Macro tao tre n chu ky lenh, n > 2

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

mov.b

[W4++], W0

;Doc mot ky tu

cp0.b


W0

;Da het chuoi chua?

wrt_loop1:

3

bra z, homeL2

;Da het chuoi, vay nhay den lenh chuyen dong

rcall

;Chua het chuoi, xuat ky tu trong W0 ra LCD

LCD_dat4

mov #(ms_count*1), W0

;Nguong tran 1 ms cho timer 1

rcall

;Yeu cau cho 1 ms

Delay_ms


Người báo cáo:


Nguyễn Quang Nam

Tài liệu:

Ngày:

8/3/2006

Trang:

bra wrt_loop1

TUT04.01
5/15

;Chuyen sang ky tu ke tiep

homeL2:
mov #LCD_homeL2, W0
rcall

;Chuyen den dau dong thu hai

LCD_cmd4

mov #(ms_count*1), W0

;Nguong tran 1 ms cho timer 1


rcall

;Yeu cau cho 1 ms

Delay_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

;Xuat ky tu trong W0 ra LCD


LCD_dat4

mov #(ms_count*1), W0

;Nguong tran 1 ms cho timer 1

rcall

;Yeu cau cho 1 ms

Delay_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:

Ngày:

8/3/2006

Trang:

TUT04.01
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
rcall

;Dat che do giao tiep 4-bit, man hinh 2 dong

LCD_cmd4

mov #(ms_count*1), W0

;Nguong tran 1 ms cho timer 1

rcall

;Yeu cau cho 1 ms


Delay_ms

mov #LCD_off, W0
rcall

;Tat man hinh

LCD_cmd4

mov #(ms_count*1), W0

;Nguong tran 1 ms cho timer 1

rcall

;Yeu cau cho 1 ms

Delay_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:


Ngày:

8/3/2006

Trang:

rcall

TUT04.01
7/15

LCD_cmd4

mov #(ms_count*1), W0

;Nguong tran 1 ms cho timer 1

rcall

;Yeu cau cho 1 ms

Delay_ms

mov #LCD_on_blink, W0
rcall

;Bat man hinh, hien con tro nhap nhay

LCD_cmd4


mov #(ms_count*1), W0

;Nguong tran 1 ms cho timer 1

rcall

;Yeu cau cho 1 ms

Delay_ms

mov #LCD_clear, W0
rcall

;Xoa man hinh

LCD_cmd4

mov #(ms_count*5), W0

;Nguong tran 5 ms cho timer 1

rcall

;Yeu cau cho 5 ms

Delay_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

5

6

7

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

;Xoa 4 bit thap nhat cua LCD_DAT

#0xF0, W1

mov W0, W2

;Giu lai lenh 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 lenh 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

;Xoa 4 bit thap nhat cua LCD_DAT

#0xF0, W1

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:

Ngày:

8/3/2006

Trang:

TUT04.01

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

;Xoa 4 bit thap nhat cua LCD_DAT

#0xF0, W1

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

;Xoa 4 bit thap nhat cua LCD_DAT

#0xF0, W1

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:
bclr

;Ten nay da duoc dinh truoc trong tap tin lien ket
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:

Ngày:

8/3/2006

Trang:

TUT04.01
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à n1 nếu cần lặp lại n lần lệnh kế tiếp. Để đảm bảo thứ tự tính tố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 tố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 tố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:

Ngày:

8/3/2006

Trang:

TUT04.01
10/15

nhỏ trong tổng thời gian thực thi của tồ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 µs

- 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
rcall

;Ghi 0x33 lan thu nhat

LCD_cmd4

mov #(ms_count*5), W0

;Nguong tran 5 ms cho timer 1

rcall

;Yeu cau cho 5 ms

Delay_ms

mov #0x33, W0
rcall

;Ghi 0x33 lan thu hai


LCD_cmd4

mov #13, W0

;Nguong tran 100 us cho timer 1

rcall

;Yeu cau cho 100 us

Delay_ms

mov #0x33, W0
rcall

;Ghi 0x33 lan thu ba

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
ngồ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 q 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:

Ngày:

8/3/2006

Trang:

TUT04.01
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

;Yeu cau cho 500 ms

Delay_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

;Xuat ky tu trong W0 ra LCD

LCD_dat4

mov #(ms_count*1), W0

;Nguong tran 1 ms cho timer 1

rcall

;Yeu cau cho 1 ms

Delay_ms

bra wrt_loop1

sw_stat:

;Chuyen sang ky tu ke tiep



Người báo cáo:

Nguyễn Quang Nam

Tài liệu:

Ngày:

8/3/2006

Trang:

TUT04.01
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
rcall


;Chuyen den dau dong thu hai

LCD_cmd4

mov #(ms_count*1), W0

;Nguong tran 1 ms cho timer 1

rcall

;Yeu cau cho 1 ms

Delay_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

;Yeu cau cho 1 ms

Delay_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:

1

mov SW_DAT, W0

;Doc trang thai cua cac switch

and #0x001F, W0

;Xoa 11 bit cao nhat


cp

;Neu khong thay doi

sw_old

bra z, sw_chg

update_LCD:

;thi kiem tra tiep

;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:

Ngày:

8/3/2006

Trang:

TUT04.01
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


2

;Cac chan du lieu LCD la ngo ra

bset

LATF, #LCD_BL

bclr

TRISF, #LCD_BL

bclr

LATE, #LCD_EN

bclr

TRISE, #LCD_EN

bclr

LATD, #LCD_RW

bclr

TRISD, #LCD_RW

bclr


LATD, #LCD_RS

bclr

TRISD, #LCD_RS

;RD1 la ngo ra, noi vao Reset cua LCD

setm

ADPCFG

;RB0..RB4 la cac chan digital

;RF3 la ngo ra, noi vao back light LED

;RE8 la ngo ra, noi vao Enable cua LCD

;RD0 la ngo ra, noi vao R/W cua LCD

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:

Ngày:

8/3/2006

Trang:

TUT04.01
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. Tốn hạng thứ hai
có thể là một tố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
DelayNTcy

;Dat che do doc du lieu

8

is_busy:
bset LATE, #LCD_EN
DelayNTcy
mov

;Tao xung Enable

4

LCD_PORT, W1 ;Doc nibble cao (RE3..RE0 = D7..D4)

DelayNTcy

4

bclr LATE, #LCD_EN
DelayNTcy

8


bset LATE, #LCD_EN
DelayNTcy

;Tao xung Enable

8

bclr LATE, #LCD_EN
DelayNTcy

;keo dai toi thieu 4.5 us

4

;keo dai toi thieu 4.5 us


Người báo cáo:

Nguyễn Quang Nam

Tài liệu:

Ngày:

8/3/2006

Trang:


btsc W1, #3

;Con ban hay khong?

bra is_busy

;Con, vay tiep tuc cho

TUT04.01
15/15

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!



×