找回密码
 立即注册

QQ登录

只需一步,快速开始

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

while(1)循环是不是很慢

  [复制链接]
跳转到指定楼层
楼主
ID:1144680 发表于 2025-5-31 21:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
DS1302时钟,在while(1)里有两个"if"检测按键,没有按键时用switch/case显示时钟,结果发现时钟不同步,秒进位时,有时候“小时”或“分钟”会延迟1秒左右,这是while循环有延迟吗?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:712493 发表于 2025-5-31 21:46 | 只看该作者
肯定不是,while(1)只是大循环而已!
回复

使用道具 举报

板凳
ID:584814 发表于 2025-5-31 22:33 | 只看该作者
可能是防抖功能的设计问题
回复

使用道具 举报

地板
ID:619259 发表于 2025-5-31 23:38 | 只看该作者
时间有延时与while(1)无关,秒溢出,分+1延时,应该是你的1302读写函数有延时了。
回复

使用道具 举报

5#
ID:624769 发表于 2025-5-31 23:54 | 只看该作者
是你读DS1302代码的问题
回复

使用道具 举报

6#
ID:1128898 发表于 2025-6-1 06:15 | 只看该作者
延迟对的,信号并不是时时的,关键看处理什么控制什么,又不是f16
回复

使用道具 举报

7#
ID:1109793 发表于 2025-6-1 07:51 | 只看该作者
是一个循环,慢不慢,看你代码啊
回复

使用道具 举报

8#
ID:1144680 发表于 2025-6-1 13:45 | 只看该作者
xiaobendan001 发表于 2025-6-1 07:51
是一个循环,慢不慢,看你代码啊

帮忙看看,谢谢!

  1.         while (1)      
  2. {       
  3.       if (TM1639_KEY_B1==1)
  4. {
  5.     _nop_();
  6.     while(TM1639_KEY_B1==1);//按住不放
  7.     _nop_();
  8.         SetSelect++;//松手后
  9.        
  10.                                 if(SetSelect>=7){SetSelect=0;DS1302_GengxinTime();}        //更新时间                       
  11.                                
  12. //                                        LED_OF[TimeWei-1]=0xff;        //离开该位显示,防止正好熄灭       
  13.                                 LED_OF[0]=0xff;
  14.                                 LED_OF[1]=0xff;                                
  15.                                 LED_OF[3]=0xff;        
  16.                                 LED_OF[4]=0xff;
  17.                                 LED_OF[6]=0xff;                                
  18.                                 LED_OF[7]=0xff;                                        
  19. }
  20.                         switch(SetSelect)
  21.                         {
  22.                                 case 0:        TimeShow(); break;        //读取并显示时间
  23.                                 case 1:        TimeWei=0;        break;        //10时               
  24.                                 case 2:        TimeWei=1;        break;        // 时               
  25.                                 case 3:        TimeWei=3;        break;                //10分       
  26.                                 case 4: TimeWei=4;        break;                //分       
  27.                                 case 5:        TimeWei=6;        break;        //10秒                       
  28.                                 case 6: TimeWei=7;        break;        //秒       
  29.                         }
  30.                
  31. if (TM1639_KEY_B2==1)
  32.         {
  33.     _nop_();
  34.     while(TM1639_KEY_B2==1);//按住不放
  35.     _nop_();
  36.                
  37.     Shezhi();        //设置时间
  38.         }       
  39.                
  40. }
复制代码



回复

使用道具 举报

9#
ID:1144680 发表于 2025-6-1 13:47 | 只看该作者
  1. void TimeShow()
  2. {
  3.      DS1302_ReadTime();//读取时间
  4.           LED_BCD[0] =DS1302_Time[0];                  //最高位,10时               
  5.           LED_BCD[1] =DS1302_Time[1];         

  6.           LED_BCD[3] =DS1302_Time[3];                        
  7.           LED_BCD[4] =DS1302_Time[4];                       

复制代码


显示时间代码
回复

使用道具 举报

10#
ID:1144680 发表于 2025-6-1 13:49 | 只看该作者
man1234567 发表于 2025-5-31 22:33
可能是防抖功能的设计问题

是有两个延迟,不过是按键按下后才起作用。
回复

使用道具 举报

11#
ID:1144680 发表于 2025-6-1 13:50 | 只看该作者
cy009 发表于 2025-5-31 23:38
时间有延时与while(1)无关,秒溢出,分+1延时,应该是你的1302读写函数有延时了。

有点头晕,下面有代码,能不能帮忙看看。。。
回复

使用道具 举报

12#
ID:1144680 发表于 2025-6-1 13:51 | 只看该作者
188610329 发表于 2025-5-31 23:54
是你读DS1302代码的问题

一开始没问题,后来加了按键检测后出现的,不知道哪个环节出的。
回复

使用道具 举报

13#
ID:1152291 发表于 2025-6-1 16:53 | 只看该作者
dcc60 发表于 2025-6-1 13:51
一开始没问题,后来加了按键检测后出现的,不知道哪个环节出的。

其实加了按键检测是不太灵敏的,首先按键检测是是基于一个模块的,但是你如果添加了多个模块的话,按键检测到底是应用于谁了,所以基于按键检测模块的书写,一般是只能需求一个模块的,多个模块添加进来,是会使软件整混的,应用于仿真和实物都是不太灵敏的。
回复

使用道具 举报

14#
ID:1133081 发表于 2025-6-1 17:31 | 只看该作者
dcc60 发表于 2025-6-1 13:51
一开始没问题,后来加了按键检测后出现的,不知道哪个环节出的。

TM1639读到的键值是1个字节,并不是位信号0/1。没有看到相关代码,无法判断与你所说的延迟1秒是否有关。
回复

使用道具 举报

15#
ID:1152365 发表于 2025-6-1 17:40 | 只看该作者
肯定不是,while(1)只是大循环而已
回复

使用道具 举报

16#
ID:1144680 发表于 2025-6-1 18:15 | 只看该作者
WL0123 发表于 2025-6-1 17:31
TM1639读到的键值是1个字节,并不是位信号0/1。没有看到相关代码,无法判断与你所说的延迟1秒是否有关。

估计是我搞错了。
下次把按键改为单片机引脚。
回复

使用道具 举报

17#
ID:1144680 发表于 2025-6-1 18:17 | 只看该作者
单片机重购 发表于 2025-6-1 16:53
其实加了按键检测是不太灵敏的,首先按键检测是是基于一个模块的,但是你如果添加了多个模块的话,按键检 ...

太复杂了。
谢谢支持,再研究研究。
回复

使用道具 举报

18#
ID:883242 发表于 2025-6-2 18:48 | 只看该作者
就是while按键那两句卡住的。
回复

使用道具 举报

19#
ID:1144680 发表于 2025-6-3 10:27 | 只看该作者
Hephaestus 发表于 2025-6-2 18:48
就是while按键那两句卡住的。

下次删了试试。
回复

使用道具 举报

20#
ID:1152291 发表于 2025-6-3 17:10 | 只看该作者
有时候不用while(1)进行循环,用其它语言指令对单片机进行书写也是可以使得单片机的程序可以运行起来
回复

使用道具 举报

21#
ID:1152595 发表于 2025-6-3 18:41 | 只看该作者
这个函数本身没有快慢的说法,主要看内部函数
回复

使用道具 举报

22#
ID:1152630 发表于 2025-6-3 22:48 来自触屏版 | 只看该作者
试一下移除按键检测中的延时消抖,改为状态机方式。
回复

使用道具 举报

23#
ID:65956 发表于 2025-6-4 08:32 | 只看该作者
你可以不用while试试,因为用这个就是在死等,等超时了才重新来
回复

使用道具 举报

24#
ID:1144680 发表于 2025-6-4 10:58 | 只看该作者
aking991 发表于 2025-6-4 08:32
你可以不用while试试,因为用这个就是在死等,等超时了才重新来

在计时器里试过,没有延迟。
问题是以前也没有延迟,按说,即便延迟,应该时分秒一起延迟才对。
回复

使用道具 举报

25#
ID:1144680 发表于 2025-6-4 11:51 | 只看该作者
Hephaestus 发表于 2025-6-2 18:48
就是while按键那两句卡住的。

试过了,不是按键问题。
回复

使用道具 举报

26#
ID:1144680 发表于 2025-6-4 11:53 | 只看该作者
单片机重购 发表于 2025-6-3 17:10
有时候不用while(1)进行循环,用其它语言指令对单片机进行书写也是可以使得单片机的程序可以运行起来

是的,放在定时器里就没延迟。
回复

使用道具 举报

27#
ID:1144680 发表于 2025-6-4 11:55 | 只看该作者
2631449463 发表于 2025-6-3 22:48
试一下移除按键检测中的延时消抖,改为状态机方式。

试了,可能还是其它问题。
回复

使用道具 举报

28#
ID:1152676 发表于 2025-6-4 12:06 | 只看该作者
在DS1302时钟程序中,当`while(1)`循环内用两个`if`检测按键,且无按键时通过`switch/case`显示时钟,出现时间不同步(如秒进位时小时或分钟延迟1秒左右),**主要原因是按键检测逻辑导致主循环阻塞,影响了时钟数据的及时读取和刷新**。以下是具体分析和解决思路:   ### **一、问题根源:主循环阻塞导致时钟更新延迟** 1. **按键检测的潜在阻塞**      如果`if`语句中直接使用**延时消抖**(如`delay(20ms)`)或复杂逻辑,会导致整个`while(1)`循环卡顿。例如:      ```c    while(1) {        if(按键按下) {            delay(20ms); // 阻塞20ms,期间无法读取时钟            // 处理按键        }        // 读取DS1302时钟并显示    }    ```      此时,若按键按下,程序会在`delay`处停留20ms,导致**DS1302的秒更新可能被错过**,进而出现显示延迟。  2. **循环频率与时钟更新不匹配**      DS1302的秒数据每秒更新一次,若主循环执行周期较长(如因按键检测耗时),可能导致:      - 秒进位时,程序尚未读取到最新数据,仍在显示旧值;      - 下一次循环读取时,秒已进位,但分钟/小时的计算依赖旧秒值,导致延迟。   ### **二、解决方案:非阻塞式按键检测与定时刷新时钟** #### **1. 核心思路**   - **用定时器中断扫描按键**,避免主循环阻塞;   - **定时读取DS1302时钟**(如每100ms一次),确保数据更新频率稳定。  #### **2. 具体实现步骤**   ##### **(1)改用定时器中断检测按键(非阻塞式)**   - **原理**:通过定时器(如1ms中断)周期性扫描按键状态,用状态机记录按键按下、消抖、释放的过程,避免主循环中直接延时。   - **示例逻辑**:     ```c   unsigned char key_state = 0; // 0=未按下,1=按下消抖中,2=确认按下,3=释放等待   unsigned char key_flag = 0;  // 按键触发标志    // 定时器1ms中断函数   void Timer0_ISR() interrupt 1 {       if(按键按下) {           switch(key_state) {               case 0: key_state = 1; break; // 首次检测到按下,进入消抖               case 1: key_state = 2; key_flag = 1; break; // 消抖完成,标记按键触发           }       } else {           key_state = 0; // 按键释放,重置状态       }   }   ```  ##### **(2)定时读取DS1302时钟数据**   - **原理**:在主循环中用计数器控制读取频率(如每100ms读取一次),避免频繁读取占用资源。   - **示例逻辑**:     ```c   unsigned int tick = 0; // 计数器   unsigned char time_buf[7]; // 存储时分秒等数据    while(1) {       if(tick >= 100) { // 每100ms读取一次(100ms=0.1秒,可根据需求调整)           tick = 0;           DS1302_ReadTime(time_buf); // 读取时钟数据       }              // 显示时钟(switch/case逻辑)       switch(mode) {           case 0: 显示正常时间; break;           case 1: 显示调时界面; break;           // ...其他模式       }              tick++; // 每循环一次自增,控制读取频率       // 其他非阻塞操作(如少量延时或任务)   }   ```  ##### **(3)优化显示逻辑**   - 确保`switch/case`中的显示函数(如数码管驱动)执行速度快,避免包含耗时操作(如长延时)。   - 若显示需要动态效果(如闪烁),可通过定时器中断控制,而非在主循环中阻塞。   ### **三、其他可能原因及排查方向** 1. **DS1302通信时序问题**      - 检查读写函数是否严格遵循DS1302的时序要求(如时钟沿、复位信号顺序),避免因通信错误导致数据读取失败。   2. **变量缓存与临界资源**      - 若在中断中修改时间数据,需用`volatile`关键字声明变量,并在主循环读取时关闭中断,避免数据不一致。   3. **晶振稳定性**      - DS1302的走时精度依赖外部晶振(如32.768kHz),若晶振质量差或电容匹配不当,可能导致实际秒长偏移,需硬件排查。   ### **四、总结**   - **核心问题**:按键检测的阻塞式逻辑导致主循环无法及时读取和刷新时钟数据。   - **解决关键**:用定时器中断实现非阻塞按键扫描,主循环专注于定时读取时钟和快速显示,确保每秒至少读取一次时钟数据(如每100ms读取一次,每秒可读取10次),避免秒进位被遗漏。   - **扩展建议**:若系统支持多任务(如RTOS),可将按键处理、时钟读取、显示分别分配到独立任务,通过消息队列或信号量同步,进一步提升实时性。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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