📄 lcd12232.c
字号:
/*此例子是LCD12232,时钟和温度传感受的集合,有不明白的朋友,可以先看下前面的三个例子,再加已集合*/
#include <reg51.h>
#include <intrins.h>
#define MSB 0x80
#define LSB 0x01
sbit LCD_RS=P1^0;//定义引脚
sbit LCD_RW=P1^1;
sbit LCD_E=P1^2;
#define LCD_Data P2
#define Busy 0x80 //用于检测LCD状态字中的Busy标识
sbit SCL2=P1^3;
sbit SDA2=P1^4;
sbit RST = P1^5;// DS1302片选 5脚
sbit DS=P3^3; //定义DS18B20接口
void WriteDataLCD(unsigned char WDLCD);
void WriteCommandLCD(unsigned char WCLCD,BuysC);
unsigned char ReadDataLCD(void);
unsigned char ReadStatusLCD(void);
void LCDInit(void);
void LCDClear(void);
void LCDFlash(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char *DData);
void Delay5Ms(void);
void Delay400Ms(void);
void Write_Ds1302_byte(unsigned char temp);
void Write_Ds1302( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302 ( unsigned char address );
void Read_RTC(void);//read RTC
void Set_RTC(void);//set RTC
int tmep(void);
void tmpchange(void);
void tmpwritebyte(unsigned char dat);
unsigned char tmpread(void);
bit tmpreadbit(void);
void dsreset(void);
void delayb(unsigned int count);
unsigned char l_tmpdate[8]={0x00,0x06,0x03,0x1C,0x08,0x07,0x08,0};
code unsigned char write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
code unsigned char read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
unsigned char lhj_f[15]={"2008年08月28日"};
unsigned char lhj_s[15]={"12:00 温度28℃"};
void main(void)
{
unsigned char oldtimer=0,i=0;
int l_tmp=0;
Set_RTC();
Delay400Ms(); //启动等待,等LCD讲入工作状态
LCDInit(); //LCM初始化
Delay5Ms(); //延时片刻(可不要)
while(1){
Read_RTC();
if(oldtimer!=l_tmpdate[0]){//每一秒钟刷新显示
oldtimer=l_tmpdate[0];
lhj_f[2]=(l_tmpdate[6]/16)+0X30; //这里加上0X30是在ASCII字符编码中的地址,你们可以查下ASCII码
//这里除以16怎么不是除以10呢,是的,这是因为DS1302里面是按10进制存放的
lhj_f[3]=(l_tmpdate[6]&0x0f)+0X30;
lhj_f[6]=(l_tmpdate[4]/16)+0X30;
lhj_f[7]=(l_tmpdate[4]&0x0f)+0X30;
lhj_f[10]=(l_tmpdate[3]/16)+0X30;
lhj_f[11]=(l_tmpdate[3]&0x0f)+0X30;
lhj_s[0]=(l_tmpdate[2]/16)+0X30;
lhj_s[1]=(l_tmpdate[2]&0x0f)+0X30;
if(i==0){ //每一秒钟转换显示(空-两点)
lhj_s[2]=0X3A;
i=1;
}
else{
lhj_s[2]=0x20;
i=0;
}
lhj_s[3]=(l_tmpdate[1]/16)+0X30;
lhj_s[4]=(l_tmpdate[1]&0x0f)+0X30;
tmpchange(); //温度转换
l_tmp=tmep();
lhj_s[10]=l_tmp/100+0X30;
l_tmp=l_tmp%100;
lhj_s[11]=l_tmp/10+0X30;//温度显示我们去掉了小数位,有兴趣的朋友可以加入
DisplayListChar(0, 0, lhj_f);
DisplayListChar(0, 5, lhj_s);
}
//}
}
}
/*********************LCD12232显示处理函数****************************/
//写数据
void WriteDataLCD(unsigned char WDLCD)
{
ReadStatusLCD(); //检测忙
LCD_RS = 1;
LCD_RW = 0;
LCD_Data = WDLCD;
LCD_E = 1;
LCD_E = 1;
LCD_E = 1;
LCD_E = 0;
}
//写指令
void WriteCommandLCD(unsigned char WCLCD,BuysC) //BuysC为0时忽略忙检测
{
if (BuysC) ReadStatusLCD(); //根据需要检测忙
LCD_RS = 0;
LCD_RW = 0;
LCD_Data = WCLCD;
LCD_E = 1;
LCD_E = 1;
LCD_E = 1;
LCD_E = 0;
}
//读数据
unsigned char ReadDataLCD(void)
{
LCD_RS = 1;
LCD_RW = 1;
LCD_E = 0;
LCD_E = 0;
LCD_E = 1;
return(LCD_Data);
}
//读状态
unsigned char ReadStatusLCD(void)
{
LCD_Data = 0xFF;
LCD_RS = 0;
LCD_RW = 1;
LCD_E = 1;
while (LCD_Data & Busy); //检测忙信号
LCD_E = 0;
return(LCD_Data);
}
void LCDInit(void) //LCM初始化
{
WriteCommandLCD(0x30,1); //显示模式设置,开始要求每次检测忙信号
WriteCommandLCD(0x01,1); //显示清屏
WriteCommandLCD(0x06,1); // 显示光标移动设置
WriteCommandLCD(0x0C,1); // 显示开及光标设置
}
void LCDClear(void) //清屏
{
WriteCommandLCD(0x01,1); //显示清屏
WriteCommandLCD(0x34,1); // 显示光标移动设置
WriteCommandLCD(0x30,1); // 显示开及光标设置
}
void LCDFlash(void) //闪烁效果
{
WriteCommandLCD(0x08,1); //显示清屏
Delay400Ms();
WriteCommandLCD(0x0c,1); // 显示开及光标设置
Delay400Ms();
WriteCommandLCD(0x08,1); //显示清屏
Delay400Ms();
WriteCommandLCD(0x0c,1); // 显示开及光标设置
Delay400Ms();
WriteCommandLCD(0x08,1); //显示清屏
Delay400Ms();
}
//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x10; //当要显示第二行时地址码+0x10;
X |= 0x80; // 算出指令码
WriteCommandLCD(X, 0); //这里不检测忙信号,发送地址码
WriteDataLCD(DData);
}
//按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char *DData)
{
unsigned char ListLength,X2;
ListLength = 0;
X2=X;
Y &= 0x01;
X &= 0x0F; //限制X不能大于15,Y不能大于1
if (Y) X2 |= 0x10; //当要显示第二行时地址码+0x10;
X2 |= 0x80; // 算出指令码
WriteCommandLCD(X2, 1); //这里不检测忙信号,发送地址码
while (DData[ListLength]>=0x20) //若到达字串尾则退出
{
if (X <= 0x0F) //X坐标应小于0xF
{
WriteDataLCD(DData[ListLength]); //
ListLength++;
X++;
}
}
}
//5ms延时
void Delay5Ms(void)
{
unsigned int TempCyc = 5552;
while(TempCyc--);
}
//400ms延时
void Delay400Ms(void)
{
unsigned char TempCycA = 5;
unsigned int TempCycB;
while(TempCycA--)
{
TempCycB=7269;
while(TempCycB--);
};
}
/***********************************************************************/
/*************************************时间操作函数**************************************/
void Write_Ds1302_Byte(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++) //循环8次 写入数据
{
SCL2=0;
SDA2=temp&LSB; //每次传输低字节
temp>>=1; //右移一位
SCL2=1;
}
}
void Write_Ds1302( unsigned char address,unsigned char dat )
{
RST=0;
_nop_();
SCL2=0;
_nop_();
RST=1;
_nop_(); //启动
Write_Ds1302_Byte(address); //发送地址
Write_Ds1302_Byte(dat); //发送数据
RST=0; //恢复
}
unsigned char Read_Ds1302 ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0;
_nop_();
SCL2=0;
_nop_();
RST=1;
_nop_();
Write_Ds1302_Byte(address);
for (i=0;i<8;i++) //循环8次 读取数据
{
SCL2=1;
_nop_();
if(SDA2)
temp|=0x80; //每次传输低字节
SCL2=0;
temp>>=1; //右移一位
}
RST=0;
_nop_();
SCL2=1;
SDA2=0;
return (temp); //返回
}
void Read_RTC(void) //读取 日历
{
unsigned char i,*p;
p=read_rtc_address; //地址传递
for(i=0;i<7;i++) //分7次读取 年月日时分秒星期
{
l_tmpdate[i]=Read_Ds1302(*p);
p++;
}
}
void Set_RTC(void) //设定 日历
{
unsigned char i,*p,tmp;
for(i=0;i<7;i++){
tmp=l_tmpdate[i]/10;
l_tmpdate[i]=l_tmpdate[i]%10;
l_tmpdate[i]=l_tmpdate[i]+tmp*16;
}
Write_Ds1302(0x8E,0X00);
p=write_rtc_address; //传地址
for(i=0;i<7;i++) //7次写入 年月日时分秒星期
{
Write_Ds1302(*p,l_tmpdate[i]);
p++;
}
Write_Ds1302(0x8E,0x80);
}
/***********************************************************************/
/**********************DS18B20温度读操作函数********************************/
void delayb(unsigned int count) //delay
{
unsigned int i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}
void dsreset(void) //DS18B20初始化
{
unsigned int i;
DS=0;
i=103;
while(i>0)i--;
DS=1;
i=4;
while(i>0)i--;
}
bit tmpreadbit(void) // 读一位
{
unsigned int i;
bit dat;
DS=0;i++; //小延时一下
DS=1;i++;i++;
dat=DS;
i=8;while(i>0)i--;
return (dat);
}
unsigned char tmpread(void) //读一个字节
{
unsigned char i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好//一个字节在DAT里
}
return(dat); //将一个字节数据返回
}
void tmpwritebyte(unsigned char dat)
{ //写一个字节到DS18B20里
unsigned int i;
unsigned char j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) // 写1部分
{
DS=0;
i++;i++;
DS=1;
i=8;while(i>0)i--;
}
else
{
DS=0; //写0部分
i=8;while(i>0)i--;
DS=1;
i++;i++;
}
}
}
void tmpchange(void) //发送温度转换命令
{
dsreset(); //初始化DS18B20
delayb(1); //延时
tmpwritebyte(0xcc); // 跳过序列号命令
tmpwritebyte(0x44); //发送温度转换命令
}
int tmep() //获得温度
{
float tt;
int temp;
unsigned char a,b;
dsreset();
delayb(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe); //发送读取数据命令
a=tmpread(); //连续读两个字节数据
b=tmpread();
temp=b;
temp<<=8;
temp=temp|a; //两字节合成一个整型变量。
tt=temp*0.0625; //得到真实十进制温度值,因为DS18B20
//可以精确到0.0625度,所以读回数据的最低位代表的是
//0.0625度。
temp=tt*10+0.5; //放大十倍,这样做的目的将小数点后第一位
//也转换为可显示数字,同时进行一个四舍五入操作。
return temp; //返回温度值
}
void readrom() //read the serial 读取温度传感器的序列号
{ //本程序中没有用到此函数
unsigned char sn1,sn2;
dsreset();
delayb(1);
tmpwritebyte(0x33);
sn1=tmpread();
sn2=tmpread();
}
void delay10ms()
{
unsigned char a,b;
for(a=10;a>0;a--)
for(b=60;b>0;b--);
}
/***********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -