/*2014.12.22,于番禺云桥头村,修改更新的lcd1602驱动-------------------------------------------------*/
/*---------------------LCD1602程序-----------------------*/
/*-------------------通用的单片机驱动lcd1602头文件,驱动液晶lcd1062的通用c语言头文件调用即可,经过测试正常使用,8051上测试通过,封装成一个头文件,在工程中加入就可以使用了-----------------------------------*/
#ifndef __LinEngLCD_1602_dri__
#define __LinEngLCD_1602_dri__
#include "stdlib.h"
sbit LCD1602_rs=P2^0;//lcd1602的命令还是数据选择线
sbit LCD1602_rw=P2^1;//lcd的续写选择线,0表示写,1表示读
sbit lCD1602_en=P2^2;//脉冲信号,使能信号
data unsigned char lcd1602_j,lcd1602_k;//用于延时的函数
#define LCD_Data_Port P0//命令或者数据口定义,8bit
unsigned char gobal_str[10];
unsigned char tmp_str[10];
extern sprintf();
//lcd1602延时函数,每个形参表示80次减少,
void LCD1602_at_12mHz_Delay(unsigned char z)
{
for(lcd1602_j=z;lcd1602_j>0;lcd1602_j--)
for(lcd1602_k=80;lcd1602_k>0;lcd1602_k--);
}
void LCD_nop(void)//lcd1602的nop函数,什么也不做
{
;
}
// Test the Busy bit
void LCD1602_Check_Busy(void)//lcd1602的checkbusy函数
{
unsigned char flag=0x80;
//赋初值 高位为1 禁止
while (flag&0x80) //读写操作使能位禁止时等待 继续检测
{
P0=0xff;
LCD1602_rs=0; //指向地址计数器
LCD1602_rw=1; //读
lCD1602_en=1; //信号下降沿有效
flag=LCD_Data_Port; //读状态位 高位为状态
lCD1602_en=0;
}
}
/*~~~~~~~~~~~~~~~~~~写入命令子程序~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void LCD1602_Write_Com(unsigned char com) //写命令
{
LCD1602_Check_Busy(); //判断是否忙碌
LCD1602_rs=0;//rs等于0表示写命令
LCD1602_rw=0;//rw等于1表示写,非读
lCD1602_en=0;//en是0,
LCD_Data_Port=com;//命令送入数据线
lCD1602_en=1; //使能拉高,然后拉低,完成数据锁存
lCD1602_en=0;//高和低之间可能需要延时,看系统速度而定
}
/*~~~~~~~~~~~~~~~~~~写入数据子程序~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void LCD1602_Write_Date(unsigned char date) //写数据
{
LCD1602_Check_Busy();//每次读写,请务必检查一下是否busy
LCD1602_rs=1;//rs等于1,表示是数据
LCD1602_rw=0;//rw是0,因为是要写入
lCD1602_en=0;//先把使能拉低
LCD_Data_Port=date;//送入数据
lCD1602_en=1;//然后把使能拉高,
lCD1602_en=0;//拉高之后忙吧使能拉低,高和低之间可能需要延时,看系统速度而定
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~LCD1602初始化程序~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void LCD1602_init()
{
lCD1602_en=0;
LCD1602_rw=0;
LCD1602_Write_Com(0x30);// 8-bits, 1 lines, 7x5 dots
LCD1602_Write_Com(0x38); //设置16x2显示,5X7点阵,8为数据接口
LCD1602_Write_Com(0x0c); //00001DCB; 都等于1时D表示开显示;C表示显示光标;B表示光标闪烁
LCD1602_Write_Com(0x01);// 8-bits, 1 lines, 7x5 dots 清屏幕
LCD1602_Write_Com(0x06); //000001NS
N 等于1时表示当读或写一个字符后地址加1,且光标加1,
//N等于0时则相反;S表示显示
//S=1时当写一个字符,整屏显示左移(N=1)或右移(N=0);
//S=0时表示当写一个字符,整屏显示不移动
// write_com(0x80); //数据指针地址,80表示第一行开始处,80+40表示第二行开始处
// write_com(0x80+X); X最大值为15
}
// Display a string at lcd1602,传入的形参addr表示数据开始的地址,0x80表示第一行第一格开始,
//0xc0表示第二行,第1个开始
void LCD1602_Disp_String(unsigned char start_addr, unsigned char *s)
{
LCD1602_Write_Com(start_addr);//先设定开始的地址,然后写字符串
while(*s>0)
{
LCD1602_Write_Date(*s++);
}
}
void num2char(int num)//自己编写的int数字转换成字符串的函数,一定要注意这里的字符串长度。
{
unsigned char i,j;//临时用的计数变量
unsigned long tmp_num;//临时的数字存贮
j=0;//初始化计数变量
i=0;
if(num<0)//如果是负数,
{
tmp_num=labs(num);//先获得绝对值
judge_again_label:
if(tmp_num!=0)//如果tmp_num不是0,还可以除以10
{
i++;//数据指标加1,i从1开始
tmp_str[i] =tmp_num%10+'0';//余数放到数组,转成ascii!
tmp_num/=10;//tmp_num除掉10更新,这样非常麻烦。。。
goto judge_again_label;
}
else//如果tmp_num已经是0了
{
gobal_str[0]='-';//因为是负数,所以前面要加符号
j=1;//j从1开始,
again_label_2:
if(i!=0)//如果i不是0,一直循环,i是1---n,
{
gobal_str[j]=tmp_str[i];//把j[1--n]的数字赋值给gobal,i递减,
i--;
j++;
goto again_label_2;
}
else//如果i是0,赋值完成,最后一个gobal结尾赋值‘