找回密码
 立即注册
楼主: 杨为民

C51语言中的微秒、毫秒软件延迟函数探讨

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:16
  • 最近打卡:2025-04-30 08:41:32

105

主题

1215

回帖

1万

积分

荣誉版主

积分
12882
发表于 2024-11-5 20:12:44 | 显示全部楼层
本帖最后由 杨为民 于 2024-11-5 20:14 编辑
晓*** 发表于 2024-11-5 11:34
这是个最简单的基于中断驱动的状态机,执行一次,P0.0的状态就翻转一次,如果这两句代码放在周期为0.5s的 ...

对于下面例子,你能对下面的例子写个采用状态机方法的程序介绍给大家吗?包括定时器中断ISR的程序:
while(1){
   P0=~0x011;
   DelayMS(300);// 延迟300毫秒

   P0=~0x55;
   DelayMS(200);// 延迟200毫秒

   P0=~0xAA;
   DelayMS(350);// 延迟350毫秒

   P0=~0x0F;
   DelayMS(150);// 延迟350毫秒
}



回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:417
  • 最近打卡:2025-04-30 21:39:09
已绑定手机

34

主题

2096

回帖

2206

积分

荣誉版主

积分
2206
发表于 2024-11-5 20:30:36 | 显示全部楼层
本帖最后由 晓飛飛 于 2024-11-5 20:34 编辑
杨*** 发表于 2024-11-5 20:12
对于下面例子,你能对下面的例子写个采用状态机方法的程序介绍给大家吗?包括定时器中断ISR的程序:
while ...

下面的例子用的是1ms周期的中断,实际中,考虑到上述延迟最大公约数是50ms,可以配置定时器中断周期为50ms,状态机里面的延迟变量值就可以由变350ms改为7,150ms改为3等等,还可以大幅度降低进入定时中断的周期,提高效率。

  1. //1ms中断程序,写字板里面写的代码,未经验证,如有错误请自行排查,
  2. //大概思路就是如下
  3. void Timer0_Isr(void) interrupt 1
  4. {
  5.         static unsigned char sta;        //状态变量
  6.         static unsigned int delay;        //定时变量
  7.         switch(sta)
  8.         {
  9.                 case 0:                //状态机初始状态
  10.                         P0=~0x011;        //第一拍动作,只执行一次               
  11.                         delay = 300;        //设置定时值,倒计时方法,
  12.                         sta = 1;        //转下个状态
  13.                         break;
  14.                 case 1:                //第二拍动作
  15.                         if(delay)  delay--;  //定时变量倒计时,延迟没到就减一
  16.                         else                                 //延迟到了转下个动作,配置下个延迟
  17.                         {
  18.                                 P0=~0x55;
  19.                                 delay = 200;
  20.                                 sta++;        //转下个状态
  21.                         }
  22.                         break;
  23.                 case 2:                //第三拍动作
  24.                         if(delay)  delay--;
  25.                         else
  26.                         {
  27.                                 P0=~0xAA;
  28.                                 delay = 350;
  29.                                 sta++;        //转下个状态
  30.                         }
  31.                         break;
  32.                 case 3:                //第四拍动作
  33.                         if(delay)  delay--;
  34.                         else
  35.                         {
  36.                                 P0=~0x0f;
  37.                                 delay = 150;
  38.                                 sta++;        //转下个状态
  39.                         }
  40.                         break;
  41.                 case 4:                //第一拍动作
  42.                         if(delay)  delay--;
  43.                         else
  44.                         {
  45.                                 P0=~0x011;
  46.                                 delay = 300;
  47.                                 sta = 1;        //转第二拍动作
  48.                         }
  49.                         break;
  50.                 default:
  51.                                 sta = 0;
  52.                         break;                        
  53.         }
  54. }
  55. void Timer0_Init(void)                //1毫秒@11.0592MHz
  56. {
  57.         AUXR |= 0x80;                        //定时器时钟1T模式
  58.         TMOD &= 0xF0;                        //设置定时器模式
  59.         TL0 = 0xCD;                                //设置定时初始值
  60.         TH0 = 0xD4;                                //设置定时初始值
  61.         TF0 = 0;                                //清除TF0标志
  62.         TR0 = 1;                                //定时器0开始计时
  63.         ET0 = 1;                                //使能定时器0中断
  64. }
复制代码



点评

谢谢。 (1)实现同样的功能,你能向其他坛友点评一下,21楼的软件延时程序和22楼的状态机程序各有什么优缺点吗? (2)实现同样的功能,对比21楼的软件延时程序和22楼的状态机程序,你还坚持你19楼的观点“这比N  详情 回复 发表于 2024-11-5 22:58
睁开眼睛做场梦~~~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:16
  • 最近打卡:2025-04-30 08:41:32

105

主题

1215

回帖

1万

积分

荣誉版主

积分
12882
发表于 2024-11-5 22:58:58 | 显示全部楼层
晓*** 发表于 2024-11-5 20:30
下面的例子用的是1ms周期的中断,实际中,考虑到上述延迟最大公约数是50ms,可以配置定时器中断周期为50ms ...

谢谢。


(1)实现同样的功能你能向其他坛友点评一下,21楼的软件延时程序和22楼的状态机程序各有什么优缺点吗?

(2)实现同样的功能对比21楼的软件延时程序和22楼的状态机程序,你还坚持你19楼的观点“这比N层循环嵌套的傻delay强多了不是?”吗?
(3)俗话说“杀鸡不用牛刀”,我认为:“软件延时”与“22楼状态机”程序方法各有用武之地,不存在“谁傻”和“谁强”的问题
(4)对于状态机程序,如果像22楼将“状态机任务”放在中断服务程序中,除了像LED闪烁这种极简单例子外,在实际应用中可能产生“中断阻塞现象”,见我在下文中的讨论。
中断阻塞与信号量:C51语言中的单片机硬件定时方法探讨
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=11250
(出处: 国芯技术交流网站)
(5)正确的方法是将“状态机任务”放在后台任务中,把状态量(也是一种信号量)的变化放在ISR中。

(6)下面这个帖子介绍的才是最有代表性的“状态机”
任务调度方法,【无错,至简】!“多任务分时调度”
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=7611
(出处: 国芯技术交流网站)


点评

5,你不能把观点说成事实,你的观点不是也不可能是正确与否的标准 6,话不要说太满,“最”有代表性,我认为能代表您自己的认知范围即可 4,对于状态机有很多模式和维度的概念,OS调度系统也是在状态机基础上发展而  详情 回复 发表于 2024-11-5 23:43
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:417
  • 最近打卡:2025-04-30 21:39:09
已绑定手机

34

主题

2096

回帖

2206

积分

荣誉版主

积分
2206
发表于 2024-11-5 23:43:55 | 显示全部楼层

5,你不能把观点说成事实,你的观点不是也不可能是正确与否的标准
6,话不要说太满,“最”有代表性,我认为能代表您自己的认知范围即可
4,对于状态机有很多模式和维度的概念,OS调度系统也是在状态机基础上发展而来的,状态机放中断服务程序中,可不止能实现您所谓“极简单例子”,方法得当可堪大用,实现复杂逻辑和时序不在话下,包括很多软异步串口、软I2C、软SPI都轻松搞定。中断阻塞是什么概念,只有在中断里面用傻delay才会阻塞。
3,软件延时是傻delay,只是我对此一种可爱的称呼,对于us级软件延迟我也用,偶尔用几个nop也无伤大雅,但存在阻塞且效率低不能否认吧,单片机和人一样,等待的时候杵在那里数绵羊不傻么,还不如睡个觉打个盹喝个蜜雪冰城。搞过低功耗应用开发的都知道,主循环里面貌似只有一件事情,那就是“睡觉”,具体功能业务由各种中断唤醒即可。这和RTOS低功耗设计的机制是一样的。

PS,每个人有不同的价值观,技术也一样,综上,我只是表达我的观点,您也没必要高高在上的视角,像一个老师一样给我出各种考题,咱俩不是一种思维方式,没必要继续纠结谁对谁错。

点评

(1)既然在你的语言“傻”是可爱的称呼,那我21楼也只是给傻傻的你一个傻傻的机会而已。 (2)这个机会就是向大家展示有两种不同的看法(没有对错之分): 一种聪明人是把简单的事情复杂化,就像把22楼简单的没有技  详情 回复 发表于 2024-11-6 01:04
睁开眼睛做场梦~~~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:16
  • 最近打卡:2025-04-30 08:41:32

105

主题

1215

回帖

1万

积分

荣誉版主

积分
12882
发表于 2024-11-6 01:04:03 | 显示全部楼层
晓*** 发表于 2024-11-5 23:43
5,你不能把观点说成事实,你的观点不是也不可能是正确与否的标准
6,话不要说太满,“最”有代表性,我 ...

(1)既然在你的语言“傻”是可爱的称呼,那我21楼也只是给傻傻的你一个傻傻的机会而已。
(2)这个机会就是向大家展示有两种不同的看法(没有对错之分)
一种聪明人是把简单的事情复杂化,就像把22楼简单的没有技术含量的程序变成为23楼复杂的有技术含量的程序,
一种聪明人是把复杂的事情简单化,就像把23楼复杂的有技术含量的程序变成22楼简单的没有技术含量的程序。
我是后一种。尤其是对初学者介绍编程时。
(3)你说:“单片机和人一样,等待的时候杵在那里数绵羊不傻么,还不如睡个觉打个盹喝个蜜雪冰城”。你说的很对!
(4)所以已经写了在STC单片机上运行的RTOS操作系统,也移植了UC/OS-II操作系统到STC单片机上,在这些RTOS操作系统里,21楼的程序是这样的:
while(1){   P0=~0x011;   Sleep(300);// 休眠300毫秒   P0=~0x55;   Sleep(200);// 休眠200毫秒   P0=~0xAA;   Sleep(350);// 休眠350毫秒   P0=~0x0F;   Sleep(150);// 休眠350毫秒}

其中“Sleep()”函数就是放弃CPU控制权,让操作系统去干其他有用的事情。
(5)这个程序是不是同样比22楼程序简单明了?使用RTOS操作系统最重要的目的就是要是程序员编程容易,把复杂的事情交给操作系统去做。这是我在这个论坛里主要介绍RTOS而没有介绍状态机编程的主要原因。
(6)“中断阻塞是什么概念,只有在中断里面用傻delay才会阻塞”。关于中断阻塞,本文是用Delay来模拟的教学方法。至于真实的单片机程序里会不会发生,我觉得你应该把眼光再放开一点。
中断阻塞 对单片机RTOS的 实时响应是很大的决定因素,甚至会导致整个RTOS 系统崩溃


在本论坛的下面两篇文章里,我不仅给出了实际的例子,而且与大家进行了讨论交流。
华山论剑(3): CosyOS-II-STC8H在测试高优先级中断服务调用时崩溃了
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=8516
(出处: 国芯技术交流网站)
华山论剑(4):倚天剑x51,真正实现了“零中断延迟”的STC单片机RTOShttps://www.stcaimcu.com/forum.php?mod=viewthread&tid=8565(出处: 国芯技术交流网站)
这两篇文章后面都附有实际程序例子,你可以去验证一下有没有“中断阻塞”问题,欢迎你根据实际程序发表自己的观点





(6)关于“像一个老师一样给我出各种考题。我确实把我的每一篇帖子当做是“一堂课,大家都在互相学习,如果有跟贴的,我自然当做是“举手发言”,而我的21楼只是让你22楼“上黑板上答题”而已。
(7)对于你们的发言,我的点评不是要与你争什么对错,只是想向其他的坛友展示世界上还有不同的观点,让他们看到相同点和不同点,比如21楼和22楼两种风格的程序。至于他们认为谁对谁错,这是他们的权利

点评

关于这个“傻傻”不也本来是您的观点么,既然所见略同,就没什么好辩的了 [attachimg]62958[/attachimg]  详情 回复 发表于 2024-11-6 01:12
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:417
  • 最近打卡:2025-04-30 21:39:09
已绑定手机

34

主题

2096

回帖

2206

积分

荣誉版主

积分
2206
发表于 2024-11-6 01:12:28 | 显示全部楼层
杨*** 发表于 2024-11-6 01:04
(1)既然在你的语言“傻”是可爱的称呼,那我21楼也只是给傻傻的你一个傻傻的机会而已。
(2)这个机会 ...

关于这个“傻傻”不也本来是您的观点么,既然所见略同,就没什么好辩的了
截图202411060111066571.jpg

睁开眼睛做场梦~~~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:154
  • 最近打卡:2025-04-30 08:40:57
已绑定手机

15

主题

630

回帖

730

积分

高级会员

积分
730
发表于 2024-11-18 23:21:31 来自手机 | 显示全部楼层
杨为民 发表于 2024-10-15 12:06
谢谢你的提问,我想这也是其他网友想了解的知识。

(1)C51/C251和金水151编译器的函数调用规范之一,如 ...

谢谢 理解了
STC 666 888
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 02:24 , Processed in 0.151567 second(s), 95 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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