📄 lcd1604.c
字号:
struct lcd_pin_map {
BOOLEAN enable; // enable为1位,对应RD0
BOOLEAN rs; // rs为1位,对应RD1
BOOLEAN rw; // rw为1位,对应RD2
BOOLEAN BL_pwr; // BL_pwr为1位,对应RD3 BL_pwr为1位,对应RD3,开关LCD背光灯
int data : 4; // 声明data为4位,对应RD4,RD5,RD6,RD7
} lcd;
#if defined(__PCH__)
#if defined use_portb_lcd
#byte lcd = 0xF81 //使用端口PORT_b作为LCD接口(at address 0xF81)
#else
#byte lcd = 0xF83 //使用端口PORT_D作为LCD接口(at address 0xF83)
#endif
#endif
#if defined use_portb_lcd
#define set_tris_lcd(x) set_tris_b(x)
#else
#define set_tris_lcd(x) set_tris_d(x)
#endif
#define lcd_type 2 // LCD为两行
#define lcd_line_two 0x40 // 第二行LCD_RAM首地址为0x40
BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
// These bytes need to be sent to the LCD
// to start it up.
// The following are used for setting
// the I/O port direction register.
struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; //对于写方式,所有脚设置为输出
struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; //对于读方式,低位4为输出,高4位data pins为输入,15为F;
BYTE lcd_read_byte() {
BYTE low,high; //声明暂态变量low,high,high用来存字节的高4位,low用来存字节的低4位;
set_tris_lcd(LCD_READ);//设置端口B的低4位为输出口,端口B的高4位为输入口;
lcd.rw = 1; //发送LCD读命令;
delay_cycles(1); //相当于1个NOP指令;
lcd.enable = 1; //LCD使能;
delay_cycles(1);
high = lcd.data; //读LCD端口的数据高4位;
lcd.enable = 0; //LCD不使能;
delay_cycles(1);
lcd.enable = 1; //LCD使能;
delay_us(1); //延时1us;
low = lcd.data; //读LCD端口的数据低4位;
lcd.enable = 0; //LCD不使能;
set_tris_lcd(LCD_WRITE); //设置控制LCD端口B为输出口
return( (high<<4) | low); //合并字节的高4位和字节的低4位,组成1个字节,返回
}
void lcd_send_nibble( BYTE n ) {
lcd.data = n;
delay_cycles(1); //相当于1个NOP指令;
lcd.enable = 1; //LCD使能;
delay_us(2); //延时1us;
lcd.enable = 0; //LCD不使能;
}
/* address=0选择命令寄存器,则n为命令字;若address=1选择数据寄存器,则n为显示数据 */
void lcd_send_byte( BYTE address, BYTE n ) {
lcd.rs = 0; //选择LCD的地址寄存器;
while ( bit_test(lcd_read_byte(),7) ) ; //bit_test(X,b)位测试涵数,测试LCD是否忙;
lcd.rs = address; //选择LCD的地址寄存器
delay_cycles(1); //相当于1个NOP指令;
lcd.rw = 0; //向LCD发送写命令;
delay_cycles(1); //相当于1个NOP指令;
lcd.enable = 0; //LCD不使能;
lcd_send_nibble(n >> 4); //向LCD写数据n的高4位;
lcd_send_nibble(n & 0xf); //向LCD写数据n的低4位;
}
/* 通过x和y的坐标取得真正的LCD_RAM地址,并发送写地址命令 */
void lcd_gotoxy( BYTE x, BYTE y) {
BYTE address; //声明暂态变量address;
if(y!=1)
address=lcd_line_two; //将LCD_RAM的第2行首地址0x40送给address;
else
address=0; //将LCD_RAM的第1行首地址0x00送给address;
address+=x-1; //通过x和y的坐标取得真正的LCD_RAM地址;
lcd_send_byte(0,0x80|address); //向LCD发送写地址命令
}
/* 向LCD写数据 */
void lcd_putc( char c) {
switch (c) {
case '\f' : lcd_send_byte(0,1); //若c是走纸换页符('\f'),则执行该行;
delay_ms(2);
break;
case '\n' : lcd_gotoxy(1,2); break; //若c是换行符('\n'),则执行该行;
case '\b' : lcd_send_byte(0,0x10); break; //若c是退格符('\b'),则执行该行;
default : lcd_send_byte(1,c); break;
}
}
/* 根据x和y的坐标读取LCD的数据 */
char lcd_getc( BYTE x, BYTE y) {
char value;
lcd_gotoxy(x,y); //向LCD写写地址
while ( bit_test(lcd_read_byte(),7) ); //若LCD忙,则等待
lcd.rs=1;
value = lcd_read_byte(); //读指定坐标位置的数据
lcd.rs=0;
return(value);
}
/* LCD初始化函数 */
void lcd_init() {
BYTE i; //声明暂态变量i;
output_high(PIN_E7); //开LCD电源
set_tris_lcd(LCD_WRITE); //设置控制LCD端口B为输出口;
lcd.rs = 0; //选择LCD的地址寄存器;
lcd.rw = 0; //向LCD发送写命令;
lcd.enable = 0; //LCD不使能;
delay_ms(15); //延时15ms;
for(i=1;i<=3;++i) {
lcd_send_nibble(3); //将0x333送给LCD;
delay_ms(5); //延时5ms
}
lcd_send_nibble(2); //将0x2333送给LCD;
for(i=0;i<=3;++i)
lcd_send_byte(0,LCD_INIT_STRING[i]);
lcd.BL_pwr=1; //开LCD背光灯
lcd_putc("\fReady...\n");
delay_ms(1000);
lcd_putc("\fOutput: 0.00mA\n"); //显示Output: 0.00mA
}
void lcd1604_display(*display_pointer){
int lcd_counter=0;
int lcd_temp;
lcd_gotoxy(8,1); //计算坐标(8,1)处的LCD_RAM地址
if( *(display_pointer)=='0' )
{ lcd_putc(" ");
lcd_counter++;
}
for(; lcd_counter<5;lcd_counter++)
{
lcd_temp=*(display_pointer+lcd_counter);
lcd_putc(lcd_temp);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -