找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机万年历带温度检测仿真

[复制链接]
跳转到指定楼层
楼主
万年历的简易设计与仿真
电路原理图如下:


单片机源程序如下:
  1. #include<reg52.h>
  2. #include<intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int

  5. /***********定义LCD功能管脚************************************/
  6. sbit rs=P2^0;                //控制LCD数据或命令的读写
  7. sbit rw=P2^1;                //控制LCD读写信号
  8. sbit e=P2^2;                //使能LCD

  9. /***********定义DS1302功能管脚*********************************/
  10. sbit DSRST = P1^0;      //DS1302复位管脚
  11. sbit DSCLK = P1^1;      //DS1302时钟
  12. sbit DSIO = P1^2;       //控制DS1302数据传输
  13. sbit dq=P3^7;                    //温度传感器I/O口定义

  14. uint  numh=110,numl=50;   //上下限温度
  15. uchar bai,shi,ge,xiaoshu,fuhao;
  16. uchar th_temp,tl_temp;
  17. uchar secondh,secondl,minuteh,minutel,hourh,hourl,second,minute,hour;
  18. uint  monthl,monthh,month,day,datel,dateh,date,year,yearl,yearh;
  19. void delay_ms(uint z);
  20. void delay_us(uchar z);

  21. void lcd1602_init();
  22. bit judge_lcd();
  23. void write_com(uchar com);
  24. void write_date(uchar date);
  25. void HELLO_lcd();

  26. void ds18b20_init();
  27. void write_byte(uchar dat);
  28. uchar read_byte();
  29. void display();
  30. void convert_temp();
  31. void beyond();

  32. void ds1302_init();
  33. uchar read_ds1302();
  34. void init_ds1302();
  35. void write_ds1302() ;
  36. void read1302_write1602 ();
  37. void HELLO();

  38. /*********************延时函数*****************/
  39. void delay_us(uchar z)
  40.   {
  41.     while(z--);
  42.   }


  43. void delay_ms(uint z)
  44.   {
  45.     uint  x,y;
  46.     for(x=z;x>0;x--)
  47.     for(y=110;y>0;y--);
  48.   }



  49. /********************lcd1602初始化***************************/
  50. void lcd1602_init()
  51.   {
  52.     write_com(0x01);
  53.     delay_ms(50);
  54.     write_com(0x38);
  55.     delay_ms(50);
  56.     write_com(0x0c);
  57.     delay_ms(50);
  58.     write_com(0x06);       
  59.     delay_ms(50);
  60.   }


  61. /***********************lcd1602忙碌判断子程序*******************/
  62. bit judge_lcd()
  63.   {
  64.     bit flag;
  65.     e = 0;
  66.     rs = 0;
  67.     rw = 1;
  68.     e = 1;
  69.     delay_ms(1);
  70.     flag=(bit)(P0&0x80);    //状态位第7位为1时禁止读写,为0时可读写
  71.     e = 0;
  72.     return flag;       
  73.   }


  74. /**********************lcd1602写指令子程序*******************/
  75. void write_com(uchar addr)
  76.   {
  77.                                             
  78.     while(judge_lcd());    //检测LCD是否为忙碌状态
  79.     rs=0;
  80.     rw=0;
  81.     P0=addr;
  82.     delay_us(5);
  83.     e=0;
  84.     delay_us(5);
  85.     e=1;
  86.     delay_us(5);
  87.     e=0;
  88.   }


  89. /***********************lcd写数据子程序*******************/
  90. void write_date(uchar date)
  91.   {
  92.     while(judge_lcd());    //检测LCD是否为忙碌状态
  93.     rs=1;
  94.     rw=0;
  95.     P0=date;
  96.     delay_us(5);
  97.     e=0;
  98.     delay_us(5);
  99.     e=1;
  100.     delay_us(5);
  101.     e=0;
  102.   }



  103. /***********lcd1602写指令及数据********************************/
  104. void write_com_date(uint addr,uint date)
  105.   {
  106.     write_com(addr);
  107.     delay_ms(1);
  108.     write_date(date);
  109.   }


  110. /************************DS18B20初始化************************/
  111. void ds18b20_init()
  112.   {
  113.     dq=1;
  114.     delay_us(2);
  115.     dq=0;
  116.     delay_us(80);
  117.     dq=1;
  118.     delay_us(2);
  119.     delay_us(40);
  120.   }


  121. /************************ds18b20写数据子程序**********************/
  122. void write_byte(uchar dat)
  123.   {
  124.     uchar i,value;
  125.     dq=1;
  126.     for(i=0;i<8;i++)
  127.       {
  128.             dq=0;
  129.                 value=dat&0x01;
  130.                 if(value==0)
  131.                   {
  132.                     dq=0;
  133.                     delay_us(10);
  134.                   }
  135.                 else
  136.                   {
  137.                     dq=1;
  138.                     delay_us(10);
  139.                   }
  140.                 dq=1;
  141.                 dat=dat>>1;
  142.           }
  143.   }


  144. /************************ds18b20读数据子程序*********************/
  145. uchar read_byte()
  146.   {
  147.     uchar i, value;
  148.         dq=1;
  149.     for(i=0;i<8;i++)
  150.           {
  151.             dq=0;
  152.                 value=value>>1;
  153.                 dq=1;
  154.                 delay_us(1);
  155.                 if(dq==1)
  156.                 value=value|0x80;       
  157.                 delay_us(10);
  158.           }
  159.     return value;
  160.   }





  161. /**********************DS1302读数据子程序********************************/
  162. uchar read_ds1302(uchar addr)
  163.   {
  164.     uchar i,temp=0x00;
  165.         DSRST=0;
  166.         DSIO=1;
  167.         DSCLK=0;
  168.         DSRST=1;
  169.     for (i=0;i<8;i++)      //循环8次 写入地址数据
  170.           {
  171.                DSCLK=0;
  172.                 DSIO=addr&0x01;    //每次传输低字节
  173.              addr>>=1;          //右移一位
  174.              DSCLK=1;
  175.           }
  176.         delay_ms(1);
  177.         if(DSIO)
  178.           temp|=0x80;          //每次传输低字节
  179.         DSCLK=0;
  180.         temp>>=1;
  181.         for (i=0;i<7;i++)     //循环8次 读取数据
  182.           {
  183.                 DSCLK=0;
  184.                 if(DSIO)
  185.               temp|=0x80;     //每次传输低字节
  186.                 DSCLK=1;
  187.                 temp>>=1;         //右移一位
  188.           }
  189.     DSCLK=1;
  190.         DSRST=0;
  191.         DSIO=0;
  192.         return temp;         //返回
  193.   }


  194. /******************ds1302写指令子程序**********************************/

  195. void write_ds1302(uchar addr, uchar date)
  196.   {
  197.     uchar i;
  198.            DSRST=0;
  199.         DSCLK=0;
  200.         DSRST=1;       
  201.     for (i=0;i<8;i++)      //循环8次 写入地址数据
  202.           {
  203.         DSCLK=0;
  204.         _nop_();
  205.                 DSIO=addr&0x01;   //每次传输低字节
  206.              addr>>=1;         //右移一位
  207.              DSCLK=1;
  208.         _nop_();
  209.           }
  210.         for (i=0;i<8;i++)    //循环8次 写入数据
  211.           {
  212.                DSCLK=0;
  213.         _nop_();
  214.                 DSIO=date&0x01;  //每次传输低字节
  215.              date>>=1;        //右移一位        DSCLK=1
  216.                 DSCLK=1;
  217.         _nop_();
  218.           }
  219.         DSRST=0;
  220.         delay_ms(1);
  221.   }



  222. /*****************ds1302初始化子程序********************************/
  223. void ds1302_init()
  224.   {
  225.     if((((second=read_ds1302(0x81))>>7)&&0x01)==1)    //读秒
  226.           {
  227.             write_ds1302(0x8e,0x00);    //关闭写保护
  228.             write_ds1302(0x80,0x00);    //00秒
  229.             write_ds1302(0x82,0x54);    //54分
  230.             write_ds1302(0x84,0x17);    //17点
  231.             write_ds1302(0x86,0x08);    //8日
  232.             write_ds1302(0x88,0x06);    //6月
  233.             write_ds1302(0x8a,0x05);    //星期五
  234.             write_ds1302(0x8c,0x12);    //2012年
  235.             write_ds1302(0x8e,0x80);    //允许写保护
  236.           }
  237.   }


  238. /*****************************温度转化与LCD显示部分****************************/
  239. void convert_temp()
  240.   {          
  241.     uint temp_zhen;
  242.     uchar temp_fu;
  243.     ds18b20_init();
  244.     write_byte(0xcc);
  245.         write_byte(0x44);
  246.         delay_ms(300);
  247.         ds18b20_init();
  248.         write_byte(0xcc);
  249.         write_byte(0xbe);
  250.     tl_temp=read_byte();
  251.         th_temp=read_byte();

  252.         if((th_temp&0xf0)!=0xf0)
  253.           {   
  254.             fuhao=0x2b;                                   //正数处理
  255.         temp_zhen=th_temp*256+tl_temp;
  256.             temp_zhen=temp_zhen/16;
  257.                 temp_zhen=((tl_temp&0xf0)>>4)|(th_temp<<4);
  258.         bai=temp_zhen/100;                           //将十进制的每一位都拆开
  259.                 shi=temp_zhen/10%10;
  260.                   ge=temp_zhen%10;
  261.         xiaoshu=(tl_temp&0x0f)*10*0.0625;
  262.           }
  263.         else
  264.       {
  265.             fuhao=0x2d;                                    //负数处理
  266.                 temp_fu=((tl_temp&0xf0)>>4)|(th_temp<<4);
  267.                 temp_fu=~temp_fu;
  268.                 if((tl_temp&0x0f)==0x00)
  269.                   {
  270.                     temp_fu=temp_fu+1;
  271.           }
  272.                  bai=temp_fu/100;
  273.          shi=temp_fu/10%10;
  274.              ge=temp_fu%10;
  275.              xiaoshu=((~(tl_temp&0x0f)&0x0f)+1)*10*0.0625;       
  276.                  xiaoshu=xiaoshu%10;                                  //精确到小数点后一位
  277.            }


  278.         if(temp_zhen>numh|temp_fu>numl)
  279.           {
  280.             beyond();
  281.           }          
  282.   }



  283. /**********************lcd1602温度显示子程序*********************/
  284. void display()
  285.   {
  286.     write_com(0xCa);
  287.     write_date(fuhao);
  288.     if(bai!=0)                                      //百位为0不显示
  289.           {
  290.             write_date(bai+0x30);
  291.             write_date(shi+0x30);
  292.           }
  293.     else if(bai==0&&shi!=0)
  294.           {
  295.             write_date(shi+0x30);
  296.           }
  297.     write_date(ge+0x30);
  298.     write_date(0x2e);
  299.     write_date(xiaoshu+0x30);
  300.     write_date(0x43);
  301.     write_date(0x20);
  302.   }


  303. /**********************初始欢迎界面函数************************/
  304. void HELLO()
  305.   {       
  306.             
  307.         write_com_date(0x85,'H');
  308.             write_com_date(0x86,'E');
  309.             write_com_date(0x87,'L');
  310.             write_com_date(0x88,'L');
  311.             write_com_date(0x89,'O');
  312.         write_com_date(0xc4,'E');
  313.             write_com_date(0xc5,'V');
  314.             write_com_date(0xc6,'E');
  315.             write_com_date(0xc7,'R');
  316.         write_com_date(0xc8,'Y');
  317.             write_com_date(0xc9,'O');
  318.         write_com_date(0xca,'N');
  319.         write_com_date(0xcb,'E');
  320.         delay_ms(1500);
  321.   }



  322. /********************超过温度上下限子程序***********************/
  323. void beyond()
  324.   {  
  325.     uint temp_zhen;
  326.     uchar temp_fu;
  327.     while(1)
  328.      {
  329.        write_com(0xCA);
  330.        write_date('0');
  331.            write_date('0');
  332.            write_date('0');
  333.            write_date('0');
  334.            write_date('0');
  335.            write_date('0');          
  336.        read1302_write1602();
  337.            if(temp_zhen<=numh||temp_fu<=numl)
  338.              break;
  339.      }
  340.   }         



  341. /************************从ds1302中读时间并在LCD1602上显示***************************/
  342. void read1302_write1602 ()
  343.   {
  344.     second=read_ds1302(0x81);
  345.     secondl=second&0x0f;
  346.     secondh=second>>4;
  347.     minute=read_ds1302(0x83);
  348.         minutel=minute&0x0f;
  349.         minuteh=minute>>4;
  350.         hour=read_ds1302(0x85);
  351.         hourl=hour&0x0f;
  352.         hourh=hour>>4;       
  353.     month=read_ds1302(0x89);
  354.         monthl=month&0x0f;
  355.         monthh=month>>4;
  356.         year=read_ds1302(0x8d);
  357.         yearl=year&0x0f;
  358.         yearh=year>>4;
  359.     date=read_ds1302(0x87);
  360.         datel=date&0x0f;
  361.         dateh=date>>4;
  362.     day=read_ds1302(0x8b);
  363.         day=day&0x0f;
  364.         delay_ms(5);

  365.         write_com_date(0xc7,0x30+secondl);
  366.     write_com_date(0xc6,0x30+secondh);
  367.     write_com_date(0xc5,'-');
  368. ……………………

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

所有资料51hei提供下载:
rl.zip (123 KB, 下载次数: 44)


评分

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

查看全部评分

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

使用道具 举报

沙发
ID:247623 发表于 2019-8-26 10:15 | 只看该作者
不错,星期也是准的,不过时钟频率不够准确,比现实时间稍微慢一点
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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