#include "lcd.h"
// 正常读写操作之前检测LCD控制器状态
// 读状态时序:RS=0,RW=1,E=1,判断忙完毕后释放总线
void WaitIdle()
{
unsigned char tmp;
RS=0; // 命令
RW=1; // 读取
DPORT=0xff; // 为接收数据作准备
delay2us(); // 短暂延时
E=1; // 使能LCD1602
delay2us(); // LCD1602在E为高电平区间输出数据到端口
for(;;)
{
tmp=DPORT; // 将数据端口上的值赋给tmp
tmp&=0x80; // 最高位为1时表示液晶模块正忙,不能对其进行操作
if( tmp==0) // 其余6位表示内部当前显示地址,无实际用途。
break;
}
E=0; // 释放总线
}
// 向LCD1602液晶写入一字节数据,dat-待写入数据值
// 写数据时序:RS=1,RW=0,D7——D0 = 数据,E=正脉冲,液晶在脉冲下降沿采样数据。
void lcd1602WriteByte(unsigned char dat)
{
// WaitIdle(); // 等待LCD1602空闲
delayNms(5);
RS=1; // 数据
RW=0; // 写
E=1; // 使能LCD1602
DPORT=dat; // 将待写数据送到数据端口
delay10us(); // 短暂延时
E=0; // 关闭LCD1602使能,释放总线
}
// 向LCD1602液晶写入一字节命令,cmd-待写入命令值
// 写命令时序:RS=0,RW=0,D7——D0 = 数据,E=正脉冲,液晶在脉冲下降沿采样数据。
void lcd1602WriteCmd(unsigned char cmd)
{
// WaitIdle(); // 等待LCD1602空闲
delayNms(5);
RS=0; // 命令
RW=0; // 写
E=1; // 使能LCD1602
DPORT=cmd; // 将命令码输出在数据端口上
delay10us(); // 短暂延时
E=0; // 关闭LCD1602使能,释放总线
}
// 清屏命令:清除显示内容,将1602内部RAM全部填入空白的ASCII码20H
// 光标归位,将光标撤回到屏幕左上角的坐标原点
// 将1602内部显示地址设为0
void lcd1602Clear()
{
lcd1602WriteCmd(0x01);
delayNms(50);
}
// 内部函数用于设置显示字符起始坐标
void lcd1602WritePos(unsigned char xPos,unsigned char yPos)
{
unsigned char tmp;
xPos&=0x1f; // x位置范围是0~15
// yPos&=0x10; // y位置范围是0~1
if(yPos==0){ // 显示第一行
tmp=xPos; // 第一行字符地址从 0x00 开始
tmp|=0x80; // 设置 RAM 地址
}
else if(yPos==1){
tmp=xPos+0x40; // 第二行字符地址从 0x40 开始
tmp|=0x80; // 设置 RAM 地址
}
else if(yPos==2){
tmp=xPos; // 第三行字符地址从 0x40 开始
tmp|=0x90; // 设置 RAM 地址
}
else if(yPos==3){
tmp=xPos+0x40; // 第四行字符地址从 0x40 开始
tmp|=0x90; // 设置 RAM 地址
}
lcd1602WriteCmd(tmp);
}
void lcd1602SetCursor(unsigned char Para) // 设置光标
{
switch(Para)
{
case 0:
{
lcd1602WriteCmd(0x08); break; // 关显示
}
case 1:
{
lcd1602WriteCmd(0x0c); break; // 开显示但无光标
}
case 2:
{
lcd1602WriteCmd(0x0e); break; // 开显示有光标但不闪烁
}
case 3:
{
lcd1602WriteCmd(0x0f); break; // 开显示有光标且闪烁
}
default:
break;
}
}
//在指定的行与列显示指定的字符,xpos:行,ypos:列,c:待显示字符
void lcd1602WriteChar(unsigned char xPos,unsigned char yPos,unsigned char Dat)
{
lcd1602WritePos(xPos,yPos);
lcd1602WriteByte(Dat);
}
// 在液晶上显示字符串,xpos:行坐标,ypos:列坐标,str-字符串指针
void lcd1602WriteString(unsigned char xPos,unsigned char yPos,unsigned char *s)
{
unsigned char i=0;
lcd1602WritePos(xPos,yPos); // 起始坐标
while(s[i])
{
lcd1602WriteByte(s[i]);
i++;
if (i>=32) break; // 超出16个字符外的数据丢弃
}
}
// LCD 1602初始化
void lcd1602Init()
{
lcd1602WriteCmd(0x38); /*显示模式设置*/
delayNms(5);
lcd1602WriteCmd(0x38);
lcd1602WriteCmd(0x08); // 显示关闭,不显示光标、光标不闪烁
lcd1602WriteCmd(0x01); // 显示清屏
lcd1602WriteCmd(0x06); // 显示光标移动位置
delayNms(5);
lcd1602WriteCmd(0x0c); // 显示开及光标设置
lcd1602Clear();
}