浅谈有限状态机——单片机串口实现

7月3日来到实验室,现在算起来刚好又三个月了,一年的四分之一。谈一谈自己的小感悟
刚来看我导师的代码,中间又被我导师提醒。才恍然大悟遇到的第一个小练手竟然是有限状态机算法。
在学习数电时序电路的时候,描述元器件的一种方式是状态转换表与状态转换图。有限状态机是从逻辑学直接导出的,状态机是数字电路的基本设计单元,能接受时钟的时序控制。个人感觉其原理类似。都是从一个状态经过特定条件跳转到另外一个状态。
由于练手项目,已商用。下面我以一个简单的例子为例。阐述一下我的代码及其思路:
在这里插入图片描述
在数字电路中最容易见到的就是类似于这样的状态转换图。通过上图可以直到两种情况下存在输出。一是当前状态为111,输入为1;另一种为当前状态为001,输入为1。假设进入111和001的状态必须为如图。即100 -->101 -->110–>111,011–>010–>001这样的状态才为1。这种情况大多应用于读取串口、读取内存的时候,存在着协议,必须顺序读入的情况。以串口为例,在单片机中串口的读取过程中容易出现不及时。解决方法是增加缓存,将读取到的数据存放在buff中,之后再访问buff。因此需定义一个数组作为buff。之前在微信公众账号上看到有人写了一个队列作为buff。其原理类似。
其中main文件

#include "stc8.h"
#include "MSG_DATA.H"
#include "BSP_Uart.h"
#include "TEST.h"

void main(void)
{	
	Data_Init();			//数据初始化        								
	Time0_Step();			//定时器初始化												
	COM1_Step(0);                   //Uart1初始化 ,其中波特率为9600          
	EA=1;																			
	Uart3sendstr("init ok");        
	
	while(1)
	{
	  Get_MSG();		//抓包						
	  if(bFlag_MSGisOK==1)				
	   {
	      HandleMSG();      //数据处理
	      bFlag_MSGisOK=0;
	   }
	}
}

其中抓包程序

#include "test.h"
#include "bsp_uart.h"

//
//Fuction:void Uart_SaveTo_RxBuf(BYTE rx_data)
//Description:存储在buff中
//Parameter:rx_data存储的内容
//return:无
/
void Uart_SaveTo_RxBuf(BYTE rx_data)
{
	if(Uart_Rx_WRpt<=Uart_Rx_size)
	{
		Uart_Rx_buf[Uart_Rx_WRpt++]=rx_data;
	}
}

//Fuction:Uart_RxBuf_Clr()
//Description:清空BUFF
//Parameter:无
//return:无
///
void Uart_RxBuf_Clr(void)
{
	Uart_Rx_WRpt = 0;
}

//Fuction:void Get_MSG()
//Description:抓包
//Parameter:无
//return:无
///
void Get_MSG()
{
	BYTE rx_data;
	
	if(index_WR != index_RD)
	{
		rx_data = Uart_In_buf[index_RD];
		index_RD  =(index_RD+1)%2048;
		if(mode)													//mode Ñ¡ÔñËıßÐÎ
		{
			switch(State)
			{
				case 0:
					if((rx_data == 4)||(rx_data == 3)
					{
						if(rx_data == 4)
						{
							State = 1;
							Uart_RxBuf_Clr();
							Uart_SaveTo_RxBuf(rx_data);
						}
						else
						{
							mode  = 0;
							State = 1;
							Uart_RxBuf_Clr();
							Uart_SaveTo_RxBuf(rx_data);
						}
							break;
					}
				
				case 1:
					if(rx_data == 5)
					{
						State = 2;
						Uart_SaveTo_RxBuf(rx_data);
					}
					else
					{
						State = 0;
						Uart_RxBuf_Clr();
					}
					break;
					
				case 2:
					if(rx_data == 6)
					{
						State = 3;
						Uart_SaveTo_RxBuf(rx_data);
					}
					else
					{
						State = 0;
						Uart_RxBuf_Clr();
					}
					break;
					
				case 3:
					if(rx_data == 7)
					{
						State = 3;
						Uart_SaveTo_RxBuf(rx_data);
						bFlag_MSGisOK = 1;
					}
					else
					{
						State = 0;
						Uart_RxBuf_Clr();
					}
					break;
					
				default:
					State = 0;
					Uart_RxBuf_Clr();		
			} 
		}//if(mode)
		else
		{
			switch(State)
			{
				case 0:
					if((rx_data == 4)||(rx_data == 3)
					{
						if(rx_data == 3)
						{
							State = 1;
							Uart_RxBuf_Clr();
							Uart_SaveTo_RxBuf(rx_data);
						}
						else
						{
							mode  = 1;
							State = 1;
							Uart_RxBuf_Clr();
							Uart_SaveTo_RxBuf(rx_data);
						}
							break;
					}
					
				case 1:
					if(rx_data == 2)
					{
						State = 2;
						Uart_SaveTo_RxBuf(rx_data);
					}
					else
					{
						State = 0;
						Uart_RxBuf_Clr();
					}
					break;
					
				case 2:
					{
						if(rx_data == 1)
						{
							State = 0;
							Uart_SaveTo_RxBuf(rx_data);
							bFlag_MSGisOK = 1;
						}
						else
						{
							State = 0;
							Uart_RxBuf_Clr();
						}
					}
					break;
					
				default:
						State = 0;
						Uart_RxBuf_Clr();	
			}
		}
}

其中串口中断处理程序

void Uart1_Task() interrupt 4 using 1
{
	BYTE data c;
	ES=0;
	if(RI)
	{
		c=SBUF;
		Uart_In_buf[index_WR] = c;
		
		index_WR++;
		index_WR = index_WR %2048;
		RI=0;
	}	
	ES=1;
}

本人水平有限,如有错误,欢迎指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值