BOOLEAN RW; // The bits are allocated from BOOLEAN unused; // low order up... Khi bật nguồn cần INIT thì LCD mới hoạt động // Input = None... // Xem datasheet để biết thời gian trễ for
Trang 1Trong ví dụ sau sử dụng CCS làm trình biên dịch
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000) // Sử dụng Crystal 20 MHz
// Định nghĩa các chân cho LCD như sau
// Dùng điều khiển 4 bit ( 4 bit cao D4 đến D7)
// PIN_B0 ENABLE
// PIN_B1 RS
// PIN_B2 RW
// PIN_B4 D4
// PIN_B5 D5
// PIN_B6 D6
// PIN_B7 D7
// Chân D0-D3 Không sử dụng
// Chân RB3 của PIC cũng không sử dụng
// Định nghĩa struct của LCD tương ứng với các bit
// -
struct lcd_pin_map
{
BOOLEAN ENABLE; // on to an I/O port to gain
BOOLEAN RS; // access to the LCD pins
BOOLEAN RW; // The bits are allocated from
BOOLEAN unused; // low order up ENABLE will
Int8 data : 4; // be pin B0
} lcd;
#byte lcd = 6 // Sử dụng Port B của PIC16F877A Nếu dùng loại khác cần thay //đổi giá trị này ( Xem datasheet để sửa đổi)
#define lcd_type 2 // LCD1602 lcd_type = 2
BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xC, 1, 6};
struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // Để cấu hình cho Port của PIC struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // 4 Bit D4 - D7 là Input
BYTE lcdline;
// -
// Đọc 1 byte từ LCD
// Thường dùng để kiểm tra trạng thái ready của LCD
// Input = none
// Output = Giá trị đọc từ LCD
// -
BYTE lcd_read_byte()
Trang 2{
BYTE low,high;
set_tris_b(LCD_READ); // Set D4 - D7 là input
lcd.RW = 1;
delay_cycles(1);
lcd.ENABLE = 1;
delay_cycles(1);
high = lcd.data; // Đọc 4 bít cao
lcd.ENABLE = 0;
delay_cycles(1);
lcd.enable = 1;
delay_us(1);
low = lcd.data; // Đọc 4 bit thấp
lcd ENABLE = 0;
set_tris_b(LCD_WRITE); // Set D4 - D7 là output
return( (high<<4) | low); // Giá trị trả về
}
// -
// Ghi 4 bit vào LCD
// Input = 4 bit cần ghi
// Output = None
// -
void lcd_send_nibble( BYTE n )
{
lcd.data = n;
delay_cycles(1);
lcd.ENABLE = 1;
delay_us(2);
lcd ENABLE = 0;
}
// -
void lcd_send_byte( BYTE address, BYTE n ) {
lcd.rs = 0;
while ( bit_test(lcd_read_byte(),7) ) ;
lcd.rs = address;
delay_cycles(1);
lcd.rw = 0;
delay_cycles(1);
lcd ENABLE = 0;
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
// -
// Hàm init cho LCD Khi bật nguồn cần INIT thì LCD mới hoạt động
// Input = None
Trang 3// Output = None
// -
void lcd_init() {
BYTE i;
set_tris_b(LCD_WRITE); // D4 -D7 = output
lcd.ENABLE = 0;
delay_ms(15); // Chờ cho LCD sẵn sàng từ khi bật nguồn
// Xem datasheet để biết thời gian trễ
for(i=1;i<=3;++i)
{
lcd_send_nibble(3);
delay_ms(5);
}
lcd_send_nibble(2);
for(i=0;i<=3;++i) lcd_send_byte(0, LCD_INIT_STRING[i]);
}
// -
// Di chuyển con trỏ màn hình tới toạ độ X,Y
// X từ 0 đến 15
// Y từ 0 đến 1
// Input X,Y = Toạ độ cần chuyển tới
// Output = None
// -
void lcd_gotoxy( BYTE x, BYTE y)
{
BYTE address;
switch(y)
{
case 1 : address=0x80;break;
case 2 : address=0xc0;break;
case 3 : address=0x94;break; // Sử dụng cho LCD 4 dòng case 4 : address=0xd4;break; // Sử dụng cho LCD 4 dòng
}
address+=x-1;
lcd_send_byte(0,address);
}
// -
// Ghi 1 ký tự ra màn hình
// Input c = mã ASCII của kí tự
// Có thể sử dụng các kí tự điều khiển như xuống dòng, Về đầu trang vv
// Output = None
// -
void lcd_putc( char c)
Trang 4{
switch (c) {
case '\f' : lcd_send_byte(0,1);
lcdline=1;
delay_ms(2); // Xem datasheet để có thêm chi tiết
break;
case '\n' : lcd_gotoxy(1,++lcdline); break;
case '\b' : lcd_send_byte(0,0x10); break;
default : lcd_send_byte(1,c); break;
}
}
// -
// Đọc 1 ký tự từ LCD tại toạ độ X,Y
// Thường dùng để kiểm tra LCD hay Update LCD
// Sẽ tận dụng được bộ nhớ của MCU do không phải lưu giá trị tại MCU
// -
char lcd_getc( BYTE x, BYTE y)
{
char value;
lcd_gotoxy(x,y); // Chuyển con trỏ tới toạ độ X,Y
value = lcd_read_byte();
return(value);
}
void main()
{
char k;
lcd_init();
lcd_putc("\fReady \n");
lcd_putc(“Hello Microchip”);
while (1) ;
}