下面给出该方法在Keil C5l中的示例程序:
#include “regx52.h”
#define HEAD1 0x00
#define HEAD2 0x01
#define LEN 0x02
#define TYPE 0x03
#define DATA 0x04
#define CHECK 0x05
unsigned char g_DatRev[BUFLEN]; //接收缓冲区
unsigned char g_cmd;
unsigned char g_RecOk;
void main()
{
while(1)
{
if(g_RecOk)
{
g_RecOk=FALSE;
switch(g_cmd)
{ //相应处理程序
case: ...
break;
case: ...
break;
...
default:
}
}
}
}
void SerialComm() interrupt 4
{
static unsigned char RecState=HEAD1; //接收状态
static unsigned char len=0; //已接收的数据长度
static unsigned char CheckSum=0; //校验和
static unsigned char Len_total=0; //包长
if(RI)
{
RI=0;
swich(RecState)
{
case HEAD1:
if(SBUF==0xAA)
{
RecState=HEAD2;
}
break;
case HEAD2:
if(SBUF==0x55)
{
RecState=LEN;
}
else if(SBUF==0xAA)
{
RecState=HEAD2;
}
break;
case LEN:
RecState=TYPE;
Len_total=SBUF;
CheckSum=0xAA^0x55;
break;
case TYPE:
RecState=DATA;
g_cmd=SBUF;
CheckSum=CheckSum^SBUF;
len=0;
break;
case DATA:
g_DatRev[len]=SBUF;
CheckSum=CheckSum^SBUF;
len++;
if(len>=Len_total)
{
RecState=CHECK;
}
break;
case CHECK:
if(CheckSum==SBUF)
{
g_RecOk=TRUE;
}
RecState=HEAD1;
break;
default:
RecState=HEAD1;
break;
}
}
}
由于采用了状态机和消息机制的结构,上述设计思路快速有效地实现了串口通信的同步,而且程序结构清晰,便
于维护,也易于向其他的串口通信协议移植。另外,串口中断服务子程序中需要处理的工作很少,每个串口接收
中断平均耗时不超过20个机器周期(在单片机AT89C5l中),大大减轻了串口接收中断服务程序的压力,缓解了嵌
入式系统有限资源与需求之间的矛盾,提高了嵌入式系统的稳定性。
三、结论
从上面的分析和测试可以看出,基于有限状态机的串口通信帧同步方法是本文中提出的3种帧方法中最优的,结
构清晰且系统资源利用率高。
对一个有着完整通信协议的串口中断来说,因为要比较命令头、完成校验、解析数据等需要耗费大量的机器周期
,所以嵌入式系统中的串口中断服务程序设计显得更为重要。在实际的串口通信程序中,可采用状态机和消息机
制相结合的方法,仅在中断服务程序中设置一个标志,而在主程序中根据相应标志来作处理,这样就回避了某些
中断可能需要较长处理时间的问题。在程序结构上,由于采用状态机的结构,既提高了可读性。同时又提高了运
行速度,因而该方法不仅是一种很好的帧同步方法,还是一种很不错的串口通信程序设计方法。