422串口协议解析逻辑设计讨论

以下分别是两种串口协议软件实现源代码、逻辑图、逻辑伪代码,针对实现进行讨论:

一、模型A的串口协议及解析

1.1 串口协议

帧头

帧计数

帧标识

有效数据区

填充字节

CRC校验和

数据区长度

帧尾

0x5A54

1Byte

0x00

48Byte

0x00

2Byte

0x32

0x5AFE

1.2 解析源代码

void appRS422FrameMsg(unsigned char *msgBuffer)
 {
	 int i;
	 unsigned short checkSum;
	 unsigned int recvCheckSum;
	 while(1)
	 {
		 UartRecData(RS422_CHANNEL,(char *)(msgBuffer),1);			/*采集串口数据帧头*/
		 if((msgBuffer)[0]!=0x5A)
			 continue;
		 UartRecData(RS422_CHANNEL,(char *)(msgBuffer)+1,1);		/*采集串口数据帧头*/
		 if((msgBuffer)[1]!=0x54)
			 continue;
		 for(i=0;i<RS422_FRAME_SIZE-2;i++)							/*去掉帧头,获取剩余帧数据*/
		 {
			 if(!UartRecData(RS422_CHANNEL, (char*)(msgBuffer)+2+i, 1))
			 {
				 LOG_ERR(" appRS422FrameMsg error!");
			 }
		 }

		 if((msgBuffer)[RS422_FRAME_SIZE-1] != 0xFE || (msgBuffer)[RS422_FRAME_SIZE-2] != 0x5A || (msgBuffer)[RS422_FRAME_SIZE-3] !=(RS422_FRAME_SIZE-8))
		      continue;											/*判断帧尾*/
		
		 /*CRC校验,使用时必须进行初始化处理*/
		 checkSum=GetCheckSum((msgBuffer)+4,(RS422_FRAME_SIZE-10));						/*计算数据区的校验和*/
		 
		 recvCheckSum=*((unsigned short*)((msgBuffer)+RS422_FRAME_SIZE-5));			/*获取串口帧中的校验和*/	 

		 if(checkSum != recvCheckSum)
		 {
			 LOG_ERR(" appRS422FrameMsg CRC checkSum error.");
			 continue;
		 }
		 return;
	 }
 }

1.3 逻辑图

 

 1.4 逻辑图伪代码

@startuml

title RS422Process.c\n <b>appRS422FrameMsg(unsigned char *msgBuffer)</b>
start
repeat
	:UartRecData();
	if((msgBuffer)[0]==0x5A?) then (     **NO**)
	else (**YES**)
		:UartRecData();
		if((msgBuffer)[0]==0x54?) then (     **NO**)
		
		else (**YES**)
			'group collect frame data excpte head
			partition #lightGreen "**collect frame data excpte head**"{
			:i=0;
			repeat
				if(!UartRecData()) then (**YES**)
					:LOG_ERR(" appRS422FrameMsg error!");
				else(      **NO**)
				
				endif
			repeat while(i++<RS422_FRAME_SIZE-2)
			'end group
			}
			if(FRAME[END]!= 0xFE || FRAME[END-1] != 0x5A || FRAME lens!=(RS422_FRAME_SIZE-8)) then(**NO**)
			
			else (**YES**)
				:GetCheckSum();
				:recvCheckSum;
				if(checkSum != recvCheckSum)
					:LOG_ERR(" appRS422FrameMsg CRC checkSum error.");
				else
				endif
				stop
			endif
			
		endif
	endif
note left
//FRAME[END]!= 0xFE || FRAME[END-1] != 0x5A || FRAME lens!=(RS422_FRAME_SIZE-8) equ A//
//checkSum != recvCheckSum equ B//
end note
repeat while(msgBuffer)[0]!=0x5A? ||msgBuffer)[0]!=0x54? ||A ||B)	



@enduml

二、模型B的串口协议及解析

2.1 串口协议

字节号

意义

说明

1

0x5A

帧头

2

0x54

帧头

3

帧类型

数据区

4

帧序号

5~n

帧数据

n+1

0x00

校验和

n+2

累加和

n+3

数据区长度

数据区长度

n+4

0x5A

帧尾

n+5

0xFE

帧尾

2.2 解析源代码

int MA_RS422RcvDataCallBack(int chl,unsigned char* buff,int num)
{
#if 1
	int i=0,beginI,endI,k,d,isFlag,inFlag,cnt,datak=0;
	int length=0,readmax=0,transi=0;
	unsigned char temp[2];
	memset(temp,0,sizeof(temp));
	unsigned short  checkSum;
	
	short tempRS422Backinfo;
	inFlag=0;/*判断全缓存区是否找到帧头,一旦找到帧头inFlag赋值1,否者将num长度数据区丢弃*/

		
		for (i = 0; i < num; ++i) {
	        /*-------同步过程,判断是否有帧头帧尾-------------*/
			if((buff[i] == 0x5a) && (buff[i+1] == 0x54))
			{
				inFlag=1;									/*表示找到帧头*/
				beginI = i;									/*帧头位置*/
				endI   = i+1;								/*帧长度位置 */
				isFlag = 0;  								/*找到合格帧头帧尾标志位,0表示没有找到,1表示找到 */
				readmax=min(endI+256,num);					/*预处理,每次最多处理256字节缓存区*/
				while((endI++) && (endI<readmax))			
				{  
					/*寻找帧尾:排除转义情况*/
					if((buff[endI] != 0x00) && (buff[endI+1] == 0x5a) && (buff[endI+2] == 0xfe))
					{
						isFlag = 1;							/*找到帧尾*/
						break;
					}
				}
			
				if(isFlag==1)
				{
					/*录入数据*/	
					if(startRS422RecvLog)							/*记录所找到帧的原始帧数据*/
					{
						LW_InputData(buff + beginI, endI+3-beginI);	/*帧起始位beginI,帧长度endI+3-beginI=endI-beginI+1+2*/
					}

					/*修改已处理的数据长度*/
					i+=endI-beginI+3;								/*endI-beginI+1+2 表示一帧长度*/
					length = endI+2+1;								/*返回已经处理的数据区长度*/
									
					/*---------校验过程,判断数据长度和校验和---------*/		
					d = (int)buff[endI];							/*有效数据字节数*/
					if(d<143)           							/*判断数据长度是否少,如果数据区长度小于标准143字节,不处理*/
					{
						continue;
					}
					if((endI-beginI-4)!=d)                          /*判断实际数据长度是否与帧内标定的数据长度一致,不一致不处理,endI-beginI-4=endI-beginI+1-3-2,即去掉帧头和校验位*/
					{
						continue;
					}
					/*对422下行帧累加和进行校验*/
					checkSum = 0;
					for(cnt=0; cnt<buff[endI]; cnt++)
					{
						checkSum += buff[beginI+cnt+2];
					}
					memcpy(temp,&checkSum,sizeof(short));
					if(buff[endI-1] != temp[0])
					{
						continue;
					}
					
					/*------------去除转义字符(与143字节不符则抛弃)------------*/

					for(k=0;k<d;k++)
					{
						if((buff[k+beginI+2]==0x00) && (buff[k+beginI+3]==0x5a) && (buff[k+beginI+4]==0xfe))
						{
							transi++;									/*出现转义字符累加*/
							continue;
						}
						RS422DownInfo.Data[datak] = buff[k+beginI+2];	/*转义后的数据填入串口结构体变量*/
						datak++;										/*datak是串口结构体中Data[143]的索引*/							
						if(datak>=143)									/*1)当datak>=143时,表明原数据区中去除转义后的数据长度不对,退出转义过程,该帧将在后面丢弃不处理*/										
						{
							break;
						}						
					}	
					if((143+transi)<d)   								/*与上一条1)联合判断是否有非转义字符造成的数据长度过长,*/
					{
						continue;
					}
					transi=0;
					datak=0;
					u_rs422res_clock = 0;   							
					/*--------数据解析并存入Udp发送的结构体--------*/
		
					do something;

				}
				else
				{
					 length=beginI;
				}		
			}	
		}
	}	
	
	if(0==inFlag)
	{
		length=num;   						 /*表示扫描全数据区,没有找到帧头,全数据区丢弃*/
	}
	
	return length; 
#endif	
}

2.3 逻辑图

 

 2 .4 逻辑图伪代码

@startuml

title MainApp.c\n <b>int MA_RS422RcvDataCallBack(int chl,unsigned char* buff,int num)b>
start
	if(chl == RS422RecChl?) then (   **YES**)
		:i=0;
		repeat
			if((buff[i] == 0x5a) && (buff[i+1] == 0x54)) then (   **YES**)
				:readmax=min(endI+256,num);
				partition #lightGreen "**collect frame data excpte head**"{
				while((endI++) && (endI<readmax)?)
					if((buff[endI] != 0x00) && (buff[endI+1] == 0x5a) && (buff[endI+2] == 0xfe)) then (   **YES**)
						:isFlag = 1;
						break
				
					else (**NO**)
					
					endif
				endwhile
				}
				if(isFlag==1?) then (   **YES**)
					if(startRS422RecvLog) then (   **YES**)
						:LW_InputData(buff + beginI, endI+3-beginI);
					else (**NO**)
					endif
					
					:i+=endI-beginI+3;
					:length = endI+2+1;
					:d = (int)buff[endI];
					if(d<143 || (endI-beginI-4)!=d ?) then (   **YES**)
					
					else (**NO**)
						partition #lightGreen "**cac check sum**"{
						:cnt=0;
						repeat
							:checkSum += buff[beginI+cnt+2];
						repeat while(cnt++<buff[endI]?)
					
						}
					
						if(buff[endI-1] != temp[0] ?) then (   **YES**)
					
						else (**NO**)
							partition #lightGreen "**cal ESC 0x00**"{
							:k=0;
							repeat
								if(A ?) then (   **YES**)
									:transi++;	
								else  (**NO**)
									:RS422DownInfo.Data[datak] = buff[k+beginI+2];
									if(datak++>=143?) then(   **YES**)
										break
									else (**NO**)
									
									endif
								endif
							repeat while(k++<d?)
							if((143+transi)<d?) then(   **YES**)
							
							else (**NO**)
								:udp send data process;
								
							endif

							}
					
						endif
					
					endif
					
				else
					:length=beginI;
				
				endif
	
			else (**NO**)
			
			endif
		repeat while(i++<num )	
	else (**NO**)
	endif
	if(0==inFlag?) then (   **YES**)
		:length=num; 
	else (** NO**)
	endif
	:return length;
	stop



@enduml

三、针对两种串口协议实现逻辑进行讨论!

1)可以提出指出以上设计问、编码问题、逻辑图问题等等,并给出优化方案,给出源代码和逻辑图。

2)可以提出自己的实现方法并回复源代码和逻辑图。

  • 5
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值