LCD1602显示时间和温度

/*******************************************************************************
* 标题: LCD1602显示时钟 *
* *
* 通过本例程了解 DS1302时钟芯片和LCD1602液晶的基本原理和使用 ,理解并掌握DS1302时钟芯片 *
* *
* 注意:JP1302跳线冒要短接。 *
* 请学员认真消化本例程,懂DS1302在C语言中的操作 *
********************************************************************************/
#include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include


#define uchar unsigned char
#define uint unsigned int
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};

//管脚定义
sbit SCK=P3^6; //DS1302时钟端
sbit SDA=P3^4; //数据端
sbit RST = P3^5; // DS1302复位端

sbit LCD_RW = P2^5; //1602的读写端
sbit LCD_RS = P2^6; //1602的数据命令端
sbit LCD_EN = P2^7; //1602的使能

sbit DQ=P3^7; //DS18b20温度传感器

sbit S1=P1^0; //按键使用
sbit S2=P1^1;
sbit S3=P1^2;
sbit S4=P1^3;


uchar gw,shw,t,R1;
uchar second,minute,hour,date,month,year,week; //定义时间变量






/*************************************************************/
/* */
/* 延时子程序 */
/* */
/*************************************************************/

void delay(uchar x)
{ uchar j;
while((x--)!=0)
{ for(j=0;j<125;j++)
{;}
}
}


void DELAY_US(uint i)
{
while(i--);
}

/*************************************************************/
/* */
/* LCD1602模块 */
/* */
/*************************************************************/

/*************************************************************/
/* */
/*检查LCD忙状态 */
/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据 */
/* */
/*************************************************************/

bit lcd_busy()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delayNOP(); //高电平读出 4us
result = (bit)(P0&0x80);
LCD_EN = 0;
return(result);
}

/*******************************************************************/
/* */
/*写指令数据到LCD

*/
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。 */
/* */
/*******************************************************************/

void lcd_wcom(uchar com)

{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = com;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}

/*******************************************************************/
/* */
/*写显示数据到LCD */
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。 */
/* */
/*******************************************************************/

void lcd_wdat(uchar dat)
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}

/*************************************************************/
/* */
/* LCD初始化设定 */
/* */
/*************************************************************/

void lcd_init()
{
delay(15);
lcd_wcom(0x38); //16*2显示,5*7点阵,8位数据
delay(5);
lcd_wcom(0x38);
delay(5);
lcd_wcom(0x38);
delay(5);

lcd_wcom(0x0c); //显示开,关光标
delay(5);
lcd_wcom(0x06); //移动光标
delay(5);
lcd_wcom(0x01); //清除LCD的显示内容
delay(5);
}
/*************************************************************/
/* */
/* 1602显示字符串 */
/* */
/*************************************************************/
void lcd_word(unsigned char *p)
{while(*p>0)
{ lcd_wdat(*p) ;
p++;
}
}

/*************************************************************/
/* */
/* 1602显示星期子程序 */
/* */
/*************************************************************/

void write_week(uchar week) //写时分秒
{
lcd_wcom(0x80+0x0b);
switch(week)

{ case 1:lcd_word("MON");break;
case 2:lcd_word("TUE");break;
case 3:lcd_word("WED");break;
case 4:lcd_word("THU");break;
case 5:lcd_word("FRI");break;
case 6:lcd_wo

rd("SAT");break;
case 7:lcd_word("SUN");break;

}

}




/******************************************************************/

/* DS1302模块 */

/******************************************************************/



/******************************************************************/
/* 写一个字节 */
/******************************************************************/
void Write_Ds1302_Byte(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++) //循环8次 写入数据
{
SCK=0;
SDA=temp&0x01; //每次传输低字节
temp>>=1; //右移一位
SCK=1;
}
}
/******************************************************************/
/* 写入DS1302 */
/******************************************************************/
void Write_Ds1302( unsigned char address,unsigned char dat )
{
RST=0; //初始复位端为0
_nop_();
SCK=0; //初始时钟线为0
_nop_();
RST=1; //启动
_nop_();
Write_Ds1302_Byte(address); //传输命令字,发送要写入的时间地址
Write_Ds1302_Byte(dat); //发送数据,写入哟啊修改的时间
RST=0; //读取结束,结束数据的传输
}
/******************************************************************/
/* 读出DS1302数据 */
/******************************************************************/
unsigned char Read_Ds1302 ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; //初始复位端为0
_nop_();
_nop_();
SCK=0; //初始时钟线为0
_nop_();
_nop_();
RST=1; //启动
_nop_();
_nop_();
Write_Ds1302_Byte(address);
for (i=0;i<8;i++) //循环8次 读取数据
{
if(SDA)
temp|=0x80; //每次传输低字节
SCK=0;
temp>>=1; //右移一位
_nop_();
_nop_();
_nop_();
SCK=1;
}
RST=0;
_nop_(); //以下为DS1302复位的稳定时间
_nop_();
RST=0;
SCK=0;
_nop_();
_nop_();
_nop_();
_nop_();
SCK=1;
_nop_();
_nop_();
SDA=0;
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
return (temp); //返回
}


//**********温度模块*******
void DS1820RST() //DS18b20的初始化函数
{ uchar x=0;
DQ=1; //DQ复位
DELAY_US(4); //延时
DQ=0; //DQ拉低
DELAY_US(1000); //精确延时大于480us
DQ=1; //拉高
DELAY_US(40);
x=DQ;
}

uchar DS1820RD() //读一个字节
{
uchar i=0,dat=0;
for (i=8;i>0;i--)
{
DQ=0; //给脉冲信号
dat=dat>>1;
DQ=1; //给脉冲信号
if(DQ==1)
dat|=0x80;
DELAY_US(10);
}
return (dat); //写一个字节
}

void DS1820WR(uchar dat)
{

char i=0;
for (i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
DELAY_US(10);
DQ=1;
dat=dat>>1;
}
}
uchar READ_T()
{
uchar a,b;
DS1820RST();
DS1820WR(0xcc);//跳过读序列号(固定)
DS1820WR(0x44);//启动温度转换
DS1820RST();
DS1820WR(0xcc);//跳过读序列号
DS1820WR(0xbe);//读取温度
a=DS1820RD();
b=DS1820RD();
b<<=4;
b+=(a&0xf0)>>4;
t=b;
return (t);
}
//显示温度
void DISP_T()
{ R1=READ_T();
lcd_wcom(0xca);
if(R1<0x81)
{lcd_wdat(0x30+R1/100);}
else
{
R1=~(R1)+1;
lcd_wdat('-');
}

lcd_wdat(0x30+R1%100/10);
lcd_wdat(0x30+R1%10);
lcd_wdat(0xDF);
lcd_wdat('C');

}


/******************************************************************/
/* BCD码转换为十六进制数子程序 */
/******************************************************************/
uchar bcd_decimal(uchar bcd)
{
uchar dec;
dec=bcd>>4;
dec=dec*10+(bcd&=0x0f) ;
return (dec);


}

/******************************************************************/
/* 十六进制 转换为BCD码子程序 */
/******************************************************************/
uchar decimal_bcd(uchar dec)
{
uchar bcd;
bcd=(dec)/10*16+(dec)%10;
return(bcd);

}



/******************************************************************/
/* 时间更新程序 */
/******************************************************************/
void time_update()
{
second=bcd_decimal(Read_Ds1302 ( 0x81 )) ;//读取1302的秒
minute=bcd_decimal(Read_Ds1302 ( 0x83 )) ;//读取1302的分
hour=bcd_decimal(Read_Ds1302 ( 0x85 )) ;//读取1302的小时
date=bcd_decimal(Read_Ds1302 ( 0x87 )) ;//读取1302的日
month=bcd_decimal(Read_Ds1302 ( 0x89 )) ;//读取1302的月
week=bcd_decimal(Read_Ds1302 ( 0x8b )) ;//读取1302的星期
year=bcd_decimal(Read_Ds1302(0x8d)) ;//读取1302的年

//LCD1602显示年-月-日
lcd_wcom(0x80); //显示20
lcd_word("20");
shw=year/10; //显示年
gw=year%10;
lcd_wcom(0x82);
lcd_wdat(0x30+shw);
lcd_wdat(0x30+gw);
lcd_wcom(0x84);
lcd_wdat('-');
shw=month/10; //显示月
gw=month%10;
lcd_wcom(0x85);
lcd_wdat(0x30+shw);
lcd_wdat(0x30+gw);
lcd_wcom(0x87);
lcd_wdat('-');
shw=date/10;
gw=date%10;
lcd_wcom(0x88); //显示日
lcd_wdat(0x30+shw);
lcd_wdat(0x30+gw);

shw=hour/10;//LCD1602显示时:分:秒
gw=hour%10;
lcd_wcom(0xc0);
lcd_wdat(0x30+shw);
lcd_wdat(0x30+gw);
lcd_wcom(0xc2);
lcd_wdat(':');
shw=minute/10;
gw=minute%10;
lcd_wcom(0xc3);
lcd_wdat(0x30+shw);

lcd_wdat(0x30+gw);
lcd_wcom(0xc5);
lcd_wdat(':');
shw=second/10;
gw=second%10;
lcd_wcom(0xc6);
lcd_wdat(0x30+shw);
lcd_wdat(0x30+gw);

write_week(week); //显示星期

}


/******************************************************************/
/* 主程序 */
/******************************************************************/
void main()
{
lcd_init();
while(1)
{DISP_T();
time_update();
}
}


相关文档
最新文档