杨为民
发表于 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毫秒
}
晓飛飛
发表于 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等等,还可以大幅度降低进入定时中断的周期,提高效率。
//1ms中断程序,写字板里面写的代码,未经验证,如有错误请自行排查,
//大概思路就是如下
void Timer0_Isr(void) interrupt 1
{
static unsigned char sta; //状态变量
static unsigned int delay; //定时变量
switch(sta)
{
case 0: //状态机初始状态
P0=~0x011; //第一拍动作,只执行一次
delay = 300; //设置定时值,倒计时方法,
sta = 1; //转下个状态
break;
case 1: //第二拍动作
if(delay)delay--;//定时变量倒计时,延迟没到就减一
else //延迟到了转下个动作,配置下个延迟
{
P0=~0x55;
delay = 200;
sta++; //转下个状态
}
break;
case 2: //第三拍动作
if(delay)delay--;
else
{
P0=~0xAA;
delay = 350;
sta++; //转下个状态
}
break;
case 3: //第四拍动作
if(delay)delay--;
else
{
P0=~0x0f;
delay = 150;
sta++; //转下个状态
}
break;
case 4: //第一拍动作
if(delay)delay--;
else
{
P0=~0x011;
delay = 300;
sta = 1; //转第二拍动作
}
break;
default:
sta = 0;
break;
}
}
void Timer0_Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初始值
TH0 = 0xD4; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
杨为民
发表于 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
(出处: 国芯技术交流网站)
晓飛飛
发表于 2024-11-5 23:43:55
杨为民 发表于 2024-11-5 22:58
谢谢。
5,你不能把观点说成事实,你的观点不是也不可能是正确与否的标准
6,话不要说太满,“最”有代表性,我认为能代表您自己的认知范围即可
4,对于状态机有很多模式和维度的概念,OS调度系统也是在状态机基础上发展而来的,状态机放中断服务程序中,可不止能实现您所谓“极简单例子”,方法得当可堪大用,实现复杂逻辑和时序不在话下,包括很多软异步串口、软I2C、软SPI都轻松搞定。中断阻塞是什么概念,只有在中断里面用傻delay才会阻塞。
3,软件延时是傻delay,只是我对此一种可爱的称呼,对于us级软件延迟我也用,偶尔用几个nop也无伤大雅,但存在阻塞且效率低不能否认吧,单片机和人一样,等待的时候杵在那里数绵羊不傻么,还不如睡个觉打个盹喝个蜜雪冰城。搞过低功耗应用开发的都知道,主循环里面貌似只有一件事情,那就是“睡觉”,具体功能业务由各种中断唤醒即可。这和RTOS低功耗设计的机制是一样的。
PS,每个人有不同的价值观,技术也一样,综上,我只是表达我的观点,您也没必要高高在上的视角,像一个老师一样给我出各种考题,咱俩不是一种思维方式,没必要继续纠结谁对谁错。
杨为民
发表于 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楼两种风格的程序。至于他们认为谁对谁错,这是他们的权利。
晓飛飛
发表于 2024-11-6 01:12:28
杨为民 发表于 2024-11-6 01:04
(1)既然在你的语言“傻”是可爱的称呼,那我21楼也只是给傻傻的你一个傻傻的机会而已。
(2)这个机会 ...
关于这个“傻傻”不也本来是您的观点么,既然所见略同,就没什么好辩的了
wlhet
发表于 2024-11-18 23:21:31
杨为民 发表于 2024-10-15 12:06
谢谢你的提问,我想这也是其他网友想了解的知识。
(1)C51/C251和金水151编译器的函数调用规范之一,如 ...
谢谢 理解了