How to control LCD with PIC 16F84A
LCD là viềt tắt của Liquid Crystal Display mà bà con ta hay gọi là màn hình tinh thể lỏng
.LCD được dùng trong rất nhiều ứng dụng không chỉ vì khả năng hiển thị số,chữ cái và còn những
biểu tượng khác làm chúng trở nên linh hoạt hơn.Trong bài này tôi xin giới thiệu với các bạn 1 loại
LCD khá phổ biến ở Việt Nam đó là TC1602A do Trung Quốc sản xuất . Các bạn có thể mua chúng ở
chợ Nhật Tảo (Tp HCM) hoặc Hàng Trống (Hà Nội) với giá khoảng 140.000đ / cái.Lưu ý khi mua về
bạn nên hàn LCD vào các chân ghim (như hình dưới ) để bạn dễ dàng ghim LCD vào bảng mạch.
7 trang |
Chia sẻ: hoang10 | Lượt xem: 555 | Lượt tải: 0
Bạn đang xem nội dung tài liệu Điện - Điện Tử - How to control LCD with PIC 16F84A, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
How to control LCD with PIC 16F84A
LCD là viềt tắt của Liquid Crystal Display mà bà con ta hay gọi là màn hình tinh thể lỏng
.LCD được dùng trong rất nhiều ứng dụng không chỉ vì khả năng hiển thị số,chữ cái và còn những
biểu tượng khác làm chúng trở nên linh hoạt hơn.Trong bài này tôi xin giới thiệu với các bạn 1 loại
LCD khá phổ biến ở Việt Nam đó là TC1602A do Trung Quốc sản xuất . Các bạn có thể mua chúng ở
chợ Nhật Tảo (Tp HCM) hoặc Hàng Trống (Hà Nội) với giá khoảng 140.000đ / cái.Lưu ý khi mua về
bạn nên hàn LCD vào các chân ghim (như hình dưới ) để bạn dễ dàng ghim LCD vào bảng mạch.
TC1602A thể hiện được tối đa 16x2 kí tự ,nó có tất cà 16 chân, trong đó 3 chân (1,2,3) được
nối với nguồn,3 chân (4,5,6) là các chân điều khiển,8 chân (7-14) dùng xuất nhập dữ liệu, 2 chân
(15,16) cũng được nối với nguồn để LCD phát sáng.Bảng dưới đây giới thiệu chức năng các chân của
TC1602A
Chân Kí hiệu Mức Logic I/O Chức năng
1 Vss - - Nguồn (GND)
2 Vcc - - Nguồn (+5V)
3 Vee - - Chỉnh độ tương phản
4 RS 0/1 I 0 = Nhập lệnh 1 = Nhập dữ liệu
5 R/W 0/1 I 0 = Ghi dữ liệu 1 = Đọc dữ liệu
6 E 1, 1->0 I Tín hiệu cho phép
7 DB0 0/1 I/O Bus dữ liệu 0
8 DB1 0/1 I/O Bus dữ liệu 1
9 DB2 0/1 I/O Bus dữ liệu 2
10 DB3 0/1 I/O Bus dữ liệu 3
11 DB4 0/1 I/O Bus dữ liệu 4
12 DB5 0/1 I/O Bus dữ liệu 5
13 DB6 0/1 I/O Bus dữ liệu 6
14 DB7 0/1 I/O Bus dữ liệu 7
15 Lamp- - - Đèn LCD
16 Lamp+ - - Đèn LCD
E (Enable) : cho phép ta truy cập/xuất đến LCD thông qua chân RS và R/W.Khi chân E ở mức
cao (1) LCD sẽ kiểm tra trạng thái của 2 chân RS và R/W và đáp ứng cho phù hợp.Còn khi chân E ở
mức thấp (0),LCD sẽ bị vô hiệu hoá hoặc bỏ qua tính hiệu của 2 chân RS và R/W.
R/W (Read/Write) : dùng để xác định hướng của dữ liệu được truyền giữa LCD và vi điều
khiển .Khi nó ở mức thấp dữ liệu được ghi đến LCD và khi ở mức cao, dữ liệu được đọc từ LCD.
RS ( Register select) : khi ở mức thấp, chỉ thị được truyền đến LCD như xoá màn hình ,vị trí
con trỏ .Khi ở mức cao, kí tự được truyền đến LCD
Trước khi truyền các kí tự ra màn hình LCD ta cần thiết lập cho LCD như chọn chế độ 4 bit
hoặc 8 bit, 1 dòng hay 2 dòng ,bật/tắt con trỏ,..Dưới đây là bảng tập lệnh của LCD
Mã nhị phân
Tập lệnh
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
Mô tả
Thời
gian
thực thi
Xoá hiển
thị 0 0 0 0 0 0 0 0 0 1
Xoá hiện thị và đưa con trỏ về vị
trí ban đầu (địa chỉ 0). 1.64mS
Con trỏ
ban đầu 0 0 0 0 0 0 0 0 1 *
Trả con trỏ vầ vị trí ban đầu (địa
chỉ 0). Ngoài ra đưa hiển thị đã
bị dịch chuyển về vị trí ban đầu.
Nội dung bộ nhớ hiển thị dữ
liệu(DDRAM) không thay đổi.
1.64mS
Thiết lập
chế độ 0 0 0 0 0 0 0 1 I/D S
Thiết lập hướng di chuyển của
con trỏ
tăng/giảm(I/D=0:giảm,ID=1:tăng)
, chỉ rõ dịch chuyển hiển thị
(S=0:không dịch chuyển hiển
thị,S=0 dịch chuyển hiển thị).
Hoạt động này được thực hiện
trong suốt quá trình đọc/ghi dữ
liệu
40uS
Điều
khiển
hiển thị
0 0 0 0 0 0 1 D C B
Bật/tắt hiển thị (D=0:tắt,D=1,bật)
nhưng dữ liệu vẫn lưu trong
DDRAM, bật/tắt con
trỏ(C=0:tắt,C=1:bật) và bật tắt
con trỏ nhấp nháy tại vị trí của kí
tự (B=0:tắt,B=1:bật).
40uS
Dịch
chuyển
con
trỏ/hiển
thị
0 0 0 0 0 1 S/C R/L * *
Dịch chuyển con trỏ/hiển thị qua
trái /phải mà không phải đọc/ghi
lại dữ liệu (S/C=0:di chuyển con
trỏ,S/C=1:di chuyển hiển thị),
(R/L=0:dịch trái,R/L=1:dịch
phải). nội dung DDRAM không
thay đổi.
40uS
Thiết lập
chức
năng
0 0 0 0 1 DL N F * *
Khởi tạo giao diện của độ dài dữ
liệu (DL=0:độ dài 4 bit,DL=1:8
bit), số hàng hiển thị(N=0:1 hàng
,N=1 :2 hàng) và phông
chữ(F=0:5x7,F=1:5x10).
40uS
Thiết lập
địa chỉ
CGRAM
0 0 0 1 Địa chỉ CGRAM
Thiết lập địa chỉ bộ nhớ tạo kí tự
(CGRAM.),dữ liệu được gửi/nhận
sau thiết lập này
40uS
Mã nhị phân
Tập lệnh
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
Mô tả
Thời
gian
thực thi
Thiết lập
địa chỉ
DDRAM
0 0 1 Địa chỉ DDRAM
Thiết lập địa chỉ bộ nhớ tạo kí tự
(DDRAM.),dữ liệu được
gửi/nhận sau thiết lập này
40uS
Đọc cờ
bận 0 1 BF Địa chỉ CGRAM / DDRAM
Đọc cờ bận Busy-flag (BF),kiểm
tra xem hệ thống có đang thực thi
1 lệnh đã được nhận trước đó
không.(BF=1:hệ thống đang thực
hiện tác vụ bên trong,khi BF=0
thì lệnh tiếp theo mới được thực
thi)
0uS
Ghi dữ
liệu đến
CGRAM/
DDRAM.
1 0 Ghi dữ liệu Ghi dữ liệu đến CGRAM/ DDRAM. 40uS
Đọc dữ
liệu từ
CGRAM/
DDRAM.
1 1 Đọc dữ liệu Đọc dữ liệu từ CGRAM/ DDRAM. 40uS
Trong bài này tôi sẽ hướng dẫn các bạn điều khiển LCD qua vi điều khiển PIC 16F84A.Bạn có
thể ráp mạch theo sơ đồ sau:
Tôi sử dụng 4 bit đầu của PORTA (RA0-RA3) làm đường truyền dữ liệu, 3 bit (RB1-RB3) của
PORTB là đường điều khiển,còn lại 4 bit cuối PORTB (RB4-RB7) được nối với 4 nút nhấn.Yêu cầu
của chương trình như sau: khi nhấn 1 trong 4 nút thì sẽ có dòng chữ hiện ra trên 2 hàng của LCD
Sourse code:
..
..
Phân tích Sourse code:
Đầu tiên ta phải khai báo các biến dùng trong chương trình như count,count1,..Sau đó chỉ
định địa chỉ cho chương trình chính (địa chỉ 0x0000) và chương trình ngắt (0x0004).Trong chương
trình chính ta thiết lập các Port cần dùng,cũng như thiết lập chế độ ngắt cần sử dụng,trong chương
trình tôi dùng ngắt ở PORTB (RB4-RB7),sau đó gọi chương trình khởi tạo LCD (LCD_Init).Trong
chuơng trình này bạn thiết lập cho LCD như dùng chế độ truyền 4 bit,và các chức năng khác như bật
tắt con trỏ,hiển thị 1 hàng hay 2 hàng,...Sau đó chương trình sẽ chờ trong vòng lặp cho tới khi ngắt xảy
ra để thực hiện việc truyền dữ liệu ra LCD.
Thế ngắt là gì ? Giả sử bạn đang ngồi làm việc tại nhà trên máy tính thì bất chợt điện thoại của
bạn reo lên và bạn buộc phải tạm ngưng công việc và nhấc điện thoại để trả lời cuộc gọi.,sau khi trả lời
điện thoại xong bạn tiếp tục vào máy tính để làm việc.Hành động trong ví dụ trên cũng giống như hoạt
động của vi điều khiển.Bạn có thể hiểu nôm na là chương trình chính của bạn là hành động bạn đang
làm việc và khi điện thoại reo buộc bạn hoãn lại và chương trình ngắt là hành động bạn trả lời điện
thoại.
PIC 16F84A có 4 nguồn ngắt gồm 2 ngắt ngoài và 2 ngắt trong. Ngắt trong tôi sẽ đề cập trong
những bài viết sau.Nếu bạn để ý khi nhìn vào sơ đồ chân của 16F84A bạn thấy chân số 6 là
RB0/INT,đó là dấu hiệu của ngắt ngoài,ngoài ra bit 4 đến bit 7 của PORTB cũng được dùng làm
ngắt.Trước khi bạn muốn dùng ngắt bạn phải làm 1 số công việc sau đây.Đầu tiên bạn phải báo cho
VĐK là bạn sắp sử dụng ngắt,sau đó bạn kích hoạt ngắt mà mình muốn dùng.Trong PIC có 1 thanh
ghi 8 bit tên là INTCON.Bạn có thể xem datasheet đề biết cụ thề chức năng của từng bit.Ví dụ để sử
dụng ngắt RB0/INT bạn phải set bit 4 và bit 7 của INTCON lên 1.Tuy để vào được chương trình ngắt
cờ ngắt tương ứng phải được set 1.Trong chương trình ngắt bạn phải tự xoá cờ ngắt để có thể chờ
những ngắt sau này.Lưu ý khi vào chương trình ngắt ta phải lưu lại các giá trị của các thanh ghi W
,STATUS ,FSR ,PCLATH vì sau khi thực hiện xong chuơng trình ngắt ,nội dung của các thanh ghi
này bị thay đổi làm chương trình hoạt động không như mong muốn khi thoát khỏi chương trình ngắt
.Tất nhiên có vay phải thì phải trả,trước khi thoát khỏi ngắt bạn trả lại giá trị đã lưu vào W ,STATUS
,FSR ,PCLATH .Trong chương trình ngắt,vì ta dùng ngắt PORTB (ngắt sẽ xảy ra khi trạng thái của 1
trong 4 bit RB4,RB5,RB6,RB7 thay đổi) nên phải kiểm tra xem chân nào tạo ra ngắt bằng cách kiểm
ta xem bit nào được đưa xuống mức 0.Bình thường RB4-RB7 được kéo lên mức cao (bằng 4 điện trở
4K7).Khi 1 trong 4 chân trên thay đổi trạng thái thì chương trình sẽ gọi ngắt tương ứng với trạng thái
thay đổi đó.Cụ thề khi RB7 xuống mức 0 ,Interrup1 sẽ được gọi,chương trình se gửi các kí tự ra LCD
bằng cách đọc các kí tự từ bảng Text ra.Bảng là nơi lưu lại danh sách các giá trị
Interupt1
clrf count ;count=0
Message1
movf count, w ;w=count
call Text1 ;lay ki tu tu bang text1
xorlw 0x00 ;kiem tra xem da qua ki tu cuoi cung chua
btfsc STATUS, Z
goto NextMessage1 ;neu den roi thi xuong hang thu 2
call SEND_CHAR ;neu chua ,dua ki tu nay ra LCD
call Delay100 ;tri hoan 100ms
incf count, f ;count=count+1
goto Message1
NextMessage1 ..
..
Text1 addwf PCL, f
retlw 'H'
retlw 'u'
retlw 'o'
retlw 'n'
retlw 'g'
retlw ' '
retlw 'd'
retlw 'a'
retlw 'n'
retlw 0x00
Hàng đầu tiên của chương trình con là “addwf PCL, f” nó sẽ cộng giá trị của thanh ghi W với
PCL rồi lưu giá trị lại thanh ghi PCL.PCL là bộ đếm chương trình (Program Counter),nó lưu lại vị trí
bộ nhớ nơi mà lệnh được thực thi.Vì thế khi cộng thêm giá trị của W (W=0) vào PCL,nó sẽ di chuyển
xuống hàng tiếp theo và thực hiện lệnh “ retlw 'H' ” tức là nó sẽ trở lại chương trình nơi nó được gọi
và trả giá trị này cho W,cụ thể giá trị này là kí tự ASCII “ H “ .Chương trình cứ tiếp tục lấy giá trị tiếp
theo “u”, “o”,Cuối bảng Text có lệnh retlw “0x00” để ra dấu giới hạn của bảng,bằng cách kiểm tra
cờ Z ta có thể biết được đâu là giới hạn của bảng.Sau khi lấy giá trị của bảng , chương trình sẽ gửi ra
LCD cho nó hiển thị
Một điều cần lưu ý là khi chương trình của bạn dài và bạn có sử dụng bảng ,thì bạn phải đặt
chúng ở đầu chương trình để chúng không vượt qua địa chỉ giới hạn là 256 byte.
Để gửi các kí tự hay lệnh nào đó ra LCD ta phải viết chương trình con như SEND_CMD và
SEND_CHAR
SEND_CMD
movwf LCD_temp1 ;LCD_temp1=w
swapf LCD_temp1,w ;w=swapf(LCD_temp1)
andlw 0x0f ;w=0000xxxx
movwf LCD_DATA ;gui ra LCD
bcf PORTB, LCD_RS ;RS dua xuong 0->che do truyen lenh
call Pulse_e ;tao 1 xung xuong o chan E de LCD thuc hien lenh tren
movf LCD_temp1,w ;w=LCD_temp1
andlw 0x0f ;w=0000xxxx
movwf LCD_DATA ;gui ra LCD
bcf PORTB, LCD_RS ;RS dua xuong 0->che do truyen lenh
call Pulse_e ;Chot chan E de thuc hien lenh tren
call LCD_Busy ;Doi LCD thuc hien xong lenh tren
retlw 0x00
Do ta chọn chế độ truyền 4 bit nên ta phải chia giá trị cần gửi ra LCD thành 2 nibble cao và
thấp rồi lần lượt gửi ra LCD,nếu dữ liệu truyền ra LCD là lệnh (xoá màn hình ,bật/tắt con trỏ,..)thì phải
đưa chân RS xuống 0,ngược lại nếu đưa kí tự (A,B,C,) ra LCD thì ta phải cho RS=1.Tuy nhiên khi
ta đưa dữ liệu ra LCD (movwf LCD_DATA) thì LCD chưa thực hiện lệnh trên cho tới khi ta làm 1
động tác mà tôi tạm gọi là “phất cờ “ bằng cách đưa chân E lên mức cao trong 1 chu kì rồi lại đưa E
xuống mức thấp (call Pulse_e ) thì LCD sẽ thi hành lệnh trên.
Một điều cần chú ý nữa là khi thực thi LCD cần 1 thời gian để hoàn thành các lệnh .Trong
khoảng thời gian đó bạn không thể bắt LCD thực hiện các kệnh tiếp theo cho tới khi nó hoàn thành các
lệnh trước đó.Thời gian thực thi phụ thuôc vào lệnh được truyền đi và tần số thạch anh của LCD. Cách
giải quyết vấn đề này là kiểm tra cờ Busy của LCD nằm ở bus dữ liệu 7 ,nếu cờ Busy được kéo lên 1
tức là LCD đang bận,còn ngược laị thì LCD không còn bận nữa,ta có thể tiếp tục truyền dữ liệu sang
LCD.Nhược điểm của cách kiểm tra này là khi LCD bị kẹt (vì lý do nào đó) thì chương trình nắm mãi
ở vòng lặp kiểm tra cờ Busy.Một cách đơn giản hơn là ta làm trễ 1 thời gian phù hợp để chờ LCD
bằng cách dùng hàm Delay.Phương thức này cũng hạn chế là khi tần số thạch anh thay đổi,hay dùng
một LCD khác chương trình của ta cũng phải thay đổi theo cho phù hợp.
LCD_Busy
bsf STATUS,RP0 ;chon bank 1
movlw 0x0f ;RA0:RA3 la chan nhap
movwf LCD_TRIS
bcf STATUS,RP0 ;chon bank 0
bcf PORTB, LCD_RS ;che do nhap lenh
bsf PORTB, LCD_RW ;cho phep doc du lieu tu LCD
bsf PORTB, LCD_E ;E len muc 1
swapf LCD_DATA, w ;doc 4 bit cao ( trong do co bit kiem tra co Busy)
bcf PORTB, LCD_E ;E xuong 1
movwf LCD_temp2 ;luu 4 bit cao vao LCD_temp2
bsf PORTB, LCD_E
bcf PORTB, LCD_E ;khong can doc 4 bit thap,vi co Busy o 4 bit cao
btfsc LCD_temp2, 7 ;kiem tra xem LCD co ban khong
goto LCD_Busy ;neu ban thi kiem tra cho toi khi het ban
bcf PORTB, LCD_RW
bsf STATUS,RP0 ;chon bank 1
movlw 0x00 ;RA0:RA3 la chan xuat
movwf LCD_TRIS
bcf STATUS,RP0 ;tro lai bank 0
return
Để đọc được cờ Busy ta phải khởi tạo lại PORTA là port nhập liệu.Do cờ busy nằm ở DB7 nên
ta chỉ cần kiểm tra nibble cao.