Giới thiệu
Hôm nay mình sẽ hướng dẫn các bạn tìm hiểu và vọc vạch cái màn hình LCD NOKIA 5110. Chúng ta sẽ khám phá và “bung lụa” cái màn hình này luôn nhé 😛
Màn này có tất cả 84×48 điểm ảnh. Được điều khiển bới Chíp driver PD84544 thông qua giao thức SPI chế độ 0. Có 8 chân giao tiếp được mô tả như sau:
- RST : Chân reset LCD
- CE: Chân cho phép hoặc không cho phép LCD hoạt động ( 1 số màn ghi là CSE hoặc SE)
- DC: Chân chọn dữ liệu gửi đến LCD là lệnh hay là dữ liệu để hiển thị ra màn hình
- CLK: Chân truyền xung nhịp theo chuẩn SPI
- DIN: Chân dữ liệu data
- VCC: Chân cấp nguồn cho LCD
- BL(LED): Chân cấp nguồn cho led nền màn hình LCD
- GND: Chân mass, cấp nguồn 0V
Cách giao tiếp
Đầu tiên ta chia ra làm 2 chế độ làm việc, chân DC có tác dụng lựa chọn chế độ làm việc cho LCD
- DC=0 : Chế độ gửi lệnh, tức là dữ liệu bạn gửi đến có nhiệm vụ điều khiển, cài đặt hoạt động của LCD chứ nó không in ra màn hình
- DC=1 : Chế độ gửi dữ liệu: Lúc này, tất cả mọi dữ liệu bàn gửi đến sẽ được hiển thị ra màn hình
LCD sẽ bị reset khi có chân reset ở mức thấp
LCD sẽ bị reset khi có chân reset ở mức thấp
LCD chỉ hoạt động khi chân CE ở mức 0. Do vậy chân này có tác dụng điều khiển nhiều LCD, nếu chỉ dùng 1 LCD cho dự án của mình. Các bạn nên tống nó xuống mass luôn đỡ phí mass IO của vi điều khiển
1:Chế độ gửi lệnh (cài đặt các thông số ban đầu cho LCD). Chân DC được kéo xuống mass
Ta lại chia ra làm 2 nhóm : Nhóm lệnh điều khiển cơ bản, và nhóm lệnh điều khiển bổ sung
- Bit H có tác dụng chon chế độ lệnh là cơ bản hay dùng các lệnh bổ sung. Nếu H=0 là lệnh cơ bản. H=1 là bổ sung
- Bit V lựa chọn chiều tăng của giá trị trong bộ nhớ. V=0 giá trị tăng theo chiều ngang. V=1 giá trị tăng theo chiều dọc
- Bit PD lựa chọn chế độ hoạt động. PD=0 thì LCD hoạt động. PD =1 thì LCD ngủ
Nhóm lệnh cơ bản
Dùng để set vị trí hiển thị trên màn hình LCD NOKIA 5110
- Lệnh set dòng
LCD có độ phân giải chiều cao là 48px. Chiều bắn dữ liệu lên màn là chiều dọc. Mỗi lần bắn 1byte, vậy LCD này chiều dọc sẽ chứa 48/8=6 byte. Tương đương ng6 dò. Vậy chỉ cần 3 bit để chứa giá trị set dòng, đó chính là các bit Y0 Y1 Y2
Như bảng trên, ví dụ : Y0=0 Y1=0 Y2=0 thì dòng được chọn là 0, tương tự nhé ! - Lệnh set cột
Có tới 84 cột nên cần 7 bit để lưu giá trị set cột
- Lệnh cài chế độ hiển thị
– 0x09: Hiển thị tất cả điểm ảnh lên
– 0x0C: Hiển thị thông thường (chữ đen nền trắng)
– 0x0D: Hiển thị âm bảm ( chữ trắng nền đen)
Nhóm lệnh bổ sung
Bao gồm mấy cái lệnh như set điện áp hoạt động các kiểu ..v..v.. Để cho nhanh gọn các bạn gửi byte 0xC0 là dùng điện áp 5V (các mức điện áp khác các bạn tham khảo công thức trong datasheet thẳng tiến nhé)
Khởi động màn hình
- CE =0 để cho phéo LCD hoạt động
- Tạo 1 xung trên chân RST để reset LCD
- Kéo chân DC xuống 0 để đi vào chế độ điều khiển
- Gửi lần lượt các byte vào lcd qua giao thức SPI : 0x21 0xC0 0x20 0x0C (xong)
Một số hàm giao tiếp cơ bản
Các bạn chú ý, demo này mình sử dụng code cho ATmega8 trên phần mềm CodeVisionAVR, và mô phỏng proteus
Khởi tạo giao thức SPI để giao tiếp với màn hình LCD Nokia 5110
1 2 3 4 5 6 7 8 9 10 11 12 13 |
void LCD_gui1byte(unsigned char byte) { unsigned char i; bit outbit; for(i=0;i<8;i++) { outbit=byte&0x80; // lay ra bit thu 7 SDA_LCD=outbit; // gan chan SDA cho gia tri cua bit thu 7 CLK_LCD=1; // tao xung nhip day bit qua LCD CLK_LCD=0; byte = byte << 1; // dich trai 1 lan de chuan bi lay bit tiep theo } } |
Tuy nhiên khi gửi đi 1 byte chúng ta cần phải xác định trước byte mà ta gửi đi ra lệnh hay dữ liệu in ra LCD, vì vậy mình sẽ chỉnh lại hàm nay 1 chút để điều chỉnh chân DC trước khi byte được gửi
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
void LCD_gui1byte(unsigned char x, unsigned char byte) // ham gui 1 byte du lieu den LCD { unsigned char i; bit outbit; DC=x; // x =1 hien thi ra man hinh, x=0 la gui lenh dieu khien LCD for(i=0;i<8;i++) { outbit=byte&0x80; // lay ra bit thu 7 SDA_LCD=outbit; // gan chan SDA cho gia tri cua bit thu 7 CLK_LCD=1; // tao xung nhip day bit qua LCD CLK_LCD=0; byte = byte << 1; // dich trai 1 lan de chuan bi lay bit tiep theo } } |
OK con dê, bây giờ muốn gửi 1 byte vào LCD ở độ gửi lệnh ta chỉ cần gọi LCD_gui1byte(0,byte cần gửi). Còn ở chế độ gửi dữ liệu thì gọi LCD_gui1byte(1,byte cần gửi)
Khảo sát sự hiển thị dữ liệu của hàm hiển thị. Mình ví dụ gọi hàm LCD_guikitu(1,0×81). Trong đó 0x81 là byte gửi vào LCD, bít 1 kéo chân DC lên 1 để báo cho LCD biết đại ca muấn mày in byte 0x81 này ra màn hình. Byte 0x81 = 10000001, BIT 1 cao nhất sẽ được in ra đầu tiên, sau đó lần lượt là các bit tiếp theo và được xắp xếp theo cột.
Nhìn vào ảnh trên chắc các bạn cũng đã hiểu cách mà byte được bắn ra màn rồi nhỉ. Tiếp theo sau khi bắn 1 byte 0x81 rồi mà ta tiếp tục bắn thêm 1 byte nữa thì chuyện gì sẽ xảy ra.Lần này mình thử gửi tiếp byte 0x80 nhé !
Cứ gửi byte thì cột sẽ tự động tăng lên để nó ghi byte đó vào cột tiếp theo mà không đè lên cột cũ. Nếu hết cột rồi thì tự động xuống dòng.!
Tiếp đến là hàm khởi tạo LCD
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
void LCD_khoitao() { CLK_LCD=0; CE=0; // cho phep LCD hoat dong delayms(2); RST=0; delayms(2); RST=1; // reset LCD delayms(2); LCD_gui1byte(0,0x21); // che do dieu khien LCD, gia tri nap vao 0x21 : tuong duong ghi du lieu theo chieu ngang va cho phep thuc hien cac lenh bo sung LCD_gui1byte(0,0xC0); // che do dieu khien LCD, dung dien ap 5V LCD_gui1byte(0,0x20); // che do dieu khien LCD, dung cac lenh co ban LCD_gui1byte(0,0x0C); //che do dieu khien LCD, che do hien thi thong thuong || hoac 0x0D neu muon nen den chu trang || 0x0C la hien binh thuong } |
Hàm chon vị trí
1 |
void LCD_chonvitri(unsigned char x, unsigned char y) { LCD_gui1byte(0,(0x40 | (y-1))); // chon dong LCD_gui1byte(0,(0x80 | (x-1))); // chon cot } |
Để gửi đi 1 kí tự chứ cái. Chúng ta sẽ phải xây dựng 1 bộ mã. Ví dụ mình muốn gửi đi chữ A có font chữ là 6×8 thì mình sẽ tạo 1 mã gồm 6 byte (mỗi byte là 1 cột) rồi viết 1 hàm bắn lần lượt 6 byte này lên. Do mã mình tạo theo bộ mã ASCII. Mà bộ mã ASCII có 32 mã đầu không sử dụng nên mình trừ đi 32. Rồi tạo 1 vòng lặp for 6 lần tương ứng bắn 6 byte lên LCD
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
void LCD_guikitu(unsigned char kitu) { unsigned char x,i; x=kitu-32; for(i=0;i<6;i++) { LCD_gui1byte(1,font6[x][i]); } } void LCD_guichuoi(unsigned char *chuoi) { while(*chuoi) { LCD_guikitu(*chuoi); chuoi++; } } |
Ví dụ : Muốn gửi đi chuỗi gocdiy.com tại dòng 2, bắt đầu từ cột thứ 10 thì trong hàm main mình sẽ gọi LCD_chonvitri(10,2); LCD_guichuoi(“”Goc DIY.com);
Gửi tặng các bạn 1 số hàm vẽ hình học lên màn LCD như: vẽ hình chữ nhật, vẽ đường thằng.Các bạn xem thêm trong code nhé
Như trên mình đã gọi hàm LCD_vehinhchunhat(15,21,20,5) trong đó 15 là chọn vị trí cột (từ 1 đến 84) 21 là chọn ví trí dòng (1 đến 44) 20 là chiều cao hình chữ nhật, 55 là chiều dài. Tuy nhiên gọi xong thì hình chữ nhật chưa in ra đâu nhé. Để in ra ta cần gọi thêm hàm LCD_xuat()
1 số hàm khác
Tiếp theo là hiện thị hình ảnh lên LCD ( từ từ cập nhật sau vậy). Các bạn có thể tải project tham khảo cho vi điều khiển ATmega8 tại đây
I cannot thank you enough for the blog post.Really looking forward to read more. Fantastic.