0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用状态机设计方法重新设计嵌入式系统

电子设计 来源:eeweb 作者:Gartlan 2021-04-20 16:14 次阅读

我是嵌入式系统的讲师。我继承了一段运行良好的代码,但是由于缺少设计图,并且花了很多条件语句和标志,使我花了一些时间来理解。

该代码的目的是检测连接到微控制器端口的几个按钮之一何时被激活并记录事实。这些按钮为高电平有效,这意味着按下按钮时会在相应的引脚上产生高电压。开关弹跳的问题也已在固件中解决,因此同一引脚必须在预定的时间内保持高电平,然后才能被接受为有效引脚。

该代码每10毫秒调用一次,如果同一引脚为高电平,则计数器递增。当计数器达到预定义的值(在这种情况下为10)时,按钮按下被认为是有效的。因此,在这种情况下,在认为有效之前,引脚电压必须稳定在100mS的高电平。

为了更好地说明设计,并作为学生的状态机设计的另一个示例,我着手使用状态机设计方法重新设计系统。

状态机

状态机图如下图1所示。所述Button_PORT是定义为任何端口的按钮都连接到宏。这允许将按钮轻松移动到另一个端口。

#define Button_PORT PORTA

声明了一个联合,该联合将允许将按钮作为一个整体或单独进行访问。

typedef union {
 unsigned char Full;
 结构{
 无符号字符B0:1;
 未签名的字符B1:1;
 未签名的字符B2:1;
 未签名的字符B3:1;
 未签名的字符B4:1;
 未签名的字符B5:1;
 未签名的字符B6:1;
 未签名的字符B7:1;
 };
} Button_Type;

使用此类型定义了两个变量Button_PressTemp_Press。Button_Press在反跳后保留按钮的最终值,而Temp_Press在反跳过程中保留按钮的中间值。

在应用程序代码中,设置了一个计时器,每10毫秒产生一个中断,然后评估状态机。状态机图将此时间表示为TICK事件(TICK_E)的发生。

有以下四种状态:

等待中:等待端口上的任何按钮被激活。

检测到:按钮已激活,因此进入此状态,并使用Temp_Press记录按钮的端口值。每10毫秒,将再次检查按钮端口,并且-在其值仍然相同的情况下-计数器将递增。用状态机的话来说,该变量称为“扩展状态变量”。

WaitForRelease:如果计数器达到预定义的最小值'MIN_BUTTON_COUNT',则Temp_press现在被视为有效,并且进入WaitForRelease状态以等待按钮释放,直到变量Button_Press保留了最终的按钮值。

更新:按钮已释放,因此最终值Button_Press已用去抖动的临时值'Temp_Press'更新。

pIYBAGB-jLSAT1mYAAWndcDmQgE221.png

图1.按钮反跳状态机(来源:Thomas Gartlan)

该状态机绘制在www.draw.io上,并根据Miro Samek的书《C / C ++中的实用UML状态图:嵌入式系统的事件驱动编程》中的内容使用表示法来表示状态。

从教学的角度来看,此状态机是状态,事件,警戒条件,Do操作,OnEntry操作和扩展状态变量的一个很好的示例。

正如我们前面提到的,有四个状态。唯一的事件是10mS TICK_E。从“等待”到“检测到”的过渡中,TICK_E上有一个保护状态,[Button_PORT> 0],在这种情况下,这意味着某些按钮已被激活。“已检测”状态下的“ OnEntry”操作会重置计数器,而“已检测”状态下的“执行”操作会在计数器中递增。计数器本身是扩展状态变量。

与原始的以条件标记为中心的代码相反,此状态机图提供了非常清晰的设计视图,因此为学生提供了一个很好的示例。

实施

该设计是使用MPLABX IDE和XC8编译器实现的。目标器件是Microchip的8位PIC18F4520微控制器。该设计以易于重复使用的方式实现。如前所述,端口是使用宏定义的,因此可以轻松地对其进行更改。而且,该代码打包在一个库中并发布到GitHub,这使得它可以轻松地维护和在任何项目中使用。

库头文件包含按钮结构和端口信息。库C文件包含状态机功能。代码中使用的名称与状态机图相匹配,从而更易于理解和调试设计。函数指针并不是真正需要的,也没有使用,因为它们会使学生在此阶段对设计的理解更加复杂。状态机功能的代码如下所示。

typedef枚举{Waiting,Detected,WaitForRelease,Update}状态;
 
无效Find_Button_Press(void)
{
 静态状态Button_State =正在等待;
 静态无符号字符Button_Count = 0;
 静态Button_Type Temp_Press; 
 
 开关(按钮状态){
 案例(等待):
 如果(Button_PORT) 
 {
 Button_State =已检测到; 
 Button_Count = 0; 
 Temp_Press.Full =按钮_端口; 
 }
 休息;
 案例(检测):
 如果(Temp_Press.Full == Button_PORT)
 {
 ++ Button_Count; 
 如果(Button_Count> MIN_BUTTON_COUNT)
 {
 Button_State = WaitForRelease; 
 }
 }
 别的
 {
 Button_State =等待中; 
 }
 休息;
 案例(WaitForRelease):
 如果(!Button_PORT)
 {
 Button_State =更新; 
 }
 休息;
 案例(更新):
 {
 Button_Press = Temp_Press; 
 Button_State =等待中; 
 Button_Count = 0; 
 Temp_Press.Full = 0; 
 }
 休息;
 默认:
 {
 Button_State =等待中;
 Button_Count = 0;
 Temp_Press.Full = 0;
 Button_Press.Full = 0;
 }
 }
}

应用代码和测试

开发了一个简单的应用程序来说明和测试该设计。该应用程序测试代码的一部分如下所示。包含头文件,并定义了Button_Press变量。对头文件的唯一修改是定义用于按钮的端口。

/ ***************************************************** ***
 包括图书馆
****************************************************** *** /
#include 
#include 
#include“ Buttons_Debounce.h” 
 
Button_Type Button_Press; //创建Button变量
 
/ ****************************************************
 功能原型
****************************************************** /
void Initial(void);
void delay_s(unsigned char secs);
 
/ *****************************************************
 钟
****************************************************** /
#define _XTAL_FREQ 19660800
 
unsigned char count_test = 0;
void __interrupt myIsr(void)
{
 //定时器每10毫秒溢出一次
 if(INTCONbits.TMR0IE && INTCONbits.TMR0IF){ 
 Find_Button_Press(); //每10毫秒调用一次
 WriteTimer0(40960);
 INTCONbits.TMR0IF = 0; //清除此中断条件
 
 }
}
 
void main(无效)
{
 Button_Press.Full = 0x00;
 最初的();
 而(1)
 {
 if(Got_Button_E)//如果已按下某个按钮
 {
 if(Button_Press.B0)//如果其按钮为0
 PORTCbits.RC0 =〜PORTCbits.RC0;
 
 if(Button_Press.B1)//如果其按钮为0
 PORTCbits.RC1 =〜PORTCbits.RC1; 
 
 if(Button_Press.B2)//如果其按钮为0
 PORTCbits.RC2 =〜PORTCbits.RC2; 
 
 if(Button_Press.B3)//如果其按钮为0
 PORTCbits.RC3 =〜PORTCbits.RC3; 
 
 Button_Press.Full = 0x00; //清除所有按钮事件
 }
 }
}

将创建一个定时器中断,每10毫秒发生一次,并调用状态机功能。在此应用中,按钮连接到PORTB,而LED连接到PORTC。如果按下任何按钮,则相应的LED会切换而不会出现任何延迟或弹跳问题。处理按钮值后,将清除整个变量。

总体而言,该项目被认为是在设计阶段如何使用状态机方法,从而导致更清晰,更不易出错的实现的一个很好的例子。

编辑:hfy
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 微控制器
    +关注

    关注

    48

    文章

    7311

    浏览量

    149785
  • 嵌入式系统
    +关注

    关注

    40

    文章

    3511

    浏览量

    128742
  • 计数器
    +关注

    关注

    32

    文章

    2238

    浏览量

    93866
  • 状态机
    +关注

    关注

    2

    文章

    489

    浏览量

    27373
收藏 人收藏

    评论

    相关推荐

    嵌入式状态机的几种大牛才懂的操作

    状态机嵌入式软件中随处可见,可能你会说状态机有什么难的,不就是 switch 吗? switch仅仅是最基础的一个点,关于状态机的更多操作,或许你都没有见过,下面分享几种实现
    发表于 11-17 10:41 1353次阅读
    <b class='flag-5'>嵌入式</b><b class='flag-5'>状态机</b>的几种大牛才懂的操作

    嵌入式软件开发中常用的状态机编程实现

    嵌入式软件开发中,状态机编程是一个十分重要的编程思想,它也是嵌入式开发中一个常用的编程框架。掌握了状态机编程思想,可以更加逻辑清晰的实现复杂的业务逻辑功能。
    发表于 09-06 10:25 1739次阅读

    嵌入式系统中串口通信帧的同步方法

    比较、基于FIFO队列和基于状态机的3种帧同步方法通过测试、分析和比较得出,基于有限状态机方法嵌入式
    发表于 10-09 19:17

    基于状态机嵌入式系统开发

    给大家分享下,基于状态机嵌入式系统开发,慢慢看吧
    发表于 12-22 19:44

    嵌入式系统的描述与设计

    嵌入式系统的描述与设计》是2007年机械工业出版社出版的图书,作者是盖斯基。本书介绍嵌入式系统领域的基本概念以及实际的描述和设计方法,包括
    发表于 10-27 09:39

    高速环境下FPGA或CPLD中的状态机设

        本文给出了采用这些技术的高速环境状态机设计的规范及分析方法和优化方法,并给出了相应的示例。       为了使FPGA或CPLD中的
    发表于 04-15 11:27 635次阅读
    高速环境下FPGA或CPLD中的<b class='flag-5'>状态机设</b>计

    状态机嵌入式系统中的应用

    为了便于研究和描述状态机嵌入式前后台软件系统中的应用,本文将以移动2G光纤直放站近端机的监控软件案例来阐述和说明。
    发表于 05-23 10:48 2082次阅读
    <b class='flag-5'>状态机</b>在<b class='flag-5'>嵌入式</b><b class='flag-5'>系统</b>中的应用

    嵌入式软件中状态机的抽象与实现

    文中提出了 在嵌入式软件中把状态机作为一个独立模块从控制模块中抽象出来的思想 , 描述了 抽象出来的状态机模块 。 并介绍了 如何将这种状态机抽象模块应用到实际项目中 。
    发表于 03-22 15:47 1次下载

    有限状态机嵌入式系统中的实现及应用

    如何使嵌入式软件代码更加可靠 增强程序的可维护性 一直以来都是嵌入式程序员追 求的目标。论述了有限状态机的原理和其实现方法;采用状态机
    发表于 03-22 15:40 1次下载

    有限状态机嵌入式软件中的应用

    有限状态机嵌入式软件中的应用,感兴趣的小伙伴们可以看看。
    发表于 07-26 10:43 27次下载

    基于有限状态机嵌入式系统串口通信帧同步方法设计

    同类型或其他类型的中断,从而造成主程序得不到执行或后续中断数据丢失。所以,嵌入式系统中的串口通信虽然看似简单,但其中仍有许多问题值得研究,例如串口通信过程中的帧同步问题。本文针对该问题给出了逐次比较、基于FIFO队列和基于状态机
    发表于 04-10 08:48 2457次阅读
    基于有限<b class='flag-5'>状态机</b>的<b class='flag-5'>嵌入式</b><b class='flag-5'>系统</b>串口通信帧同步<b class='flag-5'>方法</b>设计

    嵌入式状态机的设置

    状态机嵌入式软件中随处可见,可能你会说状态机有什么难的,不就是 switch 吗?
    的头像 发表于 11-02 09:04 984次阅读

    嵌入式状态机的编程优点分析

    嵌入式状态机编程是真的好用,写出来的程序结构非常清晰!所以平时用的也比较多。
    的头像 发表于 02-25 16:21 757次阅读

    嵌入式状态机的设计与实现

    嵌入式状态机是一种常用的软件设计模式,它能够提高代码的可读性和可维护性。状态机是一个抽象的概念,它描述了一个系统或者组件的不同状态以及在不同
    的头像 发表于 04-14 11:55 1492次阅读

    LSM6DSOX嵌入式有限状态机的使用和配置

    电子发烧友网站提供《LSM6DSOX嵌入式有限状态机的使用和配置.pdf》资料免费下载
    发表于 07-31 10:55 4次下载
    LSM6DSOX<b class='flag-5'>嵌入式</b>有限<b class='flag-5'>状态机</b>的使用和配置