#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
//管腳定義
sbit SCK=P2^1; //DS1302時鐘端
sbit SDA=P2^0; //數據端
sbit RST = P2^4; // DS1302復位端
sbit LCD_RW = P1^1; //1602的讀寫端
sbit LCD_RS = P1^0; //1602的數據命令端
sbit LCD_EN = P2^5; //1602的使能
sbit DQ=P2^2; //DS18b20溫度傳感器
sbit S1=P3^4; //按鍵使用
sbit S2=P3^5;
sbit S3=P3^6;
sbit S4=P3^7;
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_word("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();
write_week ();
}
}
|