找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于STC12C5A60S2系列单片机万年历时钟

[复制链接]
跳转到指定楼层
楼主



完整的设计文档下载:
基于STC12C5A60S2系列单片机万年历时钟.doc (4.54 MB, 下载次数: 26)

  1. /**************************************************/
  2. /*基于STC12C5A60S2系列单片机+595驱动五个数码管+165按键输入
  3.       +1302实时时钟+18B20温度传感器的万年历时钟
  4. 功能键:0xfe:实现温度,时间,年月日,周的转换显示
  5.          0xdf:实现每按一次可以一次更改小时,分,年,月,日,周的闪烁,而
  6.                        实现加减按键对其改变数值
  7.                  0xfb:加功能键,在0xdf有效的情况下才能生效
  8.                  0xfd:减功能键,在0xdf有效的情况下才能生效
  9. 数码管亮度有点不一致,还希望高手能帮忙解决,其他功能都是正常的,也可以给各位爱好单片机的新人们一个互相交流的一段小程序,后面付有图片
  10. */

  11. #include < 12C5A60S2.h >   //头文件
  12. #include < intrins.h >

  13. #define uchar unsigned char           //宏定义
  14. #define uint unsigned int

  15. uchar time_tuf[]={0x14,0x04,0x10,0x12,0x30,0x00,0x5};    //年月日时分秒周
  16. uchar code weima[]={0x20,0x10,0x08,0x04,0x02,0x01};                   //数码管位选
  17. uchar code duan_ma[]={0xee,0x88,0xd6,0xdc,0xb8,0x7c,0x7e,0xc8,0xfe,0xfc};   //数码管段选信号
  18. uchar sec,min,hour,day,month,year,week,num,flag,flag1,flag2,flag3,Flicker,di,x,h;       
  19.                                     //时间变量及标志位变量
  20. uint tt,tvalue;                         //变量
  21. void yueri_work(void);                 //月日显示程序
  22. void nian_work(void);                 //年显示程序
  23. void Show_pass(uchar dss);         //不显示程序
  24. void zhou_work(void);                 //周显示程序
  25. void delay_18B20(uint i);         //温度延时显示程序
  26. void wendu_work(void);                 //温度显示程序
  27. void show_work(void);                 //显示程序
  28. void KEY(void);                                 //按键显示程序

  29. sbit RCLK=P0^2;                   //595输出存储器锁存时钟线 /165装载移位控制锁存信号
  30. sbit SRCLK=P0^0;           //595数据输入时钟线
  31. sbit SER=P0^3;                   //595数据线
  32. sbit SO=P0^4;                   //165数据输出数据线
  33. sbit CLK=P0^1;                   //165时钟信号
  34. sbit RST=P0^5;                   //1302复位引脚,高电平有效
  35. sbit IO=P0^6;                   //1302数据输入输出引脚
  36. sbit SCL=P0^7;                   //1302串行时钟输入,控制数据线的输入输出
  37. sbit DQ=P1^0;                   //18B20数字温度传感器,输入输出口

  38. void Delayms(uint z)                //1毫秒        1T时钟模式下
  39. {
  40.      uint x,y;
  41.          for(x=z;x>0;x--)
  42.           for(y=848;y>0;y--);
  43. }

  44. /********************595驱动程序*********************/
  45. void wr595(uchar date)         //595写入一个字节
  46. {
  47.            uchar i;
  48.         for(i=0;i<8;i++)
  49.          {
  50.              SRCLK=1;
  51.                  SER=date&0x80;
  52.                  date<<=1;
  53.                  SRCLK=0;
  54.          }
  55. }

  56. void send2baty(uchar date1,uchar date2)           //写入双字节程序
  57. {
  58.      wr595(date1);
  59.          wr595(date2);
  60. }

  61. void out595(void)                   //595输出锁存程序
  62. {
  63.     RCLK=0;
  64.         RCLK=1;
  65. }
  66. /****************************************************/

  67. /**************165移位寄存器并转串驱动***************/
  68. uchar series_165()               
  69. {
  70.          uchar i;
  71.          uchar BYTE=1;                         //最终接收到得字符
  72.          RCLK=0;                                    //将165外部端口数据装入内部寄存器
  73.          RCLK=1;                                    //抬高为移位准备
  74.          for(i=0;i<8;i++)
  75.          {
  76.            BYTE<<=1;                            // 1
  77.            CLK=1;                             //时钟低
  78.            BYTE=BYTE|SO;                        //先接收高位
  79.            CLK=0;                            //时钟高,上升沿下一个数据移出                                 
  80.                                              //   5
  81.          }
  82.     return  BYTE;                      //返回接收字符
  83. }
  84. /****************************************************/

  85. /***************18B20数字传感器驱动程序**************/
  86. void delay_18B20(uint i)   //延时1微秒
  87. {
  88.    i=i*12;      //由于我用的是1T 51单片机 如果用普通51请 把这句话屏蔽
  89.    while(i--);
  90. }

  91. void ds1820rst(void)       //ds1820初始化
  92. {
  93.     uchar x=0;
  94.         DQ = 1;            //DQ复位
  95.         delay_18B20(4);   //延时
  96.         DQ = 0;             //DQ拉低
  97.         delay_18B20(100);   //精确延时大于480us
  98.         DQ = 1;              //拉高
  99.         delay_18B20(40);
  100. }

  101. uchar ds1820rd(void)    //读数据
  102. {
  103.    uchar i=0;
  104.    uchar dat = 0;
  105.    for(i=8;i>0;i--)
  106.         {   
  107.             DQ = 0;               //给脉冲信号
  108.             dat>>=1;
  109.             DQ = 1;              //给脉冲信号
  110.             if(DQ)                                //如果DQ==1,执行下面语句
  111.                  {
  112.                 dat|=0x80;
  113.                   }
  114.             delay_18B20(10);
  115.         }
  116.   return(dat);
  117. }

  118. void ds1820wr(uchar wdata)        //写数据
  119. {
  120.     uchar i=0;
  121.     for (i=8; i>0; i--)
  122.      {
  123.              DQ = 0;
  124.              DQ = wdata&0x01;
  125.              delay_18B20(10);
  126.              DQ = 1;
  127.              wdata>>=1;
  128.      }
  129. }

  130. read_temp(void)       //读取温度值并转换
  131. {
  132.         uchar a,b;
  133.         ds1820rst();   
  134.         ds1820wr(0xcc);     //跳过读序列号
  135.         ds1820wr(0x44);    //启动温度转换
  136.         ds1820rst();   
  137.         ds1820wr(0xcc);   //跳过读序列号
  138.         ds1820wr(0xbe);   //读取温度
  139.         a=ds1820rd();
  140.         b=ds1820rd();
  141.         tvalue=b*16+a/16;                 //转换为十进制数
  142.        
  143.         return tvalue;
  144. }

  145. /****************1302实时时钟驱动程序****************/
  146. void write_baty(uchar dat)          //1302写入一个字节
  147. {
  148.           uchar i;
  149.         SCL=0;
  150.         for(i=0;i<8;i++)
  151.          {
  152.             IO=dat&0x01;                         //先写入低位
  153.                 SCL=1;
  154.                 SCL=0;
  155.                 dat>>=1;
  156.          }
  157. }

  158. void write_addbaty(uchar address,uchar dat)         //向1302地址写入一个字节的数据
  159. {
  160.    RST=0;
  161.    SCL=0;
  162.    RST=1;
  163.    write_baty(address);
  164.    write_baty(dat);
  165.    SCL=1;
  166.    RST=0;
  167. }

  168. uchar read_baty(void)              //1302读取一个字节
  169. {
  170.    uchar i,temp;
  171.    for(i=0;i<8;i++)
  172.     {
  173.              temp>>=1;
  174.                  if(IO)
  175.                   {
  176.                      temp=temp|0x80;
  177.                   }
  178.                  else
  179.                   {
  180.                      temp=temp&0x7f;
  181.                   }
  182.                  SCL=1;
  183.                  SCL=0;
  184.         }
  185.   return temp;
  186. }

  187. uchar read_adddaty(uchar address)        //向1302地址读取一个字节的数据
  188. {
  189.    uchar temp;
  190.    RST=0;
  191.    SCL=0;
  192.    RST=1;
  193.    write_baty(address);
  194.    temp=read_baty();
  195.    SCL=1;
  196.    RST=0;

  197.    return temp;
  198. }

  199. void Init_1302time(void)                        //1302初始化
  200. {
  201.          write_addbaty(0x8e,0x00);
  202.          write_addbaty(0x80,time_tuf[5]);
  203.          write_addbaty(0x82,time_tuf[4]);
  204.          write_addbaty(0x84,time_tuf[3]);
  205.          write_addbaty(0x86,time_tuf[2]);
  206.          write_addbaty(0x88,time_tuf[1]);
  207.          write_addbaty(0x8a,time_tuf[6]);
  208.          write_addbaty(0x8c,time_tuf[0]);
  209.          write_addbaty(0x8e,0x80);
  210. }

  211. void read_1302time(void)                 //读1302时间
  212. {
  213.      sec=read_adddaty(0x81);
  214.          min=read_adddaty(0x83);
  215.          hour=read_adddaty(0x85);
  216.          day=read_adddaty(0x87);
  217.          month=read_adddaty(0x89);
  218.          week=read_adddaty(0x8b);
  219.          year=read_adddaty(0x8d);
  220. }
  221. /****************************************************/

  222. /********************定时器0程序*********************/
  223. void Timer0Init(void)                //2毫秒@11.0592MHz         1T时钟模式下
  224. {
  225.         AUXR |= 0x80;                //定时器时钟1T模式
  226.         TMOD |= 0x01;                //设置定时器模式
  227.         TL0 = 0x9A;                //设置定时初值
  228.         TH0 = 0xA9;                //设置定时初值
  229.         TR0 = 1;                //定时器0开始计时
  230.         ET0 = 1;                //定时器0中断打开
  231.         EA = 1;                        //总中断打开
  232. }
  233. void timer0() interrupt 1 using 1
  234. {
  235.     TL0 = 0x9A;                //设置定时初值
  236.         TH0 = 0xA9;                //设置定时初值
  237.         tt++;
  238.         if(tt==500)
  239.          {
  240.             tt=0;
  241.                 x++;
  242.                 if(x==10)          //20毫秒自动跳会无按键时显示
  243.                  {
  244.                     x=0;
  245.                         di=0;
  246.                  }
  247.          }
  248.         if(tt<250)
  249.          {
  250.            Flicker=0;
  251.          }
  252.         else
  253.          {
  254.            Flicker=1;
  255.          }
  256. }

  257. /********************时间调整程序********************/
  258. void set(uchar sel,uchar sal)
  259. {
  260.       uchar address,time;
  261.           uchar max,min;
  262.           if(sel==7)  {address=0x80; max=59;min=0;}     //秒
  263.           if(sel==6)  {address=0x8a; max=7; min=1;}    //星期
  264.           if(sel==2)  {address=0x82; max=59;min=0;}    //分钟
  265.           if(sel==1)  {address=0x84; max=23;min=0;}    //小时
  266.           if(sel==5)  {address=0x86; max=31;min=1;}    //日
  267.           if(sel==4)  {address=0x88; max=12;min=1;}    //月
  268.           if(sel==3)  {address=0x8c; max=99;min=0;}    //年
  269.           
  270.           time=read_adddaty(address+1)/16*10+read_adddaty(address+1)%16;   //时间BCD转换
  271.           if (sal==0) time++;  else time--;
  272.           if(time>max) time=min;   
  273.           if(time<min) time=max;
  274.                    
  275.           write_addbaty(0x8e,0x00);
  276.           write_addbaty(address,time/10*16+time%10);
  277.           write_addbaty(0x8e,0x80);  
  278. }

  279. /**********************显示程序**********************/
  280. void wendu_work(void)
  281. {
  282.      send2baty(0x10,0x00);
  283.          out595();
  284.          Delayms(2);

  285.          send2baty(0x08,0x00);
  286.          out595();
  287.          Delayms(2);

  288.          if(tvalue/10==0x00)
  289.           {
  290.              Show_pass(0x04);
  291.           }
  292.          else
  293.           {
  294.                  send2baty(0x04,duan_ma[tvalue/10]);
  295.                  out595();
  296.                  Delayms(2);
  297.        
  298.                  send2baty(0x02,duan_ma[tvalue%10]);
  299.                  out595();
  300.                  Delayms(2);
  301.          }

  302.          send2baty(0x01,0x66);
  303.          out595();
  304.          Delayms(2);
  305. }

  306. void nian_work(void)
  307. {

  308.     send2baty(0x10,duan_ma[2]);
  309.          out595();
  310.          Delayms(2);

  311.          send2baty(0x08,duan_ma[0]);
  312.          out595();
  313.          Delayms(2);
  314.    if((Flicker==1)&&(di==3))
  315.     {
  316.            Show_pass(0x04);
  317.            Show_pass(0x02);
  318.         }
  319.         else
  320.          {
  321.          send2baty(0x04,duan_ma[year/16]);
  322.          out595();
  323.          Delayms(2);

  324.          send2baty(0x02,duan_ma[year%16]);
  325.          out595();
  326.          Delayms(2);
  327.         }

  328.          send2baty(0x01,0x10);
  329.          out595();
  330.          Delayms(2);
  331. }

  332. void yueri_work(void)
  333. {
  334.   if((Flicker==1)&&(di==4))
  335.    {
  336.        Show_pass(0x10);
  337.            Show_pass(0x08);
  338.    }
  339.   else
  340.    {
  341.             send2baty(0x10,duan_ma[month/16]);
  342.          out595();
  343.          Delayms(2);

  344.          send2baty(0x08,duan_ma[month%16]);
  345.          out595();
  346.          Delayms(2);
  347.    }
  348.          send2baty(0x04,0x10);
  349.          out595();
  350.          Delayms(2);

  351.   if((Flicker==1)&&(di==5))
  352.         {
  353.            Show_pass(0x02);
  354.            Show_pass(0x01);
  355.         }
  356.    else
  357.     {
  358.          send2baty(0x02,duan_ma[day/16]);
  359.          out595();
  360.          Delayms(2);

  361.          send2baty(0x01,duan_ma[day%16]);
  362.          out595();
  363.          Delayms(2);
  364.     }
  365. }

  366. void zhou_work(void)
  367. {
  368.      send2baty(0x10,0x10);
  369.          out595();
  370.          Delayms(2);

  371.          send2baty(0x08,0x10);
  372.          out595();
  373.          Delayms(2);

  374.         if((Flicker==1)&&(di==6))
  375.          {
  376.              Show_pass(0x04);
  377.          }
  378.         else
  379.          {
  380.                  send2baty(0x04,duan_ma[week%16]);
  381.                  out595();
  382.                  Delayms(2);
  383.          }

  384.          send2baty(0x02,0x10);
  385.          out595();
  386.          Delayms(2);

  387.          send2baty(0x01,0x10);
  388.          out595();
  389.          Delayms(2);
  390. }

  391. void show_work(void)
  392. {
  393.    if((num==0)&&(di==0))
  394.      {
  395.             wendu_work();
  396.          }

  397.    if((num==1)&&(di==0)||(di>=1)&&(di<=2))
  398.          {
  399.             if((Flicker==1)&&(di==1))
  400.                  {
  401.                      Show_pass(0x10);
  402.                          Show_pass(0x08);
  403.                  }
  404.             else
  405.                  {
  406.                          send2baty(0x08,duan_ma[hour%16]);
  407.                          out595();
  408.                          Delayms(2);
  409.                
  410.                          send2baty(0x10,duan_ma[hour/16]);
  411.                          out595();
  412.                          Delayms(2);
  413.                   }
  414.                 if((Flicker==1)&&(di==2))
  415.                  {
  416.                      Show_pass(0x02);
  417.                          Show_pass(0x01);
  418.                  }
  419.                 else
  420.                  {
  421.                          send2baty(0x02,duan_ma[min/16]);
  422.                          out595();
  423.                          Delayms(2);
  424.        
  425.                      send2baty(0x01,duan_ma[min%16]);
  426.                          out595();
  427.                          Delayms(2);
  428.                  }
  429.        
  430.                  send2baty(0x04,0x10);
  431.                  out595();
  432.                  Delayms(2);
  433.          }

  434.     if((num==2)&&(di==0)||(di==3))
  435.          {
  436.             nian_work();
  437.          }

  438.         if((num==3)&&(di==0)||(di>=4)&&(di<=5))
  439.          {
  440.            yueri_work();
  441.          }

  442.         if((num==4)&&(di==0)||(di==6))
  443.          {
  444.             zhou_work();
  445.          }
  446. }
  447. /****************************************************/

  448. /**********************不显示程序********************/
  449. void Show_pass(uchar dss)
  450. {
  451.      send2baty(dss,0x00);
  452.          out595();
  453.          Delayms(1);
  454. }

  455. /********************按键处理程序********************/
  456. void KEY(void)
  457. {
  458.     uchar key;
  459.         key=series_165();
  460.         if(key==0xdf)
  461.          {
  462.            Delayms(1);
  463.            if(key==0xdf)
  464.             {
  465.                   flag1=1;
  466.                 }
  467.          }
  468.         else
  469.          {
  470.             if(flag1==1)
  471.                  {
  472.                     flag1=0;
  473.                         di++;
  474.                         if(di==7)
  475.                          {
  476.                             di=0;
  477.                          }
  478.                  }
  479.       }

  480.         if(di!=0)
  481.          {
  482.             if(key==0xfb)
  483.                  {
  484.                     Delayms(1);
  485.                         if(key==0xfb)
  486.                          {
  487.                                     flag2=1;
  488.                          }
  489.                  }
  490.                 else
  491.                  {
  492.                     if(flag2==1)
  493.                          {
  494.                             flag2=0;
  495.                            set(di,0);
  496.                          }
  497.                  }
  498.                 if(key==0xfd)
  499.                  {
  500.                     Delayms(1);
  501.                         if(key==0xfd)
  502.                          {
  503.                             flag3=1;
  504.                          }
  505.                  }
  506.                 else
  507.                  {
  508.                    if(flag3==1)
  509.                     {
  510.                           flag3=0;
  511.                           set(di,1);
  512.                         }
  513.                  }
  514.          }
  515.         else
  516.          {

  517.         if(key==0xfe)
  518.          {
  519.            Delayms(1);
  520.            if(key==0xfe)
  521.             {
  522.                     flag=1;
  523.                 }
  524.          }
  525.         else
  526.          {
  527.             if(flag==1)
  528.                  {
  529.                     flag=0;
  530.                         num++;
  531.                         if(num==5)
  532.                          {
  533.                            num=0;
  534.                          }
  535.              }
  536.          }
  537.         }
  538. }

  539. /**********************主程序************************/
  540. void main(void)                  //主函数
  541. {
  542.    Timer0Init();
  543.    ds1820rst();
  544.    Init_1302time();
  545.    while(1)
  546.     {
  547.            read_1302time();
  548.            read_temp();
  549.            KEY();
  550.            show_work();
  551.         }
  552. }




复制代码


评分

参与人数 1黑币 +5 收起 理由
1991660756 + 5

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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