找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2373|回复: 44
收起左侧

单片机DS1302驱动与转换数据以及时序观察问题

[复制链接]
ID:332444 发表于 2022-12-23 15:06 | 显示全部楼层 |阅读模式
录像只写了读取秒钟
录像34_转.gif
观察时序电路仿真示波器可以看到全部,编程仿真无法看到读取数据时的IO状态。

1.png
在这里只看看DS1302驱动和数据转换部分代码,数码管驱动同以往帖子。

无标题1.png

评分

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

查看全部评分

回复

使用道具 举报

ID:332444 发表于 2023-1-3 14:29 | 显示全部楼层
如果哪位能写出全篇不调用独占计数延时的代码我有奖,奖励黑币.
这图演示的就是除了2个1302函数有独占循环读/写8次外,整篇都不用独占计数延时的荔枝,包括数码管显示都不再使用独占计数延时的高级应用.
1.gif
回复

使用道具 举报

ID:624769 发表于 2023-1-3 20:47 来自手机 | 显示全部楼层
虽然不知道你说的独占计数是啥东西,如果仅仅是指延时的话,直接用串口1模式0,就好了,不光不需要延时,连循环读IO都不用了,直接写一次sbuf,读一次sbuf即可,当然我更喜欢用burst一次把秒分时都读出来。
回复

使用道具 举报

ID:401564 发表于 2023-1-3 23:43 | 显示全部楼层
"独占计数延时"
"独占循环读"
不要自己创造名词,尽量用大家都能理解的词汇
这个仿真一点意义都没有,仿真行,实际电路不一定行,到了实际电路还是得重新调试,那么,这个仿真有什么意义?
对于时序,你也不一定能看得明白,自己找一个开发板,点两下烧录验证,比什么都好
奖励黑币这种东西就不需要了,你没我的多
一个1302的程序,并不是什么火箭上天的难度,他只是一个入门的东西而已,实在不想动手,我有现成的DS3231+GPS自动对时的时钟,程序和PCB都可以免费上传,只要你说了就行
回复

使用道具 举报

ID:332444 发表于 2023-1-3 23:49 | 显示全部楼层
188610329 发表于 2023-1-3 20:47
虽然不知道你说的独占计数是啥东西,如果仅仅是指延时的话,直接用串口1模式0,就好了,不光不需要延时,连 ...

看我这帖子http://www.51hei.com/bbs/dpj-225609-1.html
回复

使用道具 举报

ID:332444 发表于 2023-1-4 07:12 | 显示全部楼层
可以这样说,以贴出来的电路和只读取1302的时分秒送8位数码管显示,并有整点4响半点2响为功能,并在主函数while(1)内用beep=!beep;仿真测试整个代码响应时间为目标,且不得使用循环语句包括GOTO在内构成的独占循环计数延时,即这次把数码管显示中的while计数延时也去掉了,从而提高了程序整体响应时间,从之前的10ms提高到了约40us,这就意味着整个程序还有充足的时间去响应其它更多事件安排。各位高手可以尽情展现优秀算法,尽量使得beep的周期最小,我目前能做到beep的周期不到40us,既然“大家”们说得那么有把握,我很想开开眼界,相信有很多人也期待着。
51hei.png
回复

使用道具 举报

ID:996773 发表于 2023-1-4 13:31 | 显示全部楼层
没看懂楼主的目的,楼主用的是138解码逐个点亮数码管的扫描方式,读取1302数据和bcd转换十进制再查表只需要在点亮一个数码管周期内完成,其余时间只能等待延时,不延时还能干嘛呢,还有啊,这程序太简单了,很多功能都没实现,操作不用按钮,使用旋转编码器,年月日和闹钟都没实现呢,这些都实现了,再找优化方案和程序精简
回复

使用道具 举报

ID:401564 发表于 2023-1-4 20:03 | 显示全部楼层
xianfajushi 发表于 2023-1-4 07:12
可以这样说,以贴出来的电路和只读取1302的时分秒送8位数码管显示,并有整点4响半点2响为功能,并在主函数w ...

我这几年编程白学了?我怎么看了几次都看不明白这段文字表达了什么...........
回复

使用道具 举报

ID:213173 发表于 2023-1-4 20:42 | 显示全部楼层
xianfajushi 发表于 2023-1-4 07:12
可以这样说,以贴出来的电路和只读取1302的时分秒送8位数码管显示,并有整点4响半点2响为功能,并在主函数w ...

这种要求的程序很简单,也用不着138、573,给你一个示例参考,另加闹钟也是轻而易举的事。黑币你就自己留着吧。 无标题.jpg


  1. #include <reg51.H>
  2. #include <intrins.h>
  3. #define uchar unsigned char
  4. #define uint  unsigned int
  5. #define key_S 8                                        //宏定义短按(约20ms)
  6. #define key_L key_S*30                        //宏定义长按(约600ms)
  7. #define key_I key_S*20                        //宏定义长按连+间隔(约200ms)
  8. //DS1302引脚连接定义
  9. sbit DSIO = P3^2;
  10. sbit REST = P3^0;
  11. sbit SCLK = P3^1;
  12. sbit key1 = P3^3;
  13. uchar code table[]={//共阴数码管段码"0~f-."
  14. 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x80};
  15. uchar dis_buf[8]={0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00};                //数码管显示缓存数组
  16. //DS1302读取和写入时分秒日月周年的地址
  17. uchar code READ_RTC_ADDR[7]=  {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; //读出地址
  18. uchar code WRITE_RTC_ADDR[7]= {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c}; //写入地址
  19. //              秒    分    时    日    月    周    年
  20. uchar TIME[7]={0x00, 0x00, 0x12, 0x04, 0x01, 0x03, 0x23};//读取Ds1302 存储顺序是秒分时日月周年
  21. //---全局变量声明---
  22. uint  Cnt2ms;                //2.5ms计数变量
  23. uint  num;                    //计数变量
  24. uchar KeySec;                 //键值变量
  25. bit   flashing;               //闪烁标志
  26. //---本地函数声明---//
  27. void Ds1302Init();            //DS1302初始化
  28. void Ds1302Write(uchar addr, uchar dat);//向1302芯片写入地址和数据
  29. uchar Ds1302Read(uchar addr); //从1302读数据
  30. void Ds1302ReadTime();        //读取秒分时日月周年信息
  31. uchar BCD_D(uchar bcd);       //BCD码转十进制函数
  32. uchar D_BCD(uchar Dec);       //十进制转BCD码函数
  33. void Timer0Init(void);        //定时器T0初始化
  34. //==============DS1302驱动部分=====================
  35. //写1302时钟数据
  36. void Ds1302Write(uchar addr, uchar dat)
  37. {
  38.         uchar i;
  39.         REST= 0;
  40.         SCLK= 0;
  41.         REST= 1;
  42.         for(i=0;i<8;i++)       // 写地址
  43.         {
  44.                 DSIO=addr & 0x01;  //数据从低位开始传送
  45.                 addr>>=1;
  46.                 SCLK = 1;          //数据在上升沿时,DS1302读取数据
  47.                 SCLK = 0;
  48.         }
  49.         for(i=0;i<8;i++)       //写数据
  50.         {
  51.                 DSIO=dat & 0x01;
  52.                 dat>>= 1;
  53.                 SCLK = 1;           // 数据在上升沿时,DS1302读取数据
  54.                 SCLK = 0;       
  55.         }                 
  56.         REST = 0;                // 传送数据结束       
  57. }
  58. //读1302时钟数据
  59. uchar Ds1302Read(uchar addr)
  60. {
  61.         uchar i,dat,dat1;
  62.         REST = 0;
  63.         SCLK = 0;
  64.         REST = 1;
  65.         for(i=0; i<8; i++)      // 开始传送八位地址命令
  66.         {
  67.                 DSIO = addr & 0x01; // 数据从低位开始传送
  68.                 addr >>= 1;
  69.                 SCLK = 1;           // 上升沿有效,DS1302读取数据
  70.                 SCLK = 0;
  71.         }
  72.         for(i=0;i<8;i++)        // 读取8位数据
  73.         {
  74.                 dat1 = DSIO;        // 从最低位开始接收
  75.                 dat=(dat>>1)|(dat1<<7);
  76.                 SCLK = 1;           // 上升沿有效,DS1302读取数据
  77.                 SCLK = 0;
  78.         }
  79.         REST = 0;               // 以下为DS1302复位的稳定时间,必须的。                   
  80.         SCLK = 1;
  81.         DSIO = 0;
  82.         DSIO = 1;
  83.         return dat;       
  84. }
  85. //初始化DS1302
  86. void Ds1302Init()
  87. {
  88.         uchar i;
  89.         Ds1302Write(0x8E,0x00);   // 禁止写保护功能
  90.         for(i=0;i<3;i++)          // 写入3个字节的时钟信号:分秒时       
  91.                 Ds1302Write(WRITE_RTC_ADDR[i],TIME[i]);
  92.         Ds1302Write(0x8E,0x80);   // 打开写保护功能
  93. }
  94. //BCD码转十进制函数
  95. uchar BCD_D(uchar bcd)
  96. {
  97.         return ((bcd>>4)*10)+(bcd & 0x0f);
  98. }
  99. //十进制转BCD码函数,返回BCD码
  100. uchar D_BCD(uchar Dec)
  101. {
  102.         return (Dec/10*16+Dec%10);
  103. }

  104. //读取时钟信息
  105. void Ds1302ReadTime()
  106. {
  107.         uchar i;
  108.         for(i=0;i<3;i++)         //读取3个字节的时钟信号:秒分时
  109.                 TIME[i]=BCD_D(Ds1302Read(READ_RTC_ADDR[i]));//BCD转换成十进制保存
  110. }

  111. //按键服务函数
  112. void key_scan()
  113. {
  114.         static uint time=0;  //计数变量

  115.         if(!key1)       //按键按下
  116.         {
  117.                 time++;
  118.                 if(time>=key_L)  //长按
  119.                 {
  120.                         switch(KeySec)
  121.                         {
  122.                                 case 1: TIME[2]++;if(TIME[2]>23)TIME[2]=0;break;
  123.                                 case 2: TIME[1]++;if(TIME[1]>59)TIME[1]=0;TIME[0]=0;break;
  124.                         }
  125.                         time=key_I;  //连+间隔
  126.                         num=2000;     //自复位变量赋值(5秒)
  127.                 }
  128.         }
  129.         else                                //松手
  130.         {
  131.                 if(time>key_S && time<key_I)//短按
  132.                 {
  133.                         num=2000;    //自复位变量赋值(5秒)
  134.                         KeySec++;
  135.                         if(KeySec>2)
  136.                         {
  137. //                                KeySec=0;
  138.                                 num=1;
  139.                         }
  140.                 }
  141.                 time=0;
  142.         }
  143. }

  144. // 数码管显示函数
  145. void display()
  146. {
  147.         uchar i;
  148.         if(KeySec==0)           //常态显示
  149.         {
  150.                 dis_buf[0]=table[TIME[2]/10];
  151.                 dis_buf[1]=table[TIME[2]%10];
  152.                 dis_buf[3]=table[TIME[1]/10];
  153.                 dis_buf[4]=table[TIME[1]%10];
  154.                 dis_buf[6]=table[TIME[0]/10];
  155.                 dis_buf[7]=table[TIME[0]%10];
  156.         }
  157.         if(KeySec==1)           //调整时
  158.         {
  159.                 if(!key1)//持续不变表示键长按连加,时不闪烁
  160.                 {
  161.                         dis_buf[0]=table[TIME[2]/10];
  162.                         dis_buf[1]=table[TIME[2]%10];
  163.                 }
  164.                 else                //松手 时闪烁
  165.                 {
  166.                         if(flashing)
  167.                         {
  168.                                 dis_buf[0]=table[TIME[2]/10];
  169.                                 dis_buf[1]=table[TIME[2]%10];
  170.                         }
  171.                         else
  172.                         {
  173.                                 dis_buf[0]=0x00;
  174.                                 dis_buf[1]=0x00;
  175.                         }
  176.                 }
  177.                 dis_buf[3]=table[TIME[1]/10];
  178.                 dis_buf[4]=table[TIME[1]%10];
  179.                 dis_buf[6]=table[TIME[0]/10];
  180.                 dis_buf[7]=table[TIME[0]%10];

  181.         }
  182.         if(KeySec==2)           //调整分
  183.         {
  184.                 dis_buf[0]=table[TIME[2]/10];
  185.                 dis_buf[1]=table[TIME[2]%10];
  186.                 if(!key1)//持续不变表示键长按连加,分不闪烁
  187.                 {
  188.                         dis_buf[3]=table[TIME[1]/10];
  189.                         dis_buf[4]=table[TIME[1]%10];
  190.                 }
  191.                 else                //松手 分闪烁
  192.                 {
  193.                         if(flashing)
  194.                         {
  195.                                 dis_buf[3]=table[TIME[1]/10];
  196.                                 dis_buf[4]=table[TIME[1]%10];
  197.                         }
  198.                         else
  199.                         {
  200.                                 dis_buf[3]=0x00;
  201.                                 dis_buf[4]=0x00;
  202.                         }
  203.                 }
  204.                 dis_buf[6]=table[TIME[0]/10];
  205.                 dis_buf[7]=table[TIME[0]%10];
  206.         }
  207.         P2=0xff;
  208.         P0=dis_buf[i];
  209.         P2=~(0x01<<i);
  210.         i=++i%8;
  211. }
  212. //初始化定时器
  213. void Timer0Init(void)                //2500微秒@12.000MHz
  214. {
  215.         TMOD |= 0x01;                //设置定时器模式
  216.         TL0 = 0x3C;                //设置定时初始值
  217.         TH0 = 0xF6;                //设置定时初始值
  218.         TF0 = 0;                //清除TF0标志
  219.         TR0 = 1;                //定时器0开始计时
  220. }
  221. //主函数
  222. void main()
  223. {
  224.         uchar t;
  225.         Ds1302Init();
  226.         Timer0Init();   //初始化定时器
  227.         while(1)
  228.         {
  229.                 if(TF0)    //周期2.5ms
  230.                 {
  231.                         TF0=0;
  232.                         TL0 = 0x3C;                //设置定时初始值
  233.                         TH0 = 0xF6;                //设置定时初始值
  234.                         if(++Cnt2ms==400)Cnt2ms=0;
  235.                         key_scan();//按键扫描
  236.                         if(num!=0)
  237.                         {
  238.                                 if(Cnt2ms%80==0)//0.2s 设置状态时、分快闪
  239.                                         flashing=~flashing;
  240.                                 num--;
  241.                                 if(num==0)//按键停止操作5秒自动恢复正常显示
  242.                                 {
  243.                                         for(t=1;t<3;t++)//数据转码导入写入缓存
  244.                                                 TIME[t]=D_BCD(TIME[t]);//十进制转BCD码
  245.                                         Ds1302Init();//写入实时时间
  246.                                         KeySec=0;//键值清0
  247.                                 }
  248.                         }
  249.                         else //设置时间时 不读取DS1302实时时间
  250.                         {
  251.                                 Ds1302ReadTime();//读DS1302实时时间
  252.                         }
  253.                         display();// 数码管显示函数
  254.                 }
  255.         }
  256. }

复制代码



回复

使用道具 举报

ID:332444 发表于 2023-1-5 07:02 | 显示全部楼层
wulin 发表于 2023-1-4 20:42
这种要求的程序很简单,也用不着138、573,给你一个示例参考,另加闹钟也是轻而易举的事。黑币你就自己留 ...

实在是抱歉,我忘记了说明是不开定时器的情况下,就用简单的功能做测试,不要看表面功能简单,练就的是功夫。
回复

使用道具 举报

ID:332444 发表于 2023-1-5 07:05 | 显示全部楼层
wulin 发表于 2023-1-4 20:42
这种要求的程序很简单,也用不着138、573,给你一个示例参考,另加闹钟也是轻而易举的事。黑币你就自己留 ...

不错,通篇没用到计数延时。
回复

使用道具 举报

ID:332444 发表于 2023-1-5 07:29 | 显示全部楼层
wulin 发表于 2023-1-4 20:42
这种要求的程序很简单,也用不着138、573,给你一个示例参考,另加闹钟也是轻而易举的事。黑币你就自己留 ...

今早想起来要补充说明不开定时器的情况下,就用简单的功能来测试,蜂鸣器一定要的,若要其它功能不是不会提出来,我自己代码也是不开定时器,不使用额外循环计数延时,我的测试周期还可以优化再减小。
回复

使用道具 举报

ID:332444 发表于 2023-1-5 07:39 | 显示全部楼层
wulin 发表于 2023-1-4 20:42
这种要求的程序很简单,也用不着138、573,给你一个示例参考,另加闹钟也是轻而易举的事。黑币你就自己留 ...

主函数添加bit zq=0;zq=~zq;做测试结果大约10毫秒处理时间间隔。
用时测试.png
回复

使用道具 举报

ID:332444 发表于 2023-1-5 07:56 | 显示全部楼层
看我的,最大空白间隔约0.6毫秒表示程序处理堆叠时间,红色部分说明已经返回主函数了,不过我的周期比较长约40微秒,则说明有较多时间用于其它事件。 用时测试1.png
而看wulin程序周期只有6微秒,但是空白部分约十几毫秒表示程序占用累积堆叠处理时间,而红色部分表示已经返回主函数约有10毫秒,就说明有10毫秒间隔可以安排其它事件的时间。


以上测试都无任何操作情况下进行编程软件内的仿真。
回复

使用道具 举报

ID:332444 发表于 2023-1-9 10:26 | 显示全部楼层
1.png 2.png
从以上2张测试图片可以看到我的程序只是在读取时独占处理读取时间,其他部分都返回主程序,包括数码管延时都不再有较大的独占时间。
回复

使用道具 举报

ID:332444 发表于 2023-1-9 16:05 | 显示全部楼层
通过我提供的测试图片一看就知道单片机的时间都到哪去了,也就知道优化该从何处下手了,我之所以说我的程序还能进一步优化,指的是读取芯片的频次可以进一步减少而不会明显影响显示精度,按目前图片的时间约50毫秒的频次显然有很多次去读取是不必要的,因此是可以继续优化的,至于多少次或说多少时间去读取一次合理,就值得探讨了,各位高手不妨畅言高论。
回复

使用道具 举报

ID:213173 发表于 2023-1-9 17:17 | 显示全部楼层
xianfajushi 发表于 2023-1-5 07:29
今早想起来要补充说明不开定时器的情况下,就用简单的功能来测试,蜂鸣器一定要的,若要其它功能不是不会 ...

用定时器的目的是控制主函数循环周期,以便轻松处理按键消抖和按键长短按计数以及数码管动态扫描。如果在主函数中加无源蜂鸣器驱动就得缩短定时周期也就是主函数循环周期。大约200us。因为无源蜂鸣器有特定的驱动频率要求,常见的廉价无源蜂鸣器约2KHz声压最大。若主函数循环周期不稳定蜂鸣器音量声调也不会稳定。这不是仿真就可以搞定的。通常情况下200us可以干很多很多事。对于某些在一个主循环周期内做不完的事可以拆分。单片机玩的就是时间和逻辑。说白了就是在什么时间点干什么事。
回复

使用道具 举报

ID:332444 发表于 2023-1-10 16:50 | 显示全部楼层
wulin 发表于 2023-1-9 17:17
用定时器的目的是控制主函数循环周期,以便轻松处理按键消抖和按键长短按计数以及数码管动态扫描。如果在 ...

优化的读取是秒=0则读分,分=0则读时,不需要频繁读分和时信息,这样就可以节省很多宝贵的时间资源.
回复

使用道具 举报

ID:332444 发表于 2023-1-10 16:59 | 显示全部楼层
wulin 发表于 2023-1-9 17:17
用定时器的目的是控制主函数循环周期,以便轻松处理按键消抖和按键长短按计数以及数码管动态扫描。如果在 ...

之前代码是秒分时频繁都去读取,其实没必要,因此修改后的代码就是按条件限制的读取
Mbcd=Du_1302(0x81);
if(Mbcd==0)Fbcd=Du_1302(0x83);
if(Fbcd==0)Sbcd=Du_1302(0x85);
回复

使用道具 举报

ID:332444 发表于 2023-1-10 17:13 | 显示全部楼层
wulin 发表于 2023-1-9 17:17
用定时器的目的是控制主函数循环周期,以便轻松处理按键消抖和按键长短按计数以及数码管动态扫描。如果在 ...

限制条件的读是最合理的时间安排
Mbcd=Du_1302(0x81);
if(Mbcd==0)Fbcd=Du_1302(0x83);
if(Mbcd==0&&Fbcd==0)Sbcd=Du_1302(0x85);
回复

使用道具 举报

ID:332444 发表于 2023-1-10 23:01 | 显示全部楼层
在不开定时器情况下也可以比较精准控制只读一次秒信息精度控制在毫秒以下,因为上述说过了的6毫秒和40毫秒周期,因此可以比较精准控制去读秒信息一次足够,而不需要无谓的多次读取,同样道理读天月年也可以按条件读取,只是不开定时器情况下按我的思路是实现所有功能代码后再进行比较精准的控制读秒信息,因为不同功能的程序周期也不同,就比如6毫秒和40毫秒周期一般道理。
回复

使用道具 举报

ID:624769 发表于 2023-1-11 00:20 来自手机 | 显示全部楼层
xianfajushi 发表于 2023-1-10 16:50
优化的读取是秒=0则读分,分=0则读时,不需要频繁读分和时信息,这样就可以节省很多宝贵的时间资源.

ds1302来说,你真要节约宝贵的系统资源,就用硬件读写。不管用spi读写,还是串口1读写,都比你IO读写,占用系统时钟少。
回复

使用道具 举报

ID:401564 发表于 2023-1-11 13:22 | 显示全部楼层
188610329 发表于 2023-1-11 00:20
ds1302来说,你真要节约宝贵的系统资源,就用硬件读写。不管用spi读写,还是串口1读写,都比你IO读写,占 ...

从主程序中看到,这就是一个1302时钟,其它什么事都没干,压根就不需要节约什么时间,效率什么的都是没有什么意义的
1秒钟读取一次,延时直接用delay();
按键一样的直接延时去抖动,没必要折腾那么多东西
或者是说用读取的时间来作为数码管的延时,都比楼主折腾这个好
我也不知道,把单片机时间节约成这样子,是为了什么?
是怕单片机累坏了?还是怕单片机长时间延时会闹情绪
我看了半天,都不知道“独占时间”是个什么玩意
回复

使用道具 举报

ID:384109 发表于 2023-1-12 08:39 | 显示全部楼层
这个就是纯粹的强调所谓的效率两个字而已,但实际应用中效率到底又指什么呢
回复

使用道具 举报

ID:332444 发表于 2023-1-15 12:52 | 显示全部楼层
人中狼 发表于 2023-1-12 08:39
这个就是纯粹的强调所谓的效率两个字而已,但实际应用中效率到底又指什么呢

其它都不用说,有好的程序拿来看看。
我家一台旭日红外热水器无线控制器每周都快1小时多,比如时间是6点看它屏幕走时已经是7点多了,每次都要去调整时间,否则计算峰谷的时间就不准确了!非常麻烦,是很差劲的产品质量,可以断定是很差劲的程序代码,所以莫要小看简单的程序提高效率问题,所谓见微知著,简单的功能都不能注重效率的话,可知复杂功能是很有问题的。
回复

使用道具 举报

ID:332444 发表于 2023-1-18 10:14 | 显示全部楼层
经过几次试验目前把读秒信号压缩到每秒4次左右基本察觉不到太大差别可以接受的程度,调整后蜂鸣器音调频率也发生变化能听出区别来。
回复

使用道具 举报

ID:332444 发表于 2023-1-18 14:01 | 显示全部楼层
本帖最后由 xianfajushi 于 2023-1-18 14:44 编辑

无标题2.png
并报时期间显示日期,这样才是合理的逻辑顺序安排,按键代码看以往帖子。
回复

使用道具 举报

ID:332444 发表于 2023-1-24 15:33 | 显示全部楼层
显示年月天周用点号隔开
1.png
回复

使用道具 举报

ID:332444 发表于 2023-1-26 11:19 | 显示全部楼层
楼上各位说我功能简单了,担心我不会写还是不会安排?之下就管中窥豹看看我的功能如何安排,稍微写了按秒步进的分钟+-调节并进制到时钟+-同步,年月天周道理一样,以后想写时再补上。
之上代码还不算最优化,我还可以优化到颠覆常规思维,返回主函数周期减小到十几微秒,除了数码位7不能调节外,四层嵌套询问式延时可以灵活调节满足硬件需求,当然按键长按也可以实现。
用时测试.png

回复

使用道具 举报

ID:332444 发表于 2023-1-27 07:29 | 显示全部楼层
wulin 发表于 2023-1-9 17:17
用定时器的目的是控制主函数循环周期,以便轻松处理按键消抖和按键长短按计数以及数码管动态扫描。如果在 ...

中断+计数的1毫秒间隔或200微妙能做多少事还真的没什么案例,本案例旨在说明询问式计数延时相比独占计数延时的优越且灵活调节和设置,属于高级分析思维模式,而非入门级别独占计数延时一直套用引发种种疑难。
回复

使用道具 举报

ID:213173 发表于 2023-1-28 09:13 | 显示全部楼层
xianfajushi 发表于 2023-1-10 17:13
限制条件的读是最合理的时间安排
Mbcd=Du_1302(0x81);
if(Mbcd==0)Fbcd=Du_1302(0x83);

这个限制条件不完善,在Mbcd=0的1秒时间内会多次读1302,如果是跨年的那1秒内,则重复多次读全部数据。当然这属吹毛求疵,未必影响其它程序正常运行。何况是在半夜,谁还会去计较。
回复

使用道具 举报

ID:332444 发表于 2023-1-28 10:27 | 显示全部楼层
wulin 发表于 2023-1-28 09:13
这个限制条件不完善,在Mbcd=0的1秒时间内会多次读1302,如果是跨年的那1秒内,则重复多次读全部数据。当 ...

频繁读取1302全部数据是否会影响其计时精度?目前猜测而已没什么证据。
回复

使用道具 举报

ID:332444 发表于 2023-1-28 17:08 | 显示全部楼层
wulin 发表于 2023-1-28 09:13
这个限制条件不完善,在Mbcd=0的1秒时间内会多次读1302,如果是跨年的那1秒内,则重复多次读全部数据。当 ...

那么怎样才合理?之上已经说了,寻求合理的安排,目前把读秒压缩在每秒4次左右,在不开定时期情况下;若开定时器按每秒读取然而定时器未必就能精确每秒夜有不精确时候就会造成漏读秒的情况发生.
回复

使用道具 举报

ID:213173 发表于 2023-1-28 20:39 | 显示全部楼层
xianfajushi 发表于 2023-1-28 10:27
频繁读取1302全部数据是否会影响其计时精度?目前猜测而已没什么证据。

频繁读取1302全部数据不会影响其计时精度,但对于你刻意精打细算主循环时间肯定有影响。比如蜂鸣器音调会不稳。
回复

使用道具 举报

ID:213173 发表于 2023-1-28 20:56 | 显示全部楼层
xianfajushi 发表于 2023-1-28 17:08
那么怎样才合理?之上已经说了,寻求合理的安排,目前把读秒压缩在每秒4次左右,在不开定时期情况下;若开定时 ...

所谓合理是相对的,在不影响其它功能的前提下频繁读1302也并无不可,单片机也累不死。只能说在现有硬件条件下,满足所有功能预期,互相不发生冲突是需要一定的编程技巧。刻意追求主函数周期减小到十几微秒又有多少实际意义。
回复

使用道具 举报

ID:332444 发表于 2023-1-29 08:29 | 显示全部楼层
wulin 发表于 2023-1-28 20:56
所谓合理是相对的,在不影响其它功能的前提下频繁读1302也并无不可,单片机也累不死。只能说在现有硬件条 ...

不断优化就是对逻辑思维的验证,从而实现卖油翁的过程.
其实不然我认为频繁读取对精度有所影响,就好比开定时器中断应该说没什么影响,然而实践告诉人们,轻便的程序对定时器计时精度没多大影响,而复杂的程序对定时器计时精度就有影响,中断也要获得响应时间的,电路也是一样的总要拨点时间去处理其他事件.
回复

使用道具 举报

ID:332444 发表于 2023-1-29 08:50 | 显示全部楼层
wulin 发表于 2023-1-28 20:56
所谓合理是相对的,在不影响其它功能的前提下频繁读1302也并无不可,单片机也累不死。只能说在现有硬件条 ...

只有了然于胸才能驾轻就熟
回复

使用道具 举报

ID:332444 发表于 2023-1-29 08:55 | 显示全部楼层
wulin 发表于 2023-1-28 20:56
所谓合理是相对的,在不影响其它功能的前提下频繁读1302也并无不可,单片机也累不死。只能说在现有硬件条 ...

如果能够把程序打造得轻便即可用计时器中断实现比较精准的计时抛却时钟芯片目标,毕竟兆赫兹的精度比千赫兹提高了一个数量级别。
回复

使用道具 举报

ID:332444 发表于 2023-1-29 15:43 | 显示全部楼层
突发奇想,用数码管显示每周的值:一二三四五六日。64,64,9,9,73,73,63,63,9,61,81,69,121,79
回复

使用道具 举报

ID:332444 发表于 2023-1-31 11:00 | 显示全部楼层
为了验证程序员的价值和水平可以做到降低产品成本,我修改了程序抛开时钟芯片用定时期替代秒计时,运行十几个小时结果和电脑时钟一样精准。主函数初始化读取时钟芯片信息保持与系统一样时间后由定时期进行计时,不再读时钟芯片信息,这样就可以在仿真中对比数码管与时钟芯片显示的窗口信息。
无标题.png 无标题.png

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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