|
- #include <reg51.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- void delay(unsigned int x)//延时公用程序
- {
- unsigned char i;
- while(x--)
- {
- for(i=0;i<125;i++);
- }
- }
- /********************DS1302部分程序*************************/
- sbit sclk=P3^1;
- sbit rst=P3^0;
- sbit io=P3^2; //DS1302三个管脚定义
- unsigned char time[7]={16,2,12,5,14,28,00};//年周月日时分秒 有符号
- uchar write_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};//DS1302写时间寄存器地址
- uchar read_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};//读
- void write_ds1302_byte(uchar dat) //DS1302写字节函数
- {
- uchar i;
- for(i=0;i<8;i++)
- {
- sclk=0; //下降沿数据有效
- io=dat&0x01;
- dat=dat>>1;
- sclk=1;
- }
- }
- void write_ds1302(uchar add,uchar dat)
- {
- rst=0;
- _nop_();
- sclk=0;
- _nop_();
- rst=1;
- _nop_();
- write_ds1302_byte(add);
- write_ds1302_byte(dat); //发送地址后立即发送数据,没有停顿
- rst=0;
- _nop_();
- sclk=1;
- io=1;
- }
- uchar read_ds1302(uchar add)
- {
- uchar i,dat=0;
- rst=0;
- _nop_();
- sclk=0;
- _nop_();
- rst=1;
- _nop_();
- write_ds1302_byte(add); //发送地址后DS1302立即送出数据
- for(i=0;i<8;i++)
- {
- dat=dat>>1;
- sclk=0;
- if(io)
- dat=dat|0x80;
- sclk=1;
- }
- rst=0;
- _nop_();
- sclk=0;
- _nop_();
- sclk=1;
- io=1;
- return dat;
- }
- void ds1302_init()
- {
- uchar i,j;
- for(i=0;i<7;i++)
- {
- j=time[i]/10;
- time[i]=time[i]%10;
- time[i]=time[i]+j*16; //转换为BCD码
- }
- write_ds1302(0x8e,0x00);//去除写保护
- for(i=0;i<7;i++)
- {
- write_ds1302(write_add[i],time[i]);
- }
- write_ds1302(0x8e,0x80);//加写保护
- }
- void ds1302_set_time(uchar add,uchar dat) //设置DS1302时间
- {
- uchar i;
- i=dat/10;
- dat%=10;
- dat=dat+i*16; //转换十进制为BCD码
- write_ds1302(0x8e,0x00);
- write_ds1302(add,dat);
- write_ds1302(0x8e,0x80);
- }
- void read_time() //读时间
- {
- uchar i;
- for(i=0;i<8;i++)
- {
- time[i]=read_ds1302(read_add[i]);
- time[i]=time[i]/16*10+time[i]%16;//转换BCD码为十进制
- }
- }
- /***********************DS18B20程序********************************/
- sbit DQ=P3^6; //DS18B20数据端
- unsigned int temperature=0;//温度
- unsigned char fuhao=0;//温度的正负符号
- void delay_18B20(unsigned int i)
- {
- while(i--);
- }
- /**********ds18b20初始化函数**********************/
- void Init_DS18B20(void)
- {
- unsigned char x=0;
- DQ = 1; //DQ复位
- delay_18B20(2); //稍做延时
- DQ = 0; //单片机将DQ拉低
- delay_18B20(60); //精确延时 大于 480us
- DQ = 1; //拉高总线
- delay_18B20(2);
- x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
- delay_18B20(15);
- }
- /***********ds18b20读一个字节**************/
- unsigned char ReadOneChar(void)
- {
- unsigned char i=0;
- unsigned char dat = 0;
- for (i=8;i>0;i--)
- {
- DQ = 0; // 给脉冲信号
- dat>>=1;
- DQ = 1; // 给脉冲信号
- if(DQ)
- dat |=0x80;
- delay_18B20(4);
- }
- return(dat);
- }
- /*************ds18b20写一个字节****************/
- void WriteOneChar(unsigned char dat)
- {
- unsigned char i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = dat&0x01;
- delay_18B20(2);
- DQ = 1;
- dat>>=1;
- }
- }
- void ReadTemperature(void)
- {unsigned char readdata[2]={0,0};
- fuhao=0;
- temperature=0;
- delay_18B20(40); // this message is very important
- Init_DS18B20();
- WriteOneChar(0xCC); // 跳过读序号列号的操作
- WriteOneChar(0x44); // 启动温度转换
- delay_18B20(40); // this message is wery important
- Init_DS18B20();
- WriteOneChar(0xCC); //跳过读序号列号的操作
- WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
- delay_18B20(40);
- readdata[0]=ReadOneChar(); //读取温度值低位
- readdata[1]=ReadOneChar(); //读取温度值高位
- if (readdata[1]>127)
- {readdata[0]^=0xff;//求补码
- readdata[1]^=0xff;
- fuhao=1;//符号为“-”
- }
- temperature =readdata[1]*256+readdata[0] ;
- temperature =temperature*0.625+0.5 ;//放大了10倍
- }
- /**********************LCD程序******************************/
- #define LCD_DATA P1
- sbit LCD_RS = P0^0;
- sbit LCD_RW = P0^1;
- sbit LCD_EN = P0^2;
- unsigned char disbuff0[16]={'D',':',' ',
- ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',};//LCD第一行显示日期
- unsigned char disbuff1[16]={'T',':',' ',
- ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',};//LCD第二行显示温度
- void Delay20ms() ;
- void LCD_WriteDat(unsigned char lcd_dat);
- void LCD_WriteCmd(unsigned char lcd_cmd);
- unsigned char LCD_ReadStatus(void);
- void LCD_Goto(unsigned char x,unsigned char y);
- void LCD_Display(unsigned char row,unsigned char *str);
- void Delay20ms() //粗略延时;
- {
- unsigned int tmp = 50000;
- while(tmp--);
- }
- void LCD_Init(void)
- {
- Delay20ms();
- /*************************************************
- 功能设置: DB5=1;DB6...=0;
- DB4=1:8位接口; 0:4位接口;
- DB3=1:双行显示;0:单行显示;
- DB3=1:5×10点阵;0:5×7点阵;
- *************************************************/
- LCD_WriteCmd(0x38); //8位机接口、双行显示、5×7字符点阵;
- /*************************************************
- 显示控制:DB3=1;DB4...=0;
- DB2=1:开启显示;0:关闭LCD显示;
- DB1=1:显示光标;0:光标隐藏;
- DB0=1:光标闪烁;0:光标闪烁关闭;
- *************************************************/
- LCD_WriteCmd(0x0c); //显示开启、光标不显示也不闪烁;
- /*************************************************
- 清屏指令:DB0=1;DB1...=0;
- *************************************************/
- LCD_WriteCmd(0x01); //清屏;
- /****************************************************************
- 访问模式:DB2=1;DB3...=0;
- DB1=1:对内部Ram读写后AC自增,否则自减;
- DB0=1:与DB1设置有关,对DD RAM写时同时整屏移动1位;
- *****************************************************************/
- LCD_WriteCmd(0x06); //光标右移一位、整屏不移动;
- LCD_Goto(0,0);
- }
- void LCD_WriteDat(unsigned char lcd_dat)
- {
- unsigned char tmp;
- tmp = LCD_ReadStatus(); //读状态;
- while((tmp & 0x80)) //是否忙 ?
- {
- tmp = LCD_ReadStatus();
- }
-
- LCD_RS = 1;
- LCD_RW = 0;
- LCD_DATA = lcd_dat;
- _nop_();
- LCD_EN = 0;
- _nop_();
- _nop_();
- LCD_EN = 1;
-
- }
- void LCD_WriteCmd(unsigned char lcd_cmd)
- {
- unsigned char tmp;
- tmp = LCD_ReadStatus();
- while((tmp & 0x80))
- {
- tmp = LCD_ReadStatus();
- }
-
- LCD_RS = 0;
- LCD_RW = 0;
- LCD_DATA = lcd_cmd;
- _nop_();
- LCD_EN = 0;
- _nop_();
- _nop_();
- LCD_EN = 1;
- }
- unsigned char LCD_ReadStatus(void)
- {
- unsigned char tmp;
- #if 0
- LCD_RS = 0;
- LCD_RW = 1;
- LCD_EN = 1;
- tmp = LCD_DATA;
- LCD_EN = 0;
- #endif
- LCD_DATA = 0xff;
- LCD_RS = 0;
- LCD_RW = 1;
- LCD_EN = 0;
- _nop_();
- _nop_();
- LCD_EN = 1;
- tmp = LCD_DATA;
- return tmp;
- }
- void LCD_Goto(unsigned char x,unsigned char y)
- {
- unsigned char tmp;
- if(y) //若是第二行;
- {
- tmp = 0xc0 + x;
- LCD_WriteCmd(tmp);
- }
- else
- {
- tmp = 0x80 + x;
- LCD_WriteCmd(tmp);
- }
- }
-
- void LCD_Display(unsigned char row,unsigned char *str)
- {
- if(row)
- {
- LCD_Goto(0,1);
- }
- else
- {
- LCD_Goto(0,0);
- }
- while(*str != '\0')
- {
- LCD_WriteDat(*str++);
- }
- }
- /*************************按键处理程序********************************/
- uchar hour=0;uchar minute=0;uchar year=0;uchar month=0;uchar date=0;//时间设定
- uchar alarm_hour=0;uchar alarm_minute=0;//闹钟设定时间
- bit at_flag;//闹钟开关标志
- void key()
- {uchar key1=0;uchar key2=0;
- key1=P0;key1=key1>>3;
- delay(75);
- key2=P0;key2=key2>>3;
- if (key1==key2 && key1!=0x1f)
- {switch (key1)
- {case 0x1e://闹钟分设置键
- {while(1)
- {disbuff0[11]='_';disbuff0[12]='_';//显示时
- delay(75);LCD_Display(0,disbuff0);//LCD第一行显示
- disbuff0[11]=alarm_hour/10+'0';disbuff0[12]=alarm_hour%10+'0';//显示时
- delay(75);LCD_Display(0,disbuff0);//LCD第一行显示
- key1=0;key1=P0;key1=key1>>3;
- if (key1==0x1b)//加
- {if (alarm_hour<23)
- {alarm_hour++;}
- else
- {alarm_hour=0;}
- }
- if (key1==0x17)//确定
- {break;}
- }
- }
- case 0x1d://闹钟分设置键
- {while(1)
- {disbuff0[14]='_';disbuff0[15]='_';//显示时
- delay(75);LCD_Display(0,disbuff0);//LCD第一行显示
- disbuff0[14]=alarm_minute/10+'0';disbuff0[15]=alarm_minute%10+'0';//显示时
- delay(75);LCD_Display(0,disbuff0);//LCD第一行显示
- key1=0;key1=P0;key1=key1>>3;
- if (key1==0x1b)//加
- {if (alarm_minute<59)
- {alarm_minute++;}
- else
- {alarm_minute=0;}
- }
- if (key1==0x17)//确定
- {break;}
- }
- }
- case 0x0f://闹钟开关键
- {at_flag=!at_flag;
- }
- default : break;
- }
- }
- }
- /****************蜂鸣器程序**********************/
- sbit speaker=P3^7;
- void timer0() interrupt 1 //这里输出波形
- {TH0=254;//频率为1600hz时计时器初值
- TL0=200;
- speaker=!speaker;
- }
- /********************主程序********************/
- void main()
- {
- ds1302_init();//初始化1302
- LCD_Init();//初始化LCD
- /*计时器0设置*/
- TMOD=0x11;//定时器1、2工作于方式1
- TH0=254;//频率为1600hz时计时器初值
- TL0=200;
- ET0=1;
- EA=0;//关闭总中断
- speaker=0;
- //显示welcome to BJTU
- disbuff0[0]=' ';disbuff0[1]=' ';disbuff0[2]='W';disbuff0[3]='e';disbuff0[4]='l';disbuff0[5]='c';disbuff0[6]='o';disbuff0[7]='m';
- disbuff0[8]='e';disbuff0[9]=' ';disbuff0[10]=' ';disbuff0[11]='t';disbuff0[12]='o';disbuff0[13]=' ';disbuff0[14]=' ';disbuff0[15]=' ';
- disbuff1[0]=' ';disbuff1[1]=' ';disbuff1[6]='Y';disbuff1[7]='O';disbuff1[8]='N';disbuff1[9]='K';disbuff1[10]='0';
- LCD_Display(0,disbuff0);//LCD第一行显示
- LCD_Display(1,disbuff1);//LCD第二行显示
- delay(5000);
- disbuff0[0]='D';disbuff0[1]=':';disbuff0[2]=' ';disbuff0[3]=' ';disbuff0[4]=' ';disbuff0[5]=' ';disbuff0[6]=' ';disbuff0[7]=' ';
- disbuff0[8]=' ';disbuff0[11]=' ';disbuff0[12]=' ';
- disbuff1[0]='T';disbuff1[1]=':';disbuff1[7]=' ';disbuff1[8]=' ';disbuff1[9]=' ';disbuff1[10]=' ';
- while(1)
- {read_time();//获取时间
- year=time[0];//计算年
- month=time[2];//计算月
- date=time[3];//计算日
- hour=time[4];//计算时
- minute=time[5];//计算分
- disbuff0[2]=year/10+'0';disbuff0[3]=year%10+'0';//显示年
- disbuff0[4]='-';disbuff0[5]= month/10+'0';disbuff0[6]= month%10+'0';//显示月
- disbuff0[7]='-';disbuff0[8]= date/10+'0';disbuff0[9]= date%10+'0';//显示日
- disbuff0[10]=' ';disbuff0[11]=hour/10+'0';disbuff0[12]=hour%10+'0';//显示时
- disbuff0[13]=':';disbuff0[14]=minute/10+'0';disbuff0[15]=minute%10+'0';//显示分
- ReadTemperature();//获取温度
- if (fuhao)
- {disbuff1[2]='-';}
- else
- {disbuff1[2]='+';}
- disbuff1[3]=((temperature/1000)%10)+'0';disbuff1[4]=((temperature/100)%10)+'0';disbuff1[5]=((temperature/10)%10)+'0';
- disbuff1[6]='.';disbuff1[7]=((temperature)%10)+'0';disbuff1[8]='C';
- if (at_flag)//显示闹钟开关
- {disbuff1[10]='A';disbuff1[11]='_';disbuff1[12]='O';disbuff1[13]='N';disbuff1[14]=' ';}
- else
- {disbuff1[10]='A';disbuff1[11]='_';disbuff1[12]='O';disbuff1[13]='F';disbuff1[14]='F';}
- key();//按键处理程序
- if (alarm_minute==minute && alarm_hour==hour && at_flag)
- {EA=1;TR0=1;}
- else
- {EA=0;TR0=0;speaker=0;}
- LCD_Display(0,disbuff0);//LCD第一行显示
- LCD_Display(1,disbuff1);//LCD第二行显示
- }
- }
复制代码 |
|