找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 9283|回复: 4
打印 上一主题 下一主题
收起左侧

51单片机温度控制报警和时间显示程序+Proteus仿真

[复制链接]
跳转到指定楼层
楼主
本系统由AT89C51单片机、DS18B20温度检测部分、DS1302日期时间记录部分、数码管显示部分、按键输入部分和蜂鸣器报警部分组成。该系统通过按键一来调整模式,共五个模式。模式一是DS18B20采集环境温度并保存在存储器中通过单片机将温度显示在数码管上,当温度低于下限或高于上限时蜂鸣器报警;模式二是利用按键二和按键三调整报警的最高温度加减;模式三是利用按键二和按键三调整报警的最低温度加减;模式四是DS1302记录的日期通过单片机显示在数码管上;模式五是DS1302记录的时间通过单片机显示在数码管上。

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #include <reg52.h>
  2. #include"intrins.h"
  3. #define uchar unsigned char
  4. #define uint  unsigned int
  5. sbit dula  = P2^0;        //数码管引脚定义
  6. sbit wela = P2^1;

  7. sbit DQ = P2^2;         //

  8. sbit key1 = P2^5;
  9. sbit key2 = P2^6;
  10. sbit key3 = P2^7;

  11. sbit buzz = P2^3;
  12. sbit led = P3^7;

  13. sbit RST=P1^0;                        
  14. sbit DSIO=P1^1;                        
  15. sbit SCLK=P1^2;                         //定义ds1302使用的IO口

  16. int bai,shi,ge;
  17. uchar fuhao,flag;
  18. uint ff,Hff=50,Lff=10;

  19. uchar count=0,t100ms=0,t500ms,t1s,t2s;
  20. uchar cishu=0;
  21. uchar jiange=0;
  22. uchar biaozhi1=0;  //由低于下限到高于下限标志
  23. uchar biaozhi2=0;  //有高于上限到低于上限标志
  24. uchar biaozhi3=0;  //2s长鸣标志
  25. uchar biaozhi4=0;

  26. uchar TIMEBCD[7] = {0x00, 0x00, 0x12, 0x1, 0x01, 0x01, 0x18};
  27. //存储顺序是秒分时日月周年,存储格式是用BCD码
  28. uchar TIME[7] = {0}; //十进制时间
  29. //DS1302时钟初始化2018年1月1日星期一12点00分00秒。

  30. uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
  31. uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
  32. //DS1302写入和读取时分秒的地址命令(最低位控制读写)

  33. unsigned char code table[]={
  34. 0x3f,0x06,0x5b,0x4f,
  35. 0x66,0x6d,0x7d,0x07,
  36. 0x7f, 0x6f};
  37. unsigned char code table1[]={
  38. 0xbf,0x86,0xdb,0xcf,
  39. 0xe6,0xed,0xfd,0x87,
  40. 0xff, 0xef};
  41. unsigned char code tablefu[]={
  42. 0x40, 0x76 , 0x38 , 0x39
  43. };                        //数码管符号 - H L C
  44. /*延时函数*/
  45. void delayms(uint xms)
  46. {
  47.         uint i,j;
  48.         for(i=xms;i>0;i--)
  49.         for(j=114;j>0;j--);
  50. }
  51. /*****温度延时*****/
  52. void Delaywendu(int num)
  53. {
  54.         while(num--) ;
  55. }
  56. /*****初始化DS18B20*****/
  57. void Init_DS18B20()
  58. {
  59.         DQ = 1;         //DQ复位
  60.         Delaywendu(8);    //稍做延时
  61.         DQ = 0;         //单片机将DQ拉低
  62.         Delaywendu(80);   //精确延时,大于480us
  63.         DQ = 1;         //拉高总线
  64.         Delaywendu(40);
  65. }
  66. /*****读一个字节*****/
  67. uchar ReadOneChar()
  68. {
  69.         uchar i=0;
  70.         uchar dat = 0;
  71.         for (i=8;i>0;i--)
  72.         {
  73.                 DQ = 0;     // 给脉冲信号
  74.                 dat>>=1;
  75.                 DQ = 1;     // 给脉冲信号
  76.                 if(DQ)
  77.                 dat|=0x80;
  78.                 Delaywendu(4);
  79.         }
  80.         return(dat);
  81. }
  82. /*****写一个字节*****/
  83. void WriteOneChar(uchar dat)
  84. {
  85.         uchar i=0;
  86.         for (i=8; i>0; i--)
  87.         {
  88.                 DQ = 0;
  89.                 DQ = dat&0x01;
  90.                 Delaywendu(5);
  91.                 DQ = 1;
  92.                 dat>>=1;
  93.         }
  94. }
  95. /*****读取温度*****/
  96. uint ReadTemperature()
  97. {
  98.   uint a=0,b=0;
  99.   int temp=0;
  100.   float tt=0;
  101.   Init_DS18B20();
  102.   WriteOneChar(0xCC);  //跳过读序号列号的操作  1100 1100
  103.   WriteOneChar(0x44);  //启动温度转换     0100 0100
  104.   Init_DS18B20();
  105.   WriteOneChar(0xCC);  //跳过读序号列号的操作
  106.   WriteOneChar(0xBE);  //读取温度寄存器  1011 1110
  107.   a=ReadOneChar();     //读低8位
  108.   b=ReadOneChar();    //读高8位
  109.   temp=b;
  110.   temp<<=8;
  111.   temp=temp|a;
  112.   if(temp&0xf800)
  113.   {
  114.         temp=~temp+1;
  115.         fuhao=1;
  116.   }
  117.   else
  118.   fuhao=0;
  119.   tt=temp*0.0625;
  120.   temp=tt*10+0.5;     //放大10倍输出并四舍五入
  121.   return(temp);
  122. }

  123. /*****读取温度*****/
  124. void check_wendu()
  125. {
  126.         uint f;
  127.         f=ReadTemperature();                          //获取温度值并减去DS18B20的温漂误差
  128.         ff=f;
  129.         bai=f/100;
  130.     shi=f %100/10;
  131.         ge= f%10;                                       
  132. }
  133. /****读设定值*****/
  134. void check_v_set(int v_set)
  135. {
  136.         int bb;
  137.         bb=v_set*10;   
  138.         bai=bb/100;
  139.     shi=bb %100/10;
  140.         ge= bb %10;                                                               
  141. }
  142. /*****显示温度子程序*****/
  143. void display()
  144. {     

  145.         P0=0xff;
  146.         wela=1;
  147.         P0=0xfb;
  148.         wela=0;
  149.         dula=1;
  150.         P0=table[bai];
  151.         dula=0;
  152.         delayms(5);

  153.         P0=0xff;
  154.         wela=1;
  155.         P0=0xf7;
  156.         wela=0;
  157.         dula=1;
  158.         P0=table1[shi];
  159.         dula=0;
  160.         delayms(5);
  161.         
  162.         P0=0xff;
  163.         wela=1;
  164.         P0=0xef;
  165.         wela=0;
  166.         dula=1;
  167.         P0=table[ge];
  168.         dula=0;
  169.         delayms(5);
  170.                
  171.         P0=0xff;
  172.         wela=1;
  173.         P0=0xdf;
  174.         wela=0;
  175.         dula=1;
  176.         P0=tablefu[3];
  177.         dula=0;
  178.         delayms(5);
  179. }
  180. void keyscan()
  181. {
  182.         if(key1==0)
  183.         {
  184.                 delayms(5);
  185.                 if(key1==0)
  186.                 {
  187.                         flag++;
  188.                         if(flag==5)
  189.                                 flag=0;
  190.                         while(!key1);
  191.                 }
  192.         }
  193. }
  194. int keyad(int num)
  195. {
  196.         if(flag!=0)
  197.         {
  198.                 if(key2==0)
  199.                 {
  200.                         delayms(5);
  201.                         if(key2==0)
  202.                         {
  203.                                 num++;
  204.                                 while(!key2);
  205.                         }
  206.                 }
  207.                 if(key3==0)
  208.                 {
  209.                         delayms(5);
  210.                         if(key3==0)
  211.                         {
  212.                                 num--;
  213.                                 while(!key3);
  214.                         }
  215.                 }        
  216.         }
  217.         return num;
  218. }
  219. /**************************************************************/
  220. /**************************日历计时部分************************/
  221. void Ds1302Write(uchar addr, uchar dat) //向DS1302发送命令(地址+数据)
  222. {
  223.         uchar n;
  224.         RST = 0;
  225.         _nop_();
  226.         SCLK = 0;//先将SCLK置低电平。
  227.         _nop_();
  228.         RST = 1; //然后将RST(CE)置高电平。
  229.         _nop_();

  230.         for (n=0; n<8; n++)//开始传送八位地址命令
  231.         {
  232.                 DSIO = addr & 0x01;//数据从低位开始传送
  233.                 addr >>= 1;
  234.                 SCLK = 1;//数据在上升沿时,DS1302读取数据
  235.                 _nop_();
  236.                 SCLK = 0;
  237.                 _nop_();
  238.         }
  239.         for (n=0; n<8; n++)//写入8位数据
  240.         {
  241.                 DSIO = dat & 0x01;
  242.                 dat >>= 1;
  243.                 SCLK = 1;//数据在上升沿时,DS1302读取数据
  244.                 _nop_();
  245.                 SCLK = 0;
  246.                 _nop_();        
  247.         }        
  248.                  
  249.         RST = 0;//传送数据结束
  250.         _nop_();
  251. }

  252. uchar Ds1302Read(uchar addr) //读取一个地址的数据
  253. {
  254.         uchar n,dat,dat1;
  255.         RST = 0;
  256.         _nop_();

  257.         SCLK = 0;//先将SCLK置低电平。
  258.         _nop_();
  259.         RST = 1;//然后将RST(CE)置高电平。
  260.         _nop_();

  261.         for(n=0; n<8; n++)//开始传送八位地址命令
  262.         {
  263.                 DSIO = addr & 0x01;//数据从低位开始传送
  264.                 addr >>= 1;
  265.                 SCLK = 1;//数据在上升沿时,DS1302读取数据
  266.                 _nop_();
  267.                 SCLK = 0;//DS1302下降沿时,放置数据
  268.                 _nop_();
  269.         }
  270.         _nop_();
  271.         for(n=0; n<8; n++)//读取8位数据
  272.         {
  273.                 dat1 = DSIO;//从最低位开始接收
  274.                 dat = (dat>>1) | (dat1<<7);
  275.                 SCLK = 1;
  276.                 _nop_();
  277.                 SCLK = 0;//DS1302下降沿时,放置数据
  278.                 _nop_();
  279.         }

  280.         RST = 0;
  281.         _nop_();        //以下为DS1302复位的稳定时间
  282.         SCLK = 1;
  283.         _nop_();
  284.         DSIO = 0;
  285.         _nop_();
  286.         DSIO = 1;
  287.         _nop_();
  288.         return dat;        
  289. }

  290. void Ds1302ReadTime()  //读取时钟信息
  291. {
  292.         uchar n;
  293.         for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
  294.         {
  295.                 TIMEBCD[n] = Ds1302Read(READ_RTC_ADDR[n]);
  296.                 TIME[n] = TIMEBCD[n]/16*10+TIMEBCD[n]%16;
  297.         }
  298. }

  299. void Ds1302Init() // 初始化DS1302
  300. {        
  301.         uchar n;
  302.         Ds1302ReadTime();                           //首次读取时间
  303.         if(TIME[5]==0)                                   //判断时间值是否有效
  304.         {
  305.                 Ds1302Write(0x8E,0X00);                 //禁止写保护,就是关闭写保护功能
  306.                 for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
  307.                 {
  308.                         Ds1302Write(WRITE_RTC_ADDR[n],TIMEBCD[n]);        
  309.                 }
  310.                 Ds1302Write(0x8E,0x80);                 //打开写保护功能
  311.         }
  312. }
  313. void displaytime()
  314. {     

  315.         P0=0xff;
  316.         wela=1;
  317.         P0=0xfe;
  318.         wela=0;
  319.         dula=1;
  320.         P0=table[TIME[2]/10];
  321.         dula=0;
  322.         delayms(5);

  323.         P0=0xff;
  324.         wela=1;
  325.         P0=0xfd;
  326.         wela=0;
  327.         dula=1;
  328.         P0=table1[TIME[2]%10];
  329.         dula=0;
  330.         delayms(5);
  331.         
  332.         P0=0xff;
  333.         wela=1;
  334.         P0=0xfb;
  335.         wela=0;
  336.         dula=1;
  337.         P0=table[TIME[1]/10];
  338.         dula=0;
  339.         delayms(5);
  340.                
  341.         P0=0xff;
  342.         wela=1;
  343.         P0=0xf7;
  344.         wela=0;
  345.         dula=1;
  346.         P0=table1[TIME[1]%10];
  347.         dula=0;
  348.         delayms(5);

  349.         P0=0xff;
  350.         wela=1;
  351.         P0=0xef;
  352.         wela=0;
  353.         dula=1;
  354.         P0=table[TIME[0]/10];
  355.         dula=0;
  356.         delayms(5);

  357.         P0=0xff;
  358.         wela=1;
  359.         P0=0xdf;
  360.         wela=0;
  361.         dula=1;
  362.         P0=table1[TIME[0]%10];
  363.         dula=0;
  364.         delayms(5);
  365. }
  366. void displaydate()
  367. {     

  368.         P0=0xff;
  369.         wela=1;
  370.         P0=0xfe;
  371.         wela=0;
  372.         dula=1;
  373.         P0=table[TIME[6]/10];
  374.         dula=0;
  375.         delayms(5);

  376.         P0=0xff;
  377.         wela=1;
  378.         P0=0xfd;
  379.         wela=0;
  380.         dula=1;
  381.         P0=table1[TIME[6]%10];
  382.         dula=0;
  383.         delayms(5);
  384.         
  385.         P0=0xff;
  386.         wela=1;
  387.         P0=0xfb;
  388.         wela=0;
  389.         dula=1;
  390.         P0=table[TIME[4]/10];
  391.         dula=0;
  392.         delayms(5);
  393.                
  394.         P0=0xff;
  395.         wela=1;
  396.         P0=0xf7;
  397.         wela=0;
  398.         dula=1;
  399.         P0=table1[TIME[4]%10];
  400.         dula=0;
  401.         delayms(5);

  402.         P0=0xff;
  403.         wela=1;
  404.         P0=0xef;
  405.         wela=0;
  406.         dula=1;
  407.         P0=table[TIME[3]/10];
  408.         dula=0;
  409.         delayms(5);

  410.         P0=0xff;
  411.         wela=1;
  412.         P0=0xdf;
  413.         wela=0;
  414.         dula=1;
  415.         P0=table1[TIME[3]%10];
  416.         dula=0;
  417.         delayms(5);
  418. }
  419. /*主函数*/
  420. void main()
  421. {
  422.         
  423.         int z;
  424.         buzz=1;         //低电平响,
  425.         led=0;
  426.         TMOD=0x01;//设置定时器0工作模式1
  427.         TH0=(65536-50000)/256;//定时器装初值
  428.         TL0=(65536-50000)%256;
  429.         EA=1; //开总中断
  430.         ET0=1; //开定时器0中断

  431.         Ds1302Init( );
  432.         for(z=0;z<100;z++)
  433.         {
  434.         check_wendu();
  435.         }               
  436.         TR0=1;
  437.         while(1)
  438.         {
  439.                 keyscan();
  440.                 if(flag==0)
  441.                 {
  442.                         check_wendu();
  443.                         if(fuhao==1)                                //当温度值为负数
  444.                           {
  445.                                 P0=0xff;
  446.                                 wela=1;
  447.                                 P0=0xfd;
  448.                                 wela=0;
  449.                                 dula=1;
  450.                                 P0=tablefu[0];
  451.                                 dula=0;
  452.                                 delayms(5);                //显示负
  453.                           }
  454.                          else
  455.                           {                        
  456.                                   P0=0xff;
  457.                                 wela=1;
  458.                                 P0=0xfd;
  459.                                 wela=0;
  460.                                 dula=1;
  461.                                 P0=0x00;
  462.                                 dula=0;
  463.                                 delayms(5);                        //显示正
  464.                         }
  465.                         display();
  466.                 }
  467.                 else if(flag==1)
  468.                 {
  469.                         Hff=keyad(Hff);
  470.                         check_v_set(Hff);
  471.                         
  472.                         P0=0xff;
  473.                         wela=1;
  474.                         P0=0xfe;
  475.                         wela=0;
  476.                         dula=1;
  477.                         P0=tablefu[1];
  478.                         dula=0;
  479.                         delayms(5);                //显示H

  480.                         display();        
  481.                 }
  482.                 else if(flag==2)
  483.                 {
  484.                          Lff=keyad(Lff);
  485.                         check_v_set(Lff);

  486.                         P0=0xff;
  487.                         wela=1;
  488.                         P0=0xfe;
  489.                         wela=0;
  490.                         dula=1;
  491.                         P0=tablefu[2];
  492.                         dula=0;
  493.                         delayms(5);                //显示L

  494.                         display();
  495.                 }
  496.                 else if(flag==3)
  497.                 {
  498.                         Ds1302ReadTime();
  499.                     delayms(10);
  500.                         displaydate();
  501.                 }
  502.                 else if(flag==4)
  503.                 {
  504.                         Ds1302ReadTime();
  505.                     delayms(10);
  506.                         displaytime();
  507.                         
  508.                 }
  509.         }
  510. }
  511. /*中断函数*/
  512. void timer0() interrupt 1//定时器0中断服务程序
  513. {
  514.         TH0=(65536-50000)/256;//再次装定时器初值
  515.         TL0=(65536-50000)%256;
  516.         count++; //中断次数累加         //50毫秒
  517. //        ff=ReadTemperature();
  518.         if(count%2==0)
  519.         {        
  520.                 t100ms = 1;                        
  521.         }
  522.         if(count%10==0)
  523.         {        
  524.                 t500ms = 1;                        
  525.         }
  526.         if(count%20==0)
  527.         {        
  528. ……………………

  529. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
test1.zip (156.81 KB, 下载次数: 173)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:496609 发表于 2019-11-7 15:41 来自手机 | 只看该作者
感谢      
回复

使用道具 举报

板凳
ID:649621 发表于 2019-11-26 09:04 | 只看该作者
感谢!
回复

使用道具 举报

地板
ID:649921 发表于 2019-12-3 15:21 | 只看该作者
。。。。我怎么打不开 仿真图片???
回复

使用道具 举报

5#
ID:651767 发表于 2019-12-4 12:33 | 只看该作者
为啥程序导进去后 仿真数码管会不亮 端口也是灰色 连着数码管的两个 端口也是灰色的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表