Điện - Điện Tử - How to control LCD with PIC 16F84A

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.

pdf7 trang | Chia sẻ: hoang10 | Lượt xem: 555 | Lượt tải: 0download
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.