#define uint unsigned int #define uchar unsigned char
sbit rs=\"P2\"^0; // 数据/命令选择端 sbit rw=\"P2\"^1; //读写选择端 sbit e=\"P2\"^2; //使能信号
sbit rst=\"P2\"^5; //时钟芯片复位端 sbit sck=\"P2\"^6; // 时钟信号 sbit io=\"P2\"^7; // 输入/输出端
sbit ds=\"P2\"^3; //温度传感器信号线 sbit led=\"P2\"^4; //小灯位定义 uint temp; // 整型温度值 float f_temp; //浮点型温度值 void init(); // 初始化函数 void delay(uchar z); //延时函数
void write_com(uchar com); //LCD写命令 void write_date(uchar date); //LCD写数据 uint get_temp(); //获得温度
void tempchange(void); //转换温度 void dsreset(void); //DS18B20复位
bit tempreadbit(void); //读DS118B20一位
uchar tempreadbyte(void); //读DS18B20一个字节 void tempwritebyte(uchar dat); void deal(); //温度处理函数
void Write_Ds1302_Byte(uchar temp);//写入一个字节 void Write_Ds1302(uchar address,uchar dat);//写入 uchar Read_Ds1302 ( uchar address ); //读取时间 void Read_RTC(void); //读取 日历 void Set_RTC(void); //设定 日历 void time_date(); //时间数据处理
void display(uchar *lp,uchar lc); //显示时间 void Temp_Display(); //温度显示 uchar table[]=\"01234567.C\"; uchar table0[]=\"01234567-\";
uchar table1[]=\"MONTUEWEDTHUFRISATSUN\"; uchar table2[]=\"01234567:!\";
uchar l_tmpdate[7]={21,59,23,28,10,2,8};
/*初始化时钟芯片,依次是秒分时日月星期年,用十六进制表示十进制,如0x1c表示 1*16+12即28,所以显示出来的就是28*/ uchar l_tmpdisplay[18];
code uchar write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //以上是写入时钟芯片的地址,顺序同上
code uchar read_rtc_address[7]={0x81,0x83,0x85,0x87,0x,0x8b,0x8d}; //读出数据的地址
/******************************日历主函数************************************/ void main() {
init(); //初始化LCD
Set_RTC();//初始化时钟芯片 while(1) {
tempchange();//温度转换命令 time_date();//显示时间 Temp_Display(); //显示温度 deal(); //温度处理
P1=0xf0;
IT0=1; // 选择外部中断0为电平触发方式(1为跳变沿触发方式) EX0=1; EA=\"1\";
} }
void inter0() interrupt 0 //外部中断0 {
P1=0xfe; if(P1!=0xfe)
delay(10); if(P1==0xee) { led=~led;
write_com(0x1c); }
if(P1==0xde) { led=~led;
write_com(0x18); }
}
/***************************以下为温度传感器相关程序************************/
void dsreset(void) //DS18B20复位,初始化函数 {
uint i; ds=0; i=103;
while(i>0)i--; ds=1; i=4;
while(i>0)i--; }
bit tempreadbit(void) //读一位数据函数 {
uint i; bit dat;
ds=0;i++; //i++起延时的作用 ds=1;i++;i++; dat=ds;
i=8;while(i>0)i--; return(dat); }
uchar tempreadbyte(void) //读一个字节数据函数 {
uchar i,j,dat; dat=0;
for(i=1;i<=8;i++) {
j=tempreadbit();
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面 }
return(dat); }
void tempwritebyte(uchar dat) { //写一个字节数据函数 uint i; 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 //写0 {
ds=0;
i=8;while(i>0)i--; ds=1; i++;i++; } } }
void tempchange(void) //DS18B20开始获取温度并转换 {
dsreset(); delay(1);
tempwritebyte(0xcc); //写跳过读ROM指令 tempwritebyte(0x44); //写温度转换指令 }
uint get_temp() //读取寄存器中存储的温度数据 {
uchar a,b; dsreset(); delay(1);
tempwritebyte(0xcc);
tempwritebyte(0xbe); //读RAM内部9字节的温度数据 a=tempreadbyte(); //读低8位 b=tempreadbyte(); //读高8位 temp=b; temp<<=8;
temp=temp|a; //两个字节组合为一个字节
f_temp=temp*0.0625; // 温度在寄存器中为12位,分辨率为0.0625
temp=f_temp*10+0.5; //乘以10表示小数点后面只取1位,加0.5时四舍五入 f_temp=f_temp+0.05; return temp; }
void Temp_Display() //温度显示函数 {
write_com(0x80+0x40+0x0b); write_date(table[get_temp()/100]); write_com(0x80+0x40+0x0c);
write_date(table[get_temp()%100/10]); write_com(0x80+0x40+0x0d); write_date(table[10]);
write_com(0x80+0x40+0x0e); write_date(table[get_temp()%10]); write_com(0x80+0x40+0x0f); write_date(table[11]); }
void deal() //温度处理函数 {
uint i;
i=get_temp();
if(i>300||i<200) //当温度低于20度或大于30度时小灯闪烁 {
led=0;
delay(100); led=1;
// write_com(0x80+12); // write_date(table2[11]); }
// else led=\"1\"; }
/***********************以上为温度传感器相关程序***********************/ /***********************以下为时钟芯片相关程序***********************/ void Write_Ds1302_Byte(uchar temp) //写入一字节数据 {
uchar i;
for (i=0;i<8;i++) //循环8次 写入数据 ,上升沿写入 {
sck=\"0\";
io=\"temp\"&0x01; //每次传输低字节 temp>>=1; //右移一位 sck=\"1\"; } }
void Write_Ds1302(uchar address,uchar dat)//写入 {
rst=0; delay(1); sck=0; delay(1);
rst=1;
delay(1); //启动
Write_Ds1302_Byte(address); //发送地址 Write_Ds1302_Byte(dat); //发送数据 rst=0; //恢复 }
uchar Read_Ds1302 (uchar address) //读取时间 {
uchar i,time=0x00; rst=0; delay(1); sck=0; delay(1); rst=1; delay(1);
Write_Ds1302_Byte(address);
for (i=0;i<8;i++) //循环8次 读取数据 { if(io)
time|=0x80; //每次传输低字节
sck=1; //时钟下降沿读入数据????????? time>>=1; //右移一位 sck=0; }
rst=0;
delay(1); //以下为DS1302复位的稳定时间 rst=0; sck=0; delay(1); sck=1; delay(1); io=0; delay(1); io=1; delay(1);
return (time); }
void Read_RTC() //读取 日历 {
uchar i,*p;
p=read_rtc_address; //地址传递
for(i=0;i<7;i++) //分7次读取 年月日时分秒星期
{
l_tmpdate[i]=Read_Ds1302(*p); p++; } }
void Set_RTC(void) //设定 日历 {
uchar 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); //禁止写入 }
void time_date() //时间数据处理 {
Read_RTC();
l_tmpdisplay[0]=l_tmpdate[2]/16;//时 l_tmpdisplay[1]=l_tmpdate[2]&0x0f; l_tmpdisplay[2]=10; //加入\":\"
l_tmpdisplay[3]=l_tmpdate[1]/16;//分 l_tmpdisplay[4]=l_tmpdate[1]&0x0f; l_tmpdisplay[5]=10;
l_tmpdisplay[6]=l_tmpdate[0]/16;//秒 l_tmpdisplay[7]=l_tmpdate[0]&0x0f;
l_tmpdisplay[8]=2; //显示2008的2
l_tmpdisplay[9]=0; //显示2008的第一个0 l_tmpdisplay[10]=l_tmpdate[6]/16; //年 l_tmpdisplay[11]=l_tmpdate[6]&0x0f; l_tmpdisplay[12]=10; //加入“-”
l_tmpdisplay[13]=l_tmpdate[4]/16;//月 l_tmpdisplay[14]=l_tmpdate[4]&0x0f; l_tmpdisplay[15]=10;
l_tmpdisplay[16]=l_tmpdate[3]/16;//日 l_tmpdisplay[17]=l_tmpdate[3]&0x0f;
display(l_tmpdisplay,8); }
void display(uchar *lp,uchar lc) //显示时间 {
unsigned char i; //定义变量
write_com(0x80); //液晶第一行显示时间和星期 for(i=0;iwrite_date(table2[lp[i]]); delay(1); }write_com(0x80+0x09);
switch(l_tmpdate[5]) //用英文缩写显示星期 {
case 0: write_date(table1[0]); write_date(table1[1]); write_date(table1[2]); break;
case 1: write_date(table1[3]); write_date(table1[4]); write_date(table1[5]); break;
case 2: write_date(table1[6]); write_date(table1[7]); write_date(table1[8]); break;
case 3: write_date(table1[9]); write_date(table1[10]); write_date(table1[11]); break;
case 4: write_date(table1[12]); write_date(table1[13]); write_date(table1[14]); break;
case 5: write_date(table1[15]); write_date(table1[16]); write_date(table1[17]); break;
case 6: write_date(table1[18]);
write_date(table1[19]); write_date(table1[20]); break; }
write_com(0x80+0x40); //第二行显示年 for(i=8;iwrite_date(table0[lp[i]]); delay(1); } }/********************以上为时钟芯片相关程序***************************/ void init() //LCD初始化函数 { e=0;
write_com(0x38);//显示模式的设置 delay(1);
write_com(0x0c);//开显示,光标显示 delay(1);
write_com(0x06);//光标位置 delay(1);
write_com(0x01); //清显示 delay(1); }
void write_com(uchar com) //LCD写命令 { rs=0; rw=0; P0=com; delay(1); e=1; delay(1); e=0; }
void write_date(uchar date) //LCD写数据 { rs=1; rw=0; P0=date; delay(1); e=1; delay(1); e=0; }
void delay(uchar z) //延时函数 {
uchar x,y;
for(x=0;xfor(y=0;y<110;y++); }/***************END***********END******************************/