找回密码
 立即注册

QQ登录

只需一步,快速开始

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

我的智能仪表课程设计 DS12887程序

[复制链接]
跳转到指定楼层
楼主
内容:以AT89C51单片机为核心,设计一个具有实时时钟功能和温度测量功能的智能化测量仪器。要求具有实时时钟显示和校时功能,温度测量显示功能等。
硬件主要包括DS12887实时时钟电路、555转换电路、8只共阳LED数码管及相应的显示控制和驱动电路、键盘电路等。
编写相程序,编程并控制DS12887芯片,获得日期和时间值;利用按键可实现日期和时间初值的设置,以及测量值、日期和时间的显示切换功能;根据温度与频率的关系显示温度。
做得不好,多包涵。

原理图:


单片机源程序:
  1. #include <reg51.h>
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <absacc.h>
  5. #define uchar unsigned char
  6. #define uint unsigned int
  7. #define sec     XBYTE[0x7f00]
  8. #define seca    XBYTE[0x7f01]
  9. #define min     XBYTE[0x7f02]
  10. #define mina    XBYTE[0x7f03]
  11. #define hour    XBYTE[0x7f04]
  12. #define houra   XBYTE[0x7f05]
  13. #define day     XBYTE[0x7f06]
  14. #define date    XBYTE[0x7f07]
  15. #define month   XBYTE[0x7f08]
  16. #define year    XBYTE[0x7f09]
  17. #define A       XBYTE[0x7f0A]
  18. #define B       XBYTE[0x7f0B]
  19. #define C       XBYTE[0x7f0C]
  20. #define D       XBYTE[0x7f0D]

  21. uchar wendu[8];/*温度数组*/
  22. uchar show[4][8];/*显示数组,第一行存储年月日数据,第二行存储时分秒数据,第三行存储温度和频率数据,第四行存储农历年月日数据*/
  23. uchar Buffer[8];/*中间寄存器*/
  24. uchar weixuan;
  25. uchar page=0;/*显示页面选择*/
  26. uchar shanshuo=0;/*闪烁标志位   初始为不闪烁状态*/
  27. uint nsec,nmin,nhour,nday,ndate,nmonth,nyear;/*更新后时间*/
  28. uint lyear,lmonth,ldate;/*农历年月日*/
  29. uint t1_num,frequency,tempture;/*定时次数 频率 温度*/
  30. uint s3_num=0;/*闪烁(修改)位置选择*/
  31. sbit s2=P1^5;
  32. sbit s3=P1^6;
  33. sbit s4=P1^7;
  34. sbit P3_5=P3^5;/*对T1引脚定义*/
  35. sbit key_on=P3^3;/*对INT1引脚定义*/
  36. uchar code table[13]={               /*数码管段码*/
  37. 0x03,0x9f,0x25,0x0d,0x99,0x49,
  38. 0x41,0x1F,0x01,0x09,0xff,0x39,0x63
  39. };

  40. void delay(uint z);/*延时函数*/
  41. void DS12887_init();/*时钟芯片初始化函数*/
  42. void DS12887_read();/*读时钟芯片函数*/
  43. void DS12887_write();/*写时钟芯片函数*/
  44. void change();/*数据处理函数*/
  45. void display();/*位选及显示函数*/
  46. void T0andT1_init();/*定时器T0,T1初始化函数*/
  47. void int0_init();/*INT0初始化函数*/
  48. void int1_init();/*INT1初始化函数*/
  49. void key_service();/*按键服务函数*/
  50. void flash();/*闪烁函数*/
  51. void add();/*加1函数*/
  52. void nongli();/*农历处理函数*/
  53. void LED_duan(uchar i);/*段选函数*/

  54. void main()
  55. {        
  56.         uint n;
  57.          DS12887_init();/*时间初始化*/
  58.         DS12887_read();
  59.         int0_init();
  60.         T0andT1_init();
  61.         int1_init();
  62.         
  63.         while(1)
  64.         {   
  65.                 change();
  66.                 display();
  67.                 nongli();
  68.                 n++;
  69.                 if(n==20)
  70.                 {
  71.                         shanshuo=!shanshuo;
  72.                     n=0;
  73.                 }/*当循环20次时,闪烁标志位取反,即修改位置的数码管能正常显示对应段码*/
  74.         }
  75. }


  76. /*初始化DS12887*/
  77. void DS12887_init()
  78. {
  79.   B=0x92;/*禁止芯片内部的更新周期操作*/
  80.   A=0x20;/*初始化A寄存器*/
  81.   sec=0x00;
  82.   min=0x30;
  83.   hour=0x08;
  84.   day=0x04;
  85.   date=0x08;        
  86.   month=0x06;        
  87.   year=0x17;/*写入初始时间和日期 2017年6月8日周四 8点30分0秒*/
  88.   ACC=C;
  89.   ACC=D;/*通过读寄存器来清零标志位*/
  90.   B=0x12; /*24小时制,BCD码输出,更新中断允许,芯片工作*/
  91. }

  92. /*读DS12887*/
  93. void DS12887_read()
  94. {
  95.         nsec=(sec/16)*10+sec%16;
  96.         nmin=(min/16)*10+min%16;
  97.         nhour=(hour/16)*10+hour%16;
  98.         nday=(day/16)*10+day%16;
  99.         ndate=(date/16)*10+date%16;
  100.         nmonth=(month/16)*10+month%16;
  101.         nyear=(year/16)*10+year%16;
  102. }

  103. /*写DS12887*/
  104. void DS12887_write()
  105. {
  106.         sec=(nsec/10)*16+nsec%10;
  107.         min=(nmin/10)*16+nmin%10;
  108.         hour=(nhour/10)*16+nhour%10;
  109.         day=(nday/10)*16+nday%10;
  110.         date=(ndate/10)*16+ndate%10;
  111.         month=(nmonth/10)*16+nmonth%10;
  112.         year=(nyear/10)*16+nyear%10;

  113. }

  114. /*延时函数*/
  115. void delay(uint z)
  116. {
  117.         uint x,y;
  118.         for(x=z;x>0;x--)
  119.                 for(y=110;y>0;y--);/*延时z ms*/
  120. }

  121. /*时间数据处理*/
  122. void change()
  123. {

  124.         show[0][0] = 2;
  125.         show[0][1] = 0;
  126.         show[0][2] = nyear/10;
  127.         show[0][3] = nyear%10;
  128.         show[0][4] = nmonth/10;
  129.         show[0][5] = nmonth%10;
  130.         show[0][6] = ndate/10;
  131.         show[0][7] = ndate%10;  

  132.         show[1][0] = nhour/10;
  133.         show[1][1] = nhour%10;
  134.         show[1][2] = nmin/10;
  135.         show[1][3] = nmin%10;
  136.         show[1][4] = nsec/10;
  137.         show[1][5] = nsec%10;
  138.         show[1][6] = 10;
  139.         show[1][7] = nday%10;

  140.         show[2][0] = wendu[0];
  141.         show[2][1] = wendu[1];
  142.         show[2][2] = wendu[2];
  143.         show[2][3] = wendu[3];
  144.         show[2][4] = wendu[4];
  145.         show[2][5] = wendu[5];
  146.         show[2][6] = wendu[6];
  147.         show[2][7] = wendu[7];


  148.         show[3][0] = 2;
  149.         show[3][1] = 0;
  150.         show[3][2] = lyear/10;
  151.         show[3][3] = lyear%10;
  152.         show[3][4] = lmonth/10;
  153.         show[3][5] = lmonth%10;
  154.         show[3][6] = ldate/10;
  155.         show[3][7] = ldate%10;


  156. }

  157. /*段选函数*/
  158. void LED_duan(uchar i)
  159. {
  160.         
  161.         SBUF=table[i];/*段码值先存入缓冲寄存器中*/
  162.         delay(1);/*数据串口传输时间*/
  163.         TI=0;/*数据发送完毕,数据串口传输位清零*/
  164. }


  165. /*位选及显示函数*/
  166. void display()
  167. {
  168.         uchar i;
  169.         weixuan=0xfe;
  170.         for(i=0;i<8;i++)
  171.         {Buffer[i]=show[ page][i];}
  172.         flash();        
  173.          for(i=0;i<8;i++)            /*每次左移选通一位*/
  174.         {  
  175.         
  176.                 P1=weixuan;   
  177.                 LED_duan(Buffer[i]);
  178.                 weixuan=weixuan<<1;     /*位选择,左移一位*/
  179.                 weixuan=weixuan|0x01;
  180.                 if(weixuan==0xff)
  181.                 weixuan=0xfe;
  182.                            
  183.         }        
  184.                         
  185. }

  186. /*外部中断0初始化*/
  187. void int0_init()
  188. {
  189.         SCON = 0x00;/*串口使用方式0*/
  190.          IT0 = 0;/*外部中断0的中断触发方式控制位*/
  191.         EX0 = 1;/*INT0开启*/
  192.         EA = 1;/*CPU开中断*/
  193. }
  194.         


  195. void int0_service() interrupt 0/*外部中断0更新中断*/
  196. {
  197.         if(A==0x20)/*时钟信息可读*/
  198.          {DS12887_read();
  199.           ACC=C;}
  200. }

  201. void T0andT1_init()/*定时器初始化*/
  202. {
  203.         SCON=0x00;/*串口工作方式0*/        
  204.         P3_5 = 0;/*选通温度采集*/
  205.         TMOD=0x15;/*定时器1定时工作方式1,定时器0计数*/
  206.         TH0=0;
  207.         TL0=0;/*计数器装载初值*/
  208.         TH1=(65536-50000)/256;
  209.         TL1=(65536-50000)%256;/*0.05s  定时器装载初值*/
  210.         TR1=1;
  211.         TR0=1;/*定时器启/停控制位置1*/
  212.         ET1=1;/*定时器1溢出中断允许位*/
  213.         EA=1;/*中断允许总控制位*/
  214.         
  215. }


  216. /*定时器中断,采集温度处理*/
  217. void t1_wendu(void) interrupt 3
  218. {
  219.         TR0=0;/*先让T0、T1停止工作*/
  220.         TR1=0;/*启停控制位*/
  221.         P3_5=0;/*选通温度采集*/
  222.         t1_num++;
  223.         if(t1_num==20)/*定时1s*/
  224.         {
  225.                 t1_num = 0;
  226.                 frequency=TH0*256+TL0; /*计数*/
  227.                 tempture=(frequency)*11/62-113; /*温度值转化显示数值*/   
  228.                 wendu[0] = tempture/10;
  229.                 wendu[1] = tempture%10;
  230.                 wendu[2] = 11;
  231.                 wendu[3] = 12;/*摄氏度符号*/
  232.                 wendu[4] = frequency/1000;
  233.                 wendu[5] = frequency%1000/100;
  234.                 wendu[6] = frequency%1000%100/10;
  235.                   wendu[7] = frequency%1000%100%10;
  236.                 TH0=TL0=0;   
  237.         }

  238.         TH1=(65536-50000)/256;
  239.         TL1=(65536-50000)%256;/*定时器重新装载初值*/
  240.         TR0=1;
  241.         TR1=1;
  242. }


  243. void int1_init()
  244. {
  245.         SCON = 0x00;/*串口使用方式0*/
  246.          IT1 = 0;/*外部中断1的中断触发方式控制位*/
  247.         EX1 = 1;/*INT1开启*/
  248.         EA = 1;/*CPU开中断*/
  249. }
  250.         


  251. void int1_service() interrupt 2/*外部中断1判断是否有键按下*/
  252. {
  253.         if(key_on == 0)/*有键按下时执行程序*/
  254.         {
  255.                 delay(10);/*延时10ms,按键消除抖动*/
  256.             if(key_on == 0)
  257.             {
  258.                         key_service();
  259.                            key_on= 1;
  260.                         while(key_on == 0);
  261.                 }
  262.         }
  263. }

  264. void key_service()/*按键服务程序*/
  265. {                                
  266.         if(s2==0)
  267.          {
  268.            page=(page+1)%4; /*page变量代表数码管要显示的内容 page=0数码管显示年月日 page=1数码管显示时分秒 page=2数码管显示温度和频率 page=3数码管显示农历的年月日*/
  269.          
  270.          }

  271.     if(s3==0)
  272.          {         
  273.                 s3_num++;/*8个数码管两两分为4组 s3_num代表闪烁位位置*/
  274.                 if(s3_num==5)
  275.                 s3_num=0;/*不选中数码管*/
  276.          }

  277.      if(s4==0)
  278.         {
  279.                 add();
  280.         }
  281. }

  282. /*闪烁函数*/
  283. void flash()
  284. {        
  285.         
  286.         if((s3_num!=0)&&(page!=2)&&shanshuo==0)
  287.         {
  288.                 Buffer[(s3_num-1)*2]=10;
  289.                 Buffer[(s3_num-1)*2+1]=10;/*对所选中位置的数码管给段码0xff(全灭)*/
  290.         }
  291. }

  292. /*按键加1函数*/
  293. void add()
  294. {
  295.         uint m,n,y,c,w,d;
  296.         if(s4 == 0)/*修改数据程序*/
  297.         {
  298.                 if(page==0)
  299.                 {
  300.                         switch(s3_num)
  301.                         {
  302.                                 case 2: nyear++;
  303.                                         m = nyear;
  304.                                         if(m == 100)/*年变量达到100年*/
  305.                                                 {
  306.                                                         nyear=0;
  307.                                                 }
  308.                                         DS12887_write();
  309.                                         break;

  310.                                 case 3: nmonth++;
  311.                                         m = nmonth;
  312.                                         if(m==13) /*月变量达到12*/
  313.                                         {
  314.                                                         nmonth=1;
  315.                                         }
  316.                                         DS12887_write();
  317.                                         break;

  318.                                 case 4: ndate++;
  319.                                         m = ndate;
  320.                                         if(nmonth==1||nmonth==3||nmonth==5||nmonth==7||nmonth==8||nmonth==10||nmonth==12)
  321.                                         {
  322.                                                         if(m==32) /*大月日变量达到32*/
  323.                                                 {
  324.                                                                 ndate=1;
  325.                                                 }
  326.                                                 }
  327.                                                 if(nmonth==4||nmonth==6||nmonth==9||nmonth==11)
  328.                                         {
  329.                                                         if(m==31) /*小月日变量达到31*/
  330.                                                 {
  331.                                                                 ndate=1;
  332.                                                 }
  333.                                                 }
  334.                                                 if(nmonth==2)
  335.                                         {
  336.                                                         if((nyear%4==0&&nyear%100!=0)||(nyear%400==0))/*闰年*/
  337.                                                         {
  338.                                                                 if(m==30) /*闰年2月日变量达到30*/
  339.                                                             {
  340.                                                                         ndate=1;
  341.                                                             }
  342.                                                                
  343.                                                         }
  344.                                                         else
  345.                                                         {
  346.                                                                 if(m==29)/*非闰年2月日变量达到29*/
  347.                                                                 ndate=1;
  348.                                                         }        
  349.                                         }
  350.                                         DS12887_write();
  351.                                         break;
  352.                                     default: return;
  353.                                        
  354.                                 }
  355.                     /*利用蔡勒公式计算星期*/
  356.                         y=nyear;
  357.                         c=20;
  358.                         n=nmonth;
  359.                         d=ndate;
  360.                         if(n==1||n==2)
  361.                          {
  362.                             y--;
  363.                                 n=n+12;

  364.                          }
  365.                         w=y+y/4+c/4-2*c+13*(n+1)/5+d-1;
  366.                         while(w<0)
  367.                         {w=w+7;}
  368.                         nday=w%7;
  369.                         if(nday==0)
  370.                         nday=7;}
  371.                         DS12887_write();/*通过此段程序可实现星期随年月日的改变而准确变化*/
  372.                    }


  373.                 else if(page==1)
  374.                 {
  375.                         switch(s3_num)
  376.                         {
  377.                                 case 1: nhour++;
  378.                                         m = nhour;
  379.                                         if(m==24) /*小时变量达到24*/
  380.                   
  381.                               …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码


全部资料下载地址:
智能仪表原理图.doc (56 KB, 下载次数: 28)
新建 Microsoft Word 文档.docx (19.47 KB, 下载次数: 50)


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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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