Mình xin upload thư viện viết cho LCD, ở đây mình dùng 8 bit mode cho LCD 2 line x 16 colum.
Code:
// LCD.h
#ifndef LCD_H
#define LCD_H
# include <pic.h>
//============== Using LCD - 2 line, 16 colum
#define LCD_MODE_2x16 (TRUE) // HDM16216H-2, HDM16216H-4, HDM16216H-5, HDM16216H-B, HDM16216H-D, HDM16216L-2, HDM16216L-5, HDM16216L-7, HDM16216L-D, HDM16216L-B, HDM16216H-I
#define LCD_CURSOR_BLINK (FALSE) // Blink/Noblink cursor mode
#define LCD_CURSOR_ON (TRUE) // Cursor visible
#define LCD_CURSOR_INCREMENT (TRUE) // Set left-to-right cursor movement
#define LCD_CURSOR_SHIFT (FALSE) // Shift display on entry
#define LCD_DISPLAY_ON (TRUE) // Turn display on/off
#define LCD_ALLOW_USER_CHARS (TRUE) // Controls whether display uses ASCII for control chars or uses user-defined chars in lcd_putc()
#define LCD_ENABLE_GETC (TRUE) // Save code space by setting to FALSE
#define LCD_ENABLE_GOTOXY (TRUE) // any functions which you will not
#define LCD_ENABLE_PRINTF (TRUE) // need in your application.
#define LCD_ENABLE_UNSCROLL (TRUE)
#define LCD_ENABLE_SCROLL (TRUE)
#define LCD_ENABLE_CLEAR (TRUE)
#define LCD_MAXROWS ((unsigned char)(2))
#define LCD_MAXCOLS ((unsigned char)(16))
# define LCD_MULTI_LINE (TRUE)
#define LCD_8_BIT_MODE (TRUE)
//======================= Define LCD_PORT
#define LCD_DATA_PORT PORTD // Port on which LCD data lines are connected
#define LCD_TRIS_PORT TRISD // Need to specify the corresponding TRIS
# define LCD_RS RA1
# define LCD_RW RA2
# define LCD_E RA3
# define LCD_TRIS_E TRISA1
# define LCD_TRIS_RW TRISA3
# define LCD_TRIS_RS TRISA2
// ======================= Define command code
#define LCD_COMMAND_CLEAR ((unsigned char)(0x01)) //1.53 ms // Clear screen, home cursor, unshift display
#define LCD_COMMAND_HOME ((unsigned char)(0x02)) //1.53 ms // Home cursor, unshift display
#define LCD_COMMAND_BACKSPACE ((unsigned char)(0x10)) // Move cursor left one (destructive based on LCD_DESTRUCTIVE_BS)
#define LCD_COMMAND_FWDSPACE ((unsigned char)(0x14)) // Move cursor right one
#define LCD_COMMAND_PANLEFT ((unsigned char)(0x18)) // Move screen left one
#define LCD_COMMAND_PANRIGHT ((unsigned char)(0x1C)) // Move screen right one
// ==================== Declare some functions
void delay_us (unsigned char us);
void delay_ms(unsigned char ms);
unsigned char LCD_getByte (void);
void LCD_PrByte (unsigned char c);
void LCD_Command(unsigned char c);
void LCD_PrChar (unsigned char c);
void LCD_gotoXY(unsigned char row, unsigned char col);
unsigned char LCD_getChar (void); // Read character at cursor
void LCD_Init(void);
void LCD_PrString (const char* message);
#endif
Các bạn sẽ thấy là khi muốn dùng LCD thì đầu tiên các bạn khai báo thông số cho LCD như các chân RS, RW, E, LCD_PORT ở
Define LCD_PORT. Mặc định mình khai báo là: LCD_PORT là PortD, RS là RA1, RW là RA2, E là RA3.
Các bước thực hiện:
- Khởi tạo LCD dùng lệnh: LCD_Init();
- Thao tác ghi đọc bình thường, chú ý nhất là các hàm: LCD_gotoXY, LCD_PrString, LCD_PrChar, LCD_Command.
Tiếp theo là file LCD.c là file thực hiện:
Code:
//LCD.c
# include "lcd.h"
// ==== Some constants for LCD 16x2
const unsigned char const LCD_ROW_ADDRESS[] = // Row/Column information for LCD_gotoxy()
{
0x00, // Line 1
0x40 // Line 2
};
const unsigned char const LCD_INIT_STRING [] = // LCD Init String on powerup
{
0b00000001, // Clear display
0b00000010, // Home cursor
};
//==========================================================================================
void delay_us (unsigned char us){
while(us--){
asm("nop");
asm("nop");
};
}
//==========================================================================================
void delay_ms(unsigned char ms){
unsigned char i, j;
while(ms--){
for (i = 0; i < 20; i++)
for (j = 0; j < 100; j++)
asm("nop");
};
}
// ============================================================================================
unsigned char LCD_getByte (void){
unsigned char retval; // Return value
LCD_TRIS_PORT = 0xFF; // Set port to all input
LCD_RW = 1; // Tell LCD we want to read
delay_us(2);
LCD_E = 1; // Do the read
delay_us(2);
retval = LCD_DATA_PORT;
LCD_E = 0;
LCD_TRIS_PORT = 0x00; // Set port back to outputs
return (retval);
}
//====================================================================================================
void LCD_PrByte (unsigned char c){ // Write byte to port in current RS mode
unsigned char RS_Status;
RS_Status = LCD_RS; // Get old pin state
LCD_RS = 0; // Force into command mode to read state
while (LCD_getByte () & 0x80); // Wait for read state
if (RS_Status)
LCD_RS = 1; // Restore RS to old state
delay_us (1);
LCD_RW = 0; // Set to write mode
delay_us (1);
LCD_DATA_PORT = c; // Send the character out
LCD_E = 1;
delay_us(1);
LCD_E = 0;
}
//================================================================================================
/*Ham yeu cau goi lenh dieu khien LCD*/
void LCD_Command(unsigned char c){ // Send command to LCD port
LCD_RS = 0;
LCD_PrByte(c);
}
//================================================================================================
/*Ham yeu cau goi du lieu hien thi len LCD*/
void LCD_PrChar (unsigned char c){ // Write character to LCD
LCD_RS = 1 ;
LCD_PrByte(c);
}
//=================================================================================================
void LCD_gotoXY(unsigned char row, unsigned char col){
if (row > LCD_MAXROWS) // Range limit
row = LCD_MAXROWS;
if (col > LCD_MAXCOLS)
col = LCD_MAXCOLS;
row = LCD_ROW_ADDRESS[row-1]; // Get address of first byte on desired row
row += col - 1;
LCD_Command (0x80 | row); // Write new cursor address
}
// =====================================================================================
unsigned char LCD_getChar (void) // Read character at cursor
{
unsigned char retval; // Return value
LCD_RS = 1;
retval = LCD_getByte ();
LCD_RS = 0;
return (retval);
}
//=======================================================================================
void LCD_Init(void){
unsigned char i;
LCD_TRIS_PORT = 0x00;
LCD_TRIS_E = 0;
LCD_TRIS_RW = 0;
LCD_TRIS_RS = 0;
LCD_E = 0 ;
LCD_RS = 0;
LCD_RW = 0;
//delay_ms(100); // Tao tre 100ms cho LCD khoi dong
LCD_PrByte (0b00111000); //Function set ; DL = 1(8 bits) , N = 1 (2 lines), F = 0 (5x8 dots)
LCD_PrByte (0b00001100); // Display on/off control
LCD_PrByte (0b00000110); // Entry mode set
LCD_PrByte(LCD_COMMAND_CLEAR);
LCD_PrByte(LCD_COMMAND_HOME);
}
// ===================================================================================================
void LCD_PrString (const char* message){ // Write message to LCD (C string type)
while (*message) // Look for end of string
LCD_PrChar (*message++); // Show and bump
}
Các bạn thêm 2 file này vào trong Project của mình và nhớ include file
LCD.h vào chỗ đầu file chứa hàm Main nhé.
Các bạn có thể mô phỏng bằng Proteus chạy rất ok. Lúc nào gửi tiếp mấy cái đã test.
Chúc các bạn thành công.