找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机+DS1302驱动程序时间加减出错

[复制链接]
跳转到指定楼层
楼主
ID:740383 发表于 2020-8-29 14:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
DS1302驱动程序
AIP1722液晶驱动显示
代码如下:
TimeArray[4],TimeArray[5]的加减是否正确,结果出来时TimeArray[4]减到0,再减下去就是95,TimeArray[5]到0时,再减下去显示15;
不知道什么原因,求大神!
  1. /**************************************************  
  2. 单片机-->DS1302时钟模块
  3. SCLK 7 -  P0.5
  4. IO   6 -  P0.4
  5. CE   5 -  P0.3                                                                                                                                                                  
  6. ****************************************************/
  7. #include "n76e003.h"
  8. #include "intrins.h"
  9. #include "Function_Define.h"
  10. #define uchar unsigned char
  11. #define uint  unsigned int
  12. sbit CLK = P1^1  ;            //时钟
  13. sbit CS  = P1^2  ;            //片选
  14. sbit DIN = P1^0  ;            //数据
  15. sbit SCLK= P0^5  ;            //DS1302时钟
  16. sbit DSIO= P0^4  ;            //DS1302数据
  17. sbit RST = P0^3  ;            //DS1302CE
  18. sbit LED = P0^2  ;
  19. sbit K1  = P0^1  ;            //按键1
  20. sbit K2  = P0^0  ;            //按键2
  21. sbit K3  = P1^3  ;            //按键3
  22. sbit K4  = P1^4  ;            //按键4
  23. uchar TimeArray[8]={20,21,5,21,9,20,52,2};//空2020年2月22日8时20分52秒2周 数组:array
  24. uchar ary[8];                             //空年月日时分秒周
  25. uchar Dis[7];
  26. uchar KEY_count=0;
  27. uchar code Table[]={0x5f,0x06,0x6b,0x2f,0x36,0x3d,0x7d,0x07,0x7f,0x3f};//显示数字0-9
  28. uchar code Letter[]={0x01,0x02,0x04,0x08,0x80};                        //地址0xc2单独带字母:SCENT\WORK\PAUSE\EVENT\NULL\NULL\NULL\ON
  29. uchar code Week[]={0x01,0x02,0x04,0x08};                               //地址0xc6单独带字母:THU\FRI\SAT\SUN
  30. uchar code OFF[]={0xDf,0x86,0xeb,0xaf,0xb6,0xbd,0xfd,0x87,0xff,0xbf};  //地址0xc3数字带OFF符号(加0x80)第一数码管
  31. uchar code MON[]={0xDf,0x86,0xeb,0xaf,0xb6,0xbd,0xfd,0x87,0xff,0xbf};  //地址0xcf数字带MON符号(加0x80)第二数码管
  32. uchar code TUE[]={0xDf,0x86,0xeb,0xaf,0xb6,0xbd,0xfd,0x87,0xff,0xbf};  //地址0xce数字带TUE符号(加0x80)第三数码管
  33. uchar code Colon[]={0xDf,0x86,0xeb,0xaf,0xb6,0xbd,0xfd,0x87,0xff,0xbf};//地址0xcb数字带 :符号(加0x80)第四数码管
  34. uchar code WED[]={0xDf,0x86,0xeb,0xaf,0xb6,0xbd,0xfd,0x87,0xff,0xbf};  //地址0xc7数字带WED符号(加0x80)第五数码管
  35. uchar code Week_Address[]={0xcf,0xce,0xc7,0xc6};                       //星期地址,0xc6含星期四、星期五、星期六、星期日
  36. //MON:(0xcf,MON[*])、TUE:(0xce,TUE[*])、WED:(0xc7,WED[*])、THU:(0xc6,0x01)、FRI(0xc6,0x02)、SAT(0xc6,0x04)、SUN(0xc6,0x08)//带字母数字地址及数据
  37. #define sec_add   0x80               //秒寄存器写操作命令字
  38. #define min_add   0x82               //分寄存器写操作命令字
  39. #define hour_add  0x84               //时寄存器写操作命令字
  40. #define day_add   0x86               //日寄存器写操作命令字
  41. #define mon_add   0x88               //月寄存器写操作命令字
  42. #define week_add  0x8a               //周寄存器写操作命令字
  43. #define year_add  0x8c               //年寄存器写操作命令字
  44. #define ctrl_add  0x8e               //控制寄存器写操作命令字
  45. #define cha_add   0x90               //涓流充电寄存器写操作命令字
  46. #define clk_add   0xbe               //时钟突发寄存器写操作命令字
  47. void Delay_xms(uint x)                     
  48. {
  49.                 uint i,j;
  50.                 for(i=x;i>0;i--)
  51.                         for(j=110;j>0;j--);
  52. }
  53. void Write_1722_byte(uchar DATA) //写字节
  54. {
  55.                 uchar i;
  56.                 CS=0;               
  57.                 for(i=8;i>=1;i--)
  58.      {                  
  59.        CLK  = 0;                                                     //时钟拉低,写数据
  60.        DIN  = DATA & 0x01;             //DATA & 10000000,读取最高位写入max7219,最先发送高位(从左往右D7-D0)      
  61.        CLK  = 1;                                                     //时钟拉高,送数据
  62.                          DATA = DATA >> 1;                     //左移1位,重新&运算,读取最高位写入max7219,从右往左写
  63.      }                                 
  64. }
  65. void Write_1722_com(uchar com)   //写指令
  66. {
  67.         CS=0;
  68.         Write_1722_byte(com);
  69.   CS=1;        
  70. }        
  71. void TM1722_Write_Word(uchar addr,uchar dat)  //写数据
  72. {   
  73.   Write_1722_byte(addr);
  74.         Write_1722_byte(dat);
  75.   Delay_xms(10);           
  76.   CS=1;   
  77. }
  78. void Init_1722(void)                                                                                         
  79. {
  80.   TMOD=0x01;                  
  81.         TH0=(65536-50000)/256;      
  82.         TL0=(65536-50000)%256;
  83.         EA=1;                       
  84.         ET0=1;                     
  85.         TR0=1;
  86.         P00_PushPull_Mode;
  87.         P01_PushPull_Mode;
  88.         P02_PushPull_Mode;
  89.         P03_PushPull_Mode;
  90.         P04_PushPull_Mode;
  91.         P05_PushPull_Mode;
  92.         P10_PushPull_Mode;
  93.         P11_PushPull_Mode;
  94.         P12_PushPull_Mode;
  95.         Write_1722_com(0x00);
  96.         Write_1722_com(0x40);
  97.         Write_1722_com(0xc0);
  98.         Write_1722_com(0x97);          //亮度
  99. }
  100. void Init_qingping()             //清屏程序
  101. {
  102.         TM1722_Write_Word(0xc2,0x00);        
  103.         TM1722_Write_Word(0xc3,0x00);
  104.         TM1722_Write_Word(0xc6,0x00);
  105.         TM1722_Write_Word(0xc7,0x00);
  106.         TM1722_Write_Word(0xca,0x00);
  107.         TM1722_Write_Word(0xcb,0x00);
  108.         TM1722_Write_Word(0xce,0x00);
  109.         TM1722_Write_Word(0xcf,0x00);
  110. }
  111. /*************向 DS1302 写入一字节数据***************/
  112. void DS1302_Write_DATA(uchar add, uchar dat)
  113. {
  114.         uchar i;
  115.         RST=1;                        //写入控制字节: add
  116.         add=add&0xfe;                 // 最低位置低
  117.         for(i=0;i<8;i++)              //依次写入控制字的八位
  118.         {
  119.           if(add&0x01)                // 若 add与 0x01 按位与的结果为 0x01(真)
  120.                         DSIO=1;                    //向 DS1302 写入 1
  121.                 else                        //否则若 add 与 0x01 按位与的结果不为 0x01(假)
  122.                         DSIO=0;                    //向 DS1302 写入 0
  123.                 SCLK=1;                      //时钟高电平
  124.                 SCLK=0;                      //时钟低电平
  125.                 add=add>>1;                 //add 依次由高位向低位右移
  126.         }
  127.         for(i=0;i<8;i++) //依次写入数据的八位
  128.         {
  129.                 if(dat&0x01)   //若 dat 与 0x01 按位与的结果为 0x01(真)
  130.                         DSIO=1;       //向 DS1302 写入 1
  131.                 else           //否则若 dat 与 0x01 按位与的结果不为 0x01(假)
  132.                   DSIO=0;       //向 DS1302 写入 0
  133.                 SCLK=1;         //时钟高电平
  134.                 SCLK=0;         //时钟低电平
  135.                 dat=dat>>1;    //dat 依次由高位向低位右移
  136.         }
  137.         RST=0;           //停止 DS1302 总线
  138. }

  139. uchar DS1302_Read_Bit(uchar add)   //从 DS1302 读出一字节数据
  140. {
  141.         uchar i,tem;
  142.         RST=1;                      //写入目标地址: add
  143.         add=add|0x01;               //最低位置高
  144.         for(i=0;i<8;i++)            //依次写入控制字的八位
  145.         {
  146.           if(add&0x01)              //若 add 与 0x01 按位与的结果为 0x01(真)
  147.                         DSIO=1;                 //向 DS1302 写入 1
  148.                 else                      //否则若 add与 0x01 按位与的结果不为 0x01(假)
  149.                         DSIO=0;                 //向 DS1302 写入 0
  150.                 SCLK=1;                   //时钟高电平
  151.                 SCLK=0;                   //时钟低电平
  152.                 add=add>>1;               //add 依次由高位向低位右移
  153.         }
  154.         //输出数据: temp
  155.         for(i=0;i<8;i++)            //依次读出数据的八位
  156.         {
  157.                 tem=tem>>1;               //dat 依次由高位向低位右移
  158.                 if(DSIO)                  //若 SDA=1
  159.                         tem|=0x80;              //就执行 tem 与 0x80 按位或再赋给 tem,取高位的 1
  160.                 else                      //若 SDA=0
  161.                         tem&=0x7f;              //就执行 tem 与 0x7f 按位与再赋给 tem,取高位的 0
  162.                 SCLK=1;                   //时钟高电平
  163.                 SCLK=0;                   //时钟低电平
  164.   }
  165.         RST=0;                      //停止 DS1302 总线
  166.         return tem;                 //返回 tem 的值
  167. }         
  168. /**************向 DS1302 写入时钟数据*******************/
  169. void Write_1302CLK()      
  170. {
  171.         uchar i,tmp;
  172.         for(i=0;i<8;i++)
  173.         {                            //BCD 处理
  174.                 tmp=TimeArray[i]/10;
  175.                 ary[i]=TimeArray[i]%10;
  176.                 ary[i]=ary[i]+tmp*16;      //十进制转换为十六进制,ary[]={0x20,0x11,0x06,0x27,0x13,0x33,0x00,0x01}
  177.         }
  178.         DS1302_Write_DATA(ctrl_add,0x00);   //关闭写保护
  179.         DS1302_Write_DATA(sec_add,0x80);    //暂停
  180.         //DS1302_Write_DATA(cha_add,0xa9);  //涓流充电
  181.         DS1302_Write_DATA(year_add,ary[1]); //年
  182.         DS1302_Write_DATA(mon_add,ary[2]);  //月
  183.         DS1302_Write_DATA(day_add,ary[3]);  //日
  184.         DS1302_Write_DATA(hour_add,ary[4]); //时
  185.         DS1302_Write_DATA(min_add,ary[5]);  //分
  186.         DS1302_Write_DATA(sec_add,ary[6]);  //秒
  187.         DS1302_Write_DATA(week_add,ary[7]); //周
  188.         DS1302_Write_DATA(ctrl_add,0x80);   //打开写保护
  189.   //将ary[]中的年月日时分秒周的十六进制数据写入 DS1302
  190. }
  191. /**********************从 DS1302 读出时钟数据********************************/
  192. void Read_1302CLK()                  
  193. {
  194.         uchar i,tmp;                      //从 DS1302 读出的年月日时分秒周的十六进制数据存入 ary[]
  195.         ary[1]=DS1302_Read_Bit(year_add); //年
  196.         ary[2]=DS1302_Read_Bit(mon_add);  //月
  197.         ary[3]=DS1302_Read_Bit(day_add);  //日
  198.         ary[4]=DS1302_Read_Bit(hour_add); //时
  199.         ary[5]=DS1302_Read_Bit(min_add);  //分
  200.         ary[6]=DS1302_Read_Bit(sec_add);  //秒
  201.         ary[7]=DS1302_Read_Bit(week_add); //周
  202.         
  203.         for(i=0;i<8;i++)                    //BCD 处理
  204.         {                                 
  205.                 tmp=ary[i]/16; //十位
  206.                 TimeArray[i]=ary[i]%16; //个位
  207.                 TimeArray[i]=TimeArray[i]+(tmp*10); //十六进制转换为十进制
  208.         }                                   //将每个十六进制数转换为十进制数存入 TimeArray[]  
  209. }
  210. void Arrange()                               //时间读取处理转换函数
  211. {
  212.         Dis[0]=Table[TimeArray[4]/10];      //时
  213.   Dis[1]=Table[TimeArray[4]%10];         
  214.         Dis[2]=0x40;                        //显示"-"
  215.         Dis[3]=Table[TimeArray[5]/10];      //分
  216.         Dis[4]=Table[TimeArray[5]%10];
  217.         Dis[5]=0x40;
  218.         Dis[6]=Table[TimeArray[6]/10];      //秒
  219.         Dis[7]=Table[TimeArray[6]%10];
  220.         TM1722_Write_Word(0xc3,Dis[7]);//1数码管
  221.         TM1722_Write_Word(0xcf,Dis[0]);//2数码管
  222.         TM1722_Write_Word(0xce,Dis[1]);//3数码管
  223.         TM1722_Write_Word(0xcb,Dis[3]);//4数码管
  224.         TM1722_Write_Word(0xc7,Dis[4]);//5数码管
  225. }
  226. void Standby_Colon(uchar TimeR0,uchar TimeR1)     //调整时间和星期时闪烁
  227. {
  228.         uchar j=0,k=0;
  229.         static uchar display_count=0;
  230.         display_count++;
  231.         if(display_count>120)
  232.         {
  233.                 display_count=1;
  234.         }
  235.         if(KEY_count==1)
  236.         {
  237.                 j=60;
  238.         }
  239.         else if(KEY_count==2)
  240.         {
  241.                 k=60;
  242.         }
  243.         if(display_count>j)
  244.         {
  245.                 TM1722_Write_Word(0xcf,Table[TimeR0/10]);//2数码管
  246.                 TM1722_Write_Word(0xce,Table[TimeR0%10]);//3数码管
  247.                
  248.         }
  249.         else
  250.         {
  251.                
  252.                 TM1722_Write_Word(0xcf,0x00);//2数码管
  253.                 TM1722_Write_Word(0xce,0x00);//3
  254.         }
  255.         if(display_count>k)
  256.         {
  257.                
  258.                 TM1722_Write_Word(0xcb,Table[TimeR1/10]);//4数码管
  259.                 TM1722_Write_Word(0xc7,Table[TimeR1%10]);//5数码管
  260.         }
  261.         else
  262.         {
  263.                 TM1722_Write_Word(0xcb,0x00);//4数码管
  264.                 TM1722_Write_Word(0xc7,0x00);//5
  265.         }
  266. }
  267. void Adjust_Time()
  268. {
  269.         Standby_Colon(TimeArray[4],TimeArray[5]);
  270.         if(KEY_count==0)
  271.         {
  272.                 Arrange();
  273.         }
  274.         if(KEY_count==1)
  275.         {
  276.                
  277.                 if(K3==0||K4==0)
  278.                 {
  279.                         if(!K3)
  280.                         {
  281.                                 TimeArray[4]++;                //小时
  282.                                 while(K3==0||K4==0);
  283.                                 if(TimeArray[4]>=24)
  284.                                 {
  285.                                         TimeArray[4]=0;
  286.                                 }
  287.                         }
  288.                         else if(!K4)
  289.                         {
  290.                                 TimeArray[4]--;
  291.                                 while(K3==0||K4==0);
  292.                                 if(TimeArray[4]<=0)
  293.                                 {
  294.                                         TimeArray[4]=23;
  295.                                 }
  296.                         }
  297.                                 
  298.                 }Write_1302CLK();
  299.         }
  300.         else if(KEY_count==2)
  301.         {
  302.                 if(K3==0||K4==0)
  303.                 {
  304.                         if(!K3)
  305.                         {
  306.                                 TimeArray[5]++;                //分钟
  307.                                 while(K3==0||K4==0);
  308.                                 if(TimeArray[5]>59)
  309.                                 {
  310.                                         TimeArray[5]=0;
  311.                                 }
  312.                         }
  313.                         else if(!K4)
  314.                         {
  315.                                 TimeArray[5]--;
  316.                                 while(K3==0||K4==0);
  317.                                 if(TimeArray[5]<0)
  318.                                 {
  319.                                         TimeArray[5]=59;
  320.                                 }
  321.                         }        
  322.                 }Write_1302CLK();
  323.         }
  324. }
  325. void main()
  326. {        
  327.         Init_1722();
  328.         Init_qingping();               //清屏程序
  329.         Write_1302CLK();
  330.         Read_1302CLK();
  331.         Delay_xms(5);
  332.   while(1)
  333.         {   
  334.                 Read_1302CLK();
  335.                 Adjust_Time();
  336.         }        
  337. }
  338. void timer0() interrupt 1
  339. {
  340.         TH0=(65536-53320)/256;
  341.         TL0=(65536-53320)%256;  
  342.         if(!K2)
  343.         {
  344.                 KEY_count++;
  345.                 while(!K2);
  346.                 if(KEY_count>=3)
  347.                 {
  348.                         KEY_count=0;
  349.                 }
  350.         }
  351. }
复制代码

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

使用道具 举报

沙发
ID:404160 发表于 2020-8-31 11:20 | 只看该作者
uchar TimeArray[8]...
上面变量定义的是无符号“字节”,计数范围是0~255.如果到0后再减1,就是255.(0xff)。所以得数不对
回复

使用道具 举报

板凳
ID:740383 发表于 2020-9-1 17:58 | 只看该作者
飞云居士 发表于 2020-8-31 11:20
uchar TimeArray[8]...
上面变量定义的是无符号“字节”,计数范围是0~255.如果到0后再减1,就是255.(0xf ...

感谢大佬已解决
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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