本系统由AT89C51单片机、DS18B20温度检测部分、DS1302日期时间记录部分、数码管显示部分、按键输入部分和蜂鸣器报警部分组成。该系统通过按键一来调整模式,共五个模式。模式一是DS18B20采集环境温度并保存在存储器中通过单片机将温度显示在数码管上,当温度低于下限或高于上限时蜂鸣器报警;模式二是利用按键二和按键三调整报警的最高温度加减;模式三是利用按键二和按键三调整报警的最低温度加减;模式四是DS1302记录的日期通过单片机显示在数码管上;模式五是DS1302记录的时间通过单片机显示在数码管上。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include <reg52.h>
- #include"intrins.h"
- #define uchar unsigned char
- #define uint unsigned int
- sbit dula = P2^0; //数码管引脚定义
- sbit wela = P2^1;
- sbit DQ = P2^2; //
- sbit key1 = P2^5;
- sbit key2 = P2^6;
- sbit key3 = P2^7;
- sbit buzz = P2^3;
- sbit led = P3^7;
- sbit RST=P1^0;
- sbit DSIO=P1^1;
- sbit SCLK=P1^2; //定义ds1302使用的IO口
- int bai,shi,ge;
- uchar fuhao,flag;
- uint ff,Hff=50,Lff=10;
- uchar count=0,t100ms=0,t500ms,t1s,t2s;
- uchar cishu=0;
- uchar jiange=0;
- uchar biaozhi1=0; //由低于下限到高于下限标志
- uchar biaozhi2=0; //有高于上限到低于上限标志
- uchar biaozhi3=0; //2s长鸣标志
- uchar biaozhi4=0;
- uchar TIMEBCD[7] = {0x00, 0x00, 0x12, 0x1, 0x01, 0x01, 0x18};
- //存储顺序是秒分时日月周年,存储格式是用BCD码
- uchar TIME[7] = {0}; //十进制时间
- //DS1302时钟初始化2018年1月1日星期一12点00分00秒。
- uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
- uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
- //DS1302写入和读取时分秒的地址命令(最低位控制读写)
- unsigned char code table[]={
- 0x3f,0x06,0x5b,0x4f,
- 0x66,0x6d,0x7d,0x07,
- 0x7f, 0x6f};
- unsigned char code table1[]={
- 0xbf,0x86,0xdb,0xcf,
- 0xe6,0xed,0xfd,0x87,
- 0xff, 0xef};
- unsigned char code tablefu[]={
- 0x40, 0x76 , 0x38 , 0x39
- }; //数码管符号 - H L C
- /*延时函数*/
- void delayms(uint xms)
- {
- uint i,j;
- for(i=xms;i>0;i--)
- for(j=114;j>0;j--);
- }
- /*****温度延时*****/
- void Delaywendu(int num)
- {
- while(num--) ;
- }
- /*****初始化DS18B20*****/
- void Init_DS18B20()
- {
- DQ = 1; //DQ复位
- Delaywendu(8); //稍做延时
- DQ = 0; //单片机将DQ拉低
- Delaywendu(80); //精确延时,大于480us
- DQ = 1; //拉高总线
- Delaywendu(40);
- }
- /*****读一个字节*****/
- uchar ReadOneChar()
- {
- uchar i=0;
- uchar dat = 0;
- for (i=8;i>0;i--)
- {
- DQ = 0; // 给脉冲信号
- dat>>=1;
- DQ = 1; // 给脉冲信号
- if(DQ)
- dat|=0x80;
- Delaywendu(4);
- }
- return(dat);
- }
- /*****写一个字节*****/
- void WriteOneChar(uchar dat)
- {
- uchar i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = dat&0x01;
- Delaywendu(5);
- DQ = 1;
- dat>>=1;
- }
- }
- /*****读取温度*****/
- uint ReadTemperature()
- {
- uint a=0,b=0;
- int temp=0;
- float tt=0;
- Init_DS18B20();
- WriteOneChar(0xCC); //跳过读序号列号的操作 1100 1100
- WriteOneChar(0x44); //启动温度转换 0100 0100
- Init_DS18B20();
- WriteOneChar(0xCC); //跳过读序号列号的操作
- WriteOneChar(0xBE); //读取温度寄存器 1011 1110
- a=ReadOneChar(); //读低8位
- b=ReadOneChar(); //读高8位
- temp=b;
- temp<<=8;
- temp=temp|a;
- if(temp&0xf800)
- {
- temp=~temp+1;
- fuhao=1;
- }
- else
- fuhao=0;
- tt=temp*0.0625;
- temp=tt*10+0.5; //放大10倍输出并四舍五入
- return(temp);
- }
- /*****读取温度*****/
- void check_wendu()
- {
- uint f;
- f=ReadTemperature(); //获取温度值并减去DS18B20的温漂误差
- ff=f;
- bai=f/100;
- shi=f %100/10;
- ge= f%10;
- }
- /****读设定值*****/
- void check_v_set(int v_set)
- {
- int bb;
- bb=v_set*10;
- bai=bb/100;
- shi=bb %100/10;
- ge= bb %10;
- }
- /*****显示温度子程序*****/
- void display()
- {
- P0=0xff;
- wela=1;
- P0=0xfb;
- wela=0;
- dula=1;
- P0=table[bai];
- dula=0;
- delayms(5);
- P0=0xff;
- wela=1;
- P0=0xf7;
- wela=0;
- dula=1;
- P0=table1[shi];
- dula=0;
- delayms(5);
-
- P0=0xff;
- wela=1;
- P0=0xef;
- wela=0;
- dula=1;
- P0=table[ge];
- dula=0;
- delayms(5);
-
- P0=0xff;
- wela=1;
- P0=0xdf;
- wela=0;
- dula=1;
- P0=tablefu[3];
- dula=0;
- delayms(5);
- }
- void keyscan()
- {
- if(key1==0)
- {
- delayms(5);
- if(key1==0)
- {
- flag++;
- if(flag==5)
- flag=0;
- while(!key1);
- }
- }
- }
- int keyad(int num)
- {
- if(flag!=0)
- {
- if(key2==0)
- {
- delayms(5);
- if(key2==0)
- {
- num++;
- while(!key2);
- }
- }
- if(key3==0)
- {
- delayms(5);
- if(key3==0)
- {
- num--;
- while(!key3);
- }
- }
- }
- return num;
- }
- /**************************************************************/
- /**************************日历计时部分************************/
- void Ds1302Write(uchar addr, uchar dat) //向DS1302发送命令(地址+数据)
- {
- uchar n;
- RST = 0;
- _nop_();
- SCLK = 0;//先将SCLK置低电平。
- _nop_();
- RST = 1; //然后将RST(CE)置高电平。
- _nop_();
- for (n=0; n<8; n++)//开始传送八位地址命令
- {
- DSIO = addr & 0x01;//数据从低位开始传送
- addr >>= 1;
- SCLK = 1;//数据在上升沿时,DS1302读取数据
- _nop_();
- SCLK = 0;
- _nop_();
- }
- for (n=0; n<8; n++)//写入8位数据
- {
- DSIO = dat & 0x01;
- dat >>= 1;
- SCLK = 1;//数据在上升沿时,DS1302读取数据
- _nop_();
- SCLK = 0;
- _nop_();
- }
-
- RST = 0;//传送数据结束
- _nop_();
- }
- uchar Ds1302Read(uchar addr) //读取一个地址的数据
- {
- uchar n,dat,dat1;
- RST = 0;
- _nop_();
- SCLK = 0;//先将SCLK置低电平。
- _nop_();
- RST = 1;//然后将RST(CE)置高电平。
- _nop_();
- for(n=0; n<8; n++)//开始传送八位地址命令
- {
- DSIO = addr & 0x01;//数据从低位开始传送
- addr >>= 1;
- SCLK = 1;//数据在上升沿时,DS1302读取数据
- _nop_();
- SCLK = 0;//DS1302下降沿时,放置数据
- _nop_();
- }
- _nop_();
- for(n=0; n<8; n++)//读取8位数据
- {
- dat1 = DSIO;//从最低位开始接收
- dat = (dat>>1) | (dat1<<7);
- SCLK = 1;
- _nop_();
- SCLK = 0;//DS1302下降沿时,放置数据
- _nop_();
- }
- RST = 0;
- _nop_(); //以下为DS1302复位的稳定时间
- SCLK = 1;
- _nop_();
- DSIO = 0;
- _nop_();
- DSIO = 1;
- _nop_();
- return dat;
- }
- void Ds1302ReadTime() //读取时钟信息
- {
- uchar n;
- for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
- {
- TIMEBCD[n] = Ds1302Read(READ_RTC_ADDR[n]);
- TIME[n] = TIMEBCD[n]/16*10+TIMEBCD[n]%16;
- }
- }
- void Ds1302Init() // 初始化DS1302
- {
- uchar n;
- Ds1302ReadTime(); //首次读取时间
- if(TIME[5]==0) //判断时间值是否有效
- {
- Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能
- for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
- {
- Ds1302Write(WRITE_RTC_ADDR[n],TIMEBCD[n]);
- }
- Ds1302Write(0x8E,0x80); //打开写保护功能
- }
- }
- void displaytime()
- {
- P0=0xff;
- wela=1;
- P0=0xfe;
- wela=0;
- dula=1;
- P0=table[TIME[2]/10];
- dula=0;
- delayms(5);
- P0=0xff;
- wela=1;
- P0=0xfd;
- wela=0;
- dula=1;
- P0=table1[TIME[2]%10];
- dula=0;
- delayms(5);
-
- P0=0xff;
- wela=1;
- P0=0xfb;
- wela=0;
- dula=1;
- P0=table[TIME[1]/10];
- dula=0;
- delayms(5);
-
- P0=0xff;
- wela=1;
- P0=0xf7;
- wela=0;
- dula=1;
- P0=table1[TIME[1]%10];
- dula=0;
- delayms(5);
- P0=0xff;
- wela=1;
- P0=0xef;
- wela=0;
- dula=1;
- P0=table[TIME[0]/10];
- dula=0;
- delayms(5);
- P0=0xff;
- wela=1;
- P0=0xdf;
- wela=0;
- dula=1;
- P0=table1[TIME[0]%10];
- dula=0;
- delayms(5);
- }
- void displaydate()
- {
- P0=0xff;
- wela=1;
- P0=0xfe;
- wela=0;
- dula=1;
- P0=table[TIME[6]/10];
- dula=0;
- delayms(5);
- P0=0xff;
- wela=1;
- P0=0xfd;
- wela=0;
- dula=1;
- P0=table1[TIME[6]%10];
- dula=0;
- delayms(5);
-
- P0=0xff;
- wela=1;
- P0=0xfb;
- wela=0;
- dula=1;
- P0=table[TIME[4]/10];
- dula=0;
- delayms(5);
-
- P0=0xff;
- wela=1;
- P0=0xf7;
- wela=0;
- dula=1;
- P0=table1[TIME[4]%10];
- dula=0;
- delayms(5);
- P0=0xff;
- wela=1;
- P0=0xef;
- wela=0;
- dula=1;
- P0=table[TIME[3]/10];
- dula=0;
- delayms(5);
- P0=0xff;
- wela=1;
- P0=0xdf;
- wela=0;
- dula=1;
- P0=table1[TIME[3]%10];
- dula=0;
- delayms(5);
- }
- /*主函数*/
- void main()
- {
-
- int z;
- buzz=1; //低电平响,
- led=0;
- TMOD=0x01;//设置定时器0工作模式1
- TH0=(65536-50000)/256;//定时器装初值
- TL0=(65536-50000)%256;
- EA=1; //开总中断
- ET0=1; //开定时器0中断
- Ds1302Init( );
- for(z=0;z<100;z++)
- {
- check_wendu();
- }
- TR0=1;
- while(1)
- {
- keyscan();
- if(flag==0)
- {
- check_wendu();
- if(fuhao==1) //当温度值为负数
- {
- P0=0xff;
- wela=1;
- P0=0xfd;
- wela=0;
- dula=1;
- P0=tablefu[0];
- dula=0;
- delayms(5); //显示负
- }
- else
- {
- P0=0xff;
- wela=1;
- P0=0xfd;
- wela=0;
- dula=1;
- P0=0x00;
- dula=0;
- delayms(5); //显示正
- }
- display();
- }
- else if(flag==1)
- {
- Hff=keyad(Hff);
- check_v_set(Hff);
-
- P0=0xff;
- wela=1;
- P0=0xfe;
- wela=0;
- dula=1;
- P0=tablefu[1];
- dula=0;
- delayms(5); //显示H
- display();
- }
- else if(flag==2)
- {
- Lff=keyad(Lff);
- check_v_set(Lff);
- P0=0xff;
- wela=1;
- P0=0xfe;
- wela=0;
- dula=1;
- P0=tablefu[2];
- dula=0;
- delayms(5); //显示L
- display();
- }
- else if(flag==3)
- {
- Ds1302ReadTime();
- delayms(10);
- displaydate();
- }
- else if(flag==4)
- {
- Ds1302ReadTime();
- delayms(10);
- displaytime();
-
- }
- }
- }
- /*中断函数*/
- void timer0() interrupt 1//定时器0中断服务程序
- {
- TH0=(65536-50000)/256;//再次装定时器初值
- TL0=(65536-50000)%256;
- count++; //中断次数累加 //50毫秒
- // ff=ReadTemperature();
- if(count%2==0)
- {
- t100ms = 1;
- }
- if(count%10==0)
- {
- t500ms = 1;
- }
- if(count%20==0)
- {
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
test1.zip
(156.81 KB, 下载次数: 173)
|