/*********************************************************************
文件名称:lcd1602.c
文件功能:lcd1602液晶驱动
*********************************************************************/
#include "lcd1602.h"
/*********************************************************************
功能:读取LCD状态
参数:无
返回:0 -- 空闲,可以进行读写操作
1 -- 忙
*********************************************************************/
u8 lcd1602_read_state(void)
{
u8 temp = 0;
LCD1602_EN = 0;
LCD1602_RS = 0;
LCD1602_RW = 1;
LCD1602_EN = 1;
_nop_();
_nop_();
//读取状态
LCD1602_DATA = 0xFF;
temp = LCD1602_DATA;
//只有最高位表示状态
if(temp & 0x80)
{
return 1;
}
else
{
return 0;
}
}
/*********************************************************************
功能:向lcd写入指令
参数:command -- 指令
返回:无
*********************************************************************/
void lcd1602_write_command(u8 command)
{
u8 i = 0;
while(1)
{
//统计检测次数
i++;
//空闲退出循环
if(lcd1602_read_state() == 0)
{
break;
}
//多次检测仍忙,放弃此次操作
else if(i > 50)
{
return;
}
}
//输出指令
LCD1602_EN = 0;
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_DATA = command;
_nop_();
_nop_();
//EN端产生上升沿,再恢复到低
LCD1602_EN = 1;
_nop_();
_nop_();
LCD1602_EN = 0;
}
/*********************************************************************
功能:向lcd写入数据
参数:dat -- 数据
返回:无
*********************************************************************/
void lcd1602_write_data(u8 dat)
{
u8 i = 0;
while(1)
{
//统计检测次数
i++;
//空闲退出循环
if(lcd1602_read_state() == 0)
{
break;
}
//多次检测仍忙,放弃此次操作
else if(i > 50)
{
return;
}
}
//输出数据
LCD1602_EN = 0;
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DATA = dat;
_nop_();
_nop_();
//EN端产生上升沿,再恢复到低
LCD1602_EN = 1;
_nop_();
_nop_();
LCD1602_EN = 0;
}
/*********************************************************************
功能:lcd初始化
参数:无
返回:无
*********************************************************************/
void lcd1602_init(void)
{
lcd1602_write_command(0x38); //设置16*2显示,5*7点阵,8位数据接口
lcd1602_write_command(0x0C); //开显示,没有光标
lcd1602_write_command(0x06); //写入数据,地址和光标增加,不移动
lcd1602_write_command(0x01); //显示清屏
}
/*********************************************************************
功能:设定lcd显示位置,即地址
参数:row -- 行坐标 1~2
col -- 列坐标 1~16
返回:0--修改失败
1--修改成功
*********************************************************************/
u8 lcd1602_set_cursor(u8 row, u8 col)
{
u8 addr = 0;
//判断参数合法性
if((row < 1) || (row > 2) || (col < 1) || (col > 16))
{
//参数有误,直接返回
return 0;
}
//把坐标转换成地址
if(row == 1)
{
addr = col - 1;
}
else if(row == 2)
{
addr = 0x40 + (col - 1);
}
//写入地址
lcd1602_write_command(0x80 | addr);
return 1;
}
/*********************************************************************
功能:在特定的坐标写入字符
参数:row -- 行坐标 1~2, 如果是0则不进行坐标改动
col -- 列坐标 1~16,如果是0则不进行坐标改动
chr -- 字符ASCII码
返回:无
*********************************************************************/
void lcd1602_write_char(u8 row, u8 col, u8 chr)
{
//改动光标位置
if((row != 0) && (col != 0))
{
if(!lcd1602_set_cursor(row, col))
{
//光标修改失败,直接返回
return;
}
}
//写入字符
lcd1602_write_data(chr);
}
/*********************************************************************
功能:在特定的坐标写入字符串,没有换行功能
参数:row -- 行坐标 1~2, 如果是0则不进行坐标改动
col -- 列坐标 1~16,如果是0则不进行坐标改动
str -- 字符串地址
返回:无
*********************************************************************/
void lcd1602_write_str(u8 row, u8 col, u8 *str)
{
u8 count = 0;
//改动光标位置
if((row != 0) && (col != 0))
{
if(!lcd1602_set_cursor(row, col))
{
//光标修改失败,直接返回
return;
}
}
//写入字符串
while(*str != '\0')
{
lcd1602_write_data(*str);
str++;
//这里用count计数,防止死循环
count++;
if(count > 16)
{
break;
}
}
}
/*********************************************************************
功能:在特定的坐标写入数字,没有换行功能
参数:row-- 行坐标 1~2, 如果是0则不进行坐标改动
col-- 列坐标 1~16,如果是0则不进行坐标改动
num-- 要显示的数字,范围0~9999
返回:无
*********************************************************************/
void lcd1602_write_num(u8 row, u8 col, u16 num)
{
u8 str[5]; //保存num转换成的字符串
u8 temp = 0, i = 0, count = 0;
u8 *p;
//取得千位,转换成ASCII码存入str
temp = num / 1000;
str[0] = temp + '0';
//取得百位
num = num - 1000 * temp;
temp = num / 100;
str[1] = temp + '0';
//取得十位
num = num - 100 * temp;
temp = num / 10;
str[2] = temp + '0';
//取得个位
temp = num % 10;
str[3] = temp + '0';
//添加字符串结束标志
str[4] = '\0';
//统计高位0的位数
p = str;
while(*p != '\0')
{
if(*p++ == '0')
{
count++;
}
else
{
break;
}
}
if(count == 0)
{
//最高位不为0,不用处理
}
else if((count > 0) && (count < 4))
{
//根据0的个数,将字符串左移count个
for(i = 0; i < (4 - count); i++)
{
str= str[i + count];
}
str= '\0';
}
else if(count == 4)
{
//num的值为0
str[0] = '0';
str[1] = '\0';
}
lcd1602_write_str(row, col, str);
}
/*********************************************************************
EndOfFile
*********************************************************************/