串口通信识别一帧数据的起始与结束标志位

下面给出该方法在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种帧方法中最优的,结 构清晰且系统资源利用率高。

对一个有着完整通信协议的串口中断来说,因为要比较命令头、完成校验、解析数据等需要耗费大量的机器周期 ,所以嵌入式系统中的串口中断服务程序设计显得更为重要。在实际的串口通信程序中,可采用状态机和消息机 制相结合的方法,仅在中断服务程序中设置一个标志,而在主程序中根据相应标志来作处理,这样就回避了某些 中断可能需要较长处理时间的问题。在程序结构上,由于采用状态机的结构,既提高了可读性。同时又提高了运 行速度,因而该方法不仅是一种很好的帧同步方法,还是一种很不错的串口通信程序设计方法。

经验分享 程序员 微信小程序 职场和发展