【技术分享】【原创】基于智能车的LCD显示接口设计
0赞智能车中经常需要进行显示设计,在二次开发中少不了进行接口扩充,今天我就写一下关于这方面的一点应用。灵感来源于一位同学的问题,结合我自己的思路编写了相关程序,一并给大家展示一下。
LCD液晶显示器由于具有体积小、重量轻、电压低、功耗低等特点,在大量便携式产品中得到了广泛的应用。在智能车系统中,LCD显示也提供了比LED显示更为灵活方便的一种显示解决方案。
LCD可分为段位式LCD、字符式LCD和点阵式LCD,其中段位式LCD和字符式LCD只能用于字符和数字的简单显示,不能满足图形、曲线和汉字显示的要求;而点阵式LCD不仅可以显示字符、数字、还可以显示各种图形、曲线以及汉字,并且可以实现屏幕上下左右滚动、动画、分区开窗口、反转、闪烁等多种功能。
本文以YM-0802B系列字符式LCD模块为例,叙述LCD显示在智能车系统中的应用。YM-0802B实物如下图所示,是2×8字符式LCD模块(可显示2行,每行8个字符)。
LCD显示接口设计
YM-0802B可以工作在全字或半字模式下。在此采用了半字模式,以节省MC9S12XS128的I/O口线。采用PORA口的高4位作为数据线,与YM-0802B的DB4~DB7连接,用PORTB的低3位作为控制线,分别与YM-0802B的RS、R/W、E连接,应用原理图下图所示。
关键的来了,我调试通过的程序:
#define LCD_EN PORTB_BIT0
#define LCD_RW PORTB_BIT1
#define LCD_RS PORTB_BIT2
#define LCD_DAT PORTA
/*************************************************************************
//功 能:检测忙信号
//入口参数:无
//出口参数:unsigned char
*************************************************************************/
unsigned char lcd_get_busy_state(void)
{
unsigned char ret_value;
LCD_RS = 0;
LCD_RW = 1;
PUCR_PUPAE = 1; //PORTA使能上拉
LCD_EN = 1; //产生一EN脉冲
delay_short(10);
ret_value = LCD_DAT; //返回最高位即数据最高位
ret_value &= 0x80;
PUCR_PUPAE = 0; //PORTA上拉电阻关闭
LCD_EN = 0;
delay_short(10);
return ret_value;
}
/*************************************************************************
//功 能:向LCD写高4位数据
//入口参数:unsigned char dat
//出口参数:无
*************************************************************************/
void lcd_write_4bit(unsigned char dat)
{
DDRA = 0xF0; //设置数据口PORTA高4位为输出
LCD_DAT = dat & 0xF0 //将数据送到数据口
LCD_EN = 1; //产生一EN脉冲
delay_short(10);
LCD_EN = 0;
delay_short(10);
DDRA = 0x00; //恢复数据口PORTA为输入
}
/*************************************************************************
//功 能:向LCD写命令
//入口参数:unsigned char cmd
//出口参数:无
*************************************************************************/
void lcd_write_command(unsigned char cmd)
{
while (lcd_get_busy_state() == 0x80) //忙检测
{
;
}
LCD_RS = 0;
LCD_RW = 0;
lcd_write_4bit(cmd); //写高4位
lcd_write_4bit(cmd<<4); //写低4位
}
/*************************************************************************
//功 能:向LCD写数据
//入口参数:unsigned char dat
//出口参数:无
*************************************************************************/
void lcd_write_data(unsigned char dat)
{
while (lcd_get_busy_state() == 0x80) //忙检测
{
;
}
LCD_RS = 1;
LCD_RW = 0;
lcd_write_4bit(dat); //写高4位
lcd_write_4bit(dat<<4); //写低4位
}
/*************************************************************************
//功 能:LCD清屏
//入口参数:无
//出口参数:无
*************************************************************************/
void lcd_clear(void)
{
lcd_write_command(0x01);
}
/*************************************************************************
//功 能:LCD初始化
//入口参数:无
//出口参数:无
*************************************************************************/
void lcd_init(void)
{
DDRA = 0; //数据口设置为输入
DDRB_BIT0 = 1; //控制口EN设置为输出
DDRB_BIT1 = 1; //控制口RS设置为输出
DDRB_BIT2 = 1; //控制口RW设置为输出
delay(500);
LCD_RS = 0;
LCD_RW = 0;
lcd_write_4bit(0x20);
lcd_write_command(0x28); //功能设置
lcd_write_command(0x0C); //开显示,不显示光标
lcd_write_command(0x01); //清屏
delay(30);
lcd_write_command(0x06); //增长模式
}
/*************************************************************************
//功 能:在指定位置显示数字
//入口参数:unsigned char x,unsigned char y,unsigned char num
//出口参数:无
*************************************************************************/
void lcd_display_number(unsigned char x, unsigned char y, unsigned char num)
{
if ((num >= 0) && (num <= 9))
{
num += 0x30;
}
if(x == 0) //设置当前位置
{
lcd_write_command(0x80 + y);
}
else
{
lcd_write_command(0xC0 + y);
}
lcd_write_data(num);
}