原创 【博客大赛】有限状态机(FSM)在嵌入式软件中的应用之二 编程实例

2013-11-28 10:20 2818 18 23 分类: MCU/ 嵌入式 文集: STM32F1学习笔记

现在用有限状态机的思想来写段程序。

硬件平台:STM32F103

软件平台:Keil uv4

说明:这段程序中用在STM32USART串口中断里面,接收来自上位PC的一帧的数据,完成后向PC端做出应答,表示接收完成。

 

先把状态转移图贴上吧。这是手绘的,因为我的visio打开老有问题,只好手画了一个。简单说一下,上位发送给下位的一帧数据长度不定,帧头用0x55开始,数据帧的第二个字节为数据帧的长度,第三个字节开始后面是数据。要说明一下,第二字节的长度,是指后面从第三个字节开始跟的数据的长度,也就是说,整个数据帧的长度,就是第二个字节的内容+2.

状态的切换是这样的,先是在“WaitState”,等待数据,当收到0x55后,跳到“ReadyState”,接收帧长度后就直接跳到“BusyState”,这个状态会把整个帧的数据都接收完,完成后,跳到“ACKState”应答状态,向上位PC应答,而后跳回“WaitState”。

 

20131128101315332001.jpg

 

 

/***********************************************************************/

enum {WaitState = 0, ReadyState, BusyState, ACKState} CommState;//状态

u8 Rx_DataBuf[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//接收数据缓存

u8 ACKMessage[2] = {0xAA,0x55};//应答帧

u8 CommCnt,CommDataLen;//接收计数和表示数据长度的变量

 

void USART1_IRQHandler(void)//串口中断服务程序

{

         if((USART_GetFlagStatus(USART1, USART_FLAG_RXNE)) == SET)

         {

                   USART_ClearITPendingBit(USART1, USART_IT_RXNE);

                   switch(CommState)         //状态机

                   {

                            case WaitState://等待状态

                            {

                                     Rx_DataBuf[CommCnt] = USART_ReceiveData(USART1);

                                     if(Rx_DataBuf[CommCnt] == 0x55)

                                     {

                                               CommCnt++;

                                               CommState = ReadyState;//如果是0x55,状态切换                             

                                     }

                                     break;

                            }

                            case ReadyState://准备状态,用来确定帧长度

                            {

                                     Rx_DataBuf[CommCnt] = USART_ReceiveData(USART1);

                                     CommDataLen = Rx_DataBuf[CommCnt];

                                     CommCnt++;

                                     CommState = BusyState;//切换到下一状态

                                     break;

                            }

                            case BusyState://忙状态,接收整个帧的数据

                            {

                                     Rx_DataBuf[CommCnt] = USART_ReceiveData(USART1);

                                     CommCnt++;

 

                                     if(CommCnt>=(CommDataLen + 2))

                                     {

                                               CommCnt = 0;                  

                                               CommState = ACKState;//接收完成,切换到下一状态

                                     }

                                     break;

                            }

                            case ACKState:

                            {

                                     USART1_Send(ACKMessage);

                                     CommState = WaitState;//应答上位,跳回等待状态

                            }

                            default:break;

                   }

         }

}

/****************************************************************************/

 

关于程序要做几点说明,一是这段程序是可用的,已经用在实际的项目里面,但完整的工程是不能分享给大家的,因为公司项目,只能分享这一部分用到FSM的部分;二是上面的CommState在初始化程序中已经初始化为WaitState,以及变量CommCnt 也被初始化为0;三是这段程序是最初用来测试用的,后面的加上了校验以及出错处理的机制,其实也就是再添加了几个状态,让控制逻辑上更严谨了,这个大家可以自己加上试试。

 

希望和大家分享的这点东西对您有帮助。

文章评论5条评论)

登录后参与讨论

用户377235 2015-6-27 10:37

要是能有画出状态图,可自动生成单片机代码,可测试、仿真的软件就好了

用户385411 2015-2-13 20:08

不错,这个方法不错,

用户604557 2014-8-23 18:36

楼主,你的这个程序很好,我发现你这个状态机的最后一个状态是需要上位机发一个字节任意数据,才能让下位机发送一个ACK确认信号。

用户427685 2013-12-19 13:31

很实用

用户95599 2013-12-6 10:16

good!
相关推荐阅读
飞言走笔 2017-01-06 21:56
2017,新的博客旅程
EDNChina 改版终于成功了!祝贺! 2017年,开始新的旅程~ ...
飞言走笔 2016-06-01 10:17
【博客大赛】《白鹿原》读后
《白鹿原》这本书已经买了很久,多次以来,都是只翻看几页,顶多几章就放下了,觉得这是一个大部头,得有足够的时间才行。前几天陈忠实先生去世的消息传来,让我很震惊和惭愧。 一口气读完这本书,畅快淋漓,又意...
飞言走笔 2016-03-26 16:42
【博客大赛】《毛斯朝》读后
这本书最早是在凤凰卫视曾子墨主持的一期关于沈志华先生的《世纪大讲堂》节目中知晓的。但是一直拖到今天才读完。 说实话,书的主要内容与当前官方的宣传口径有很多不一致的地方,而沈先生作为中国掌握苏联档...
飞言走笔 2016-03-08 13:46
【博客大赛】蓝牙4.0低功耗技术及其认证要求
详见附件 ...
飞言走笔 2016-02-02 14:20
【转】蓝牙4.0协议官方手册(一)——通用属性配置文件
转自:http://blog.csdn.net/jinzhichaoshuiping/article/details/43370009 通用属性配置文件 (GATT)——该说明书定义了通用属性配置...
飞言走笔 2016-01-31 23:24
【博客大赛】脑洞大开、三观重塑——《人类简史》读后
终于读完了《人类简史》,没有把这本书拖到二月份,这也是2016年读完的第一本书。之前也有所耳闻,但是没有太在意,倒是罗胖子的跨年演讲上偶然提到,不知怎么就勾起了阅读此书的欲望。 本文的标题用了“脑洞...
我要评论
5
18
关闭 站长推荐上一条 /2 下一条