前言
本文对一款基于stm32实现的扫地机器人程序进行分析。
链接: 某款stm32扫地机器人程序
扫地机器人通过串口接收或发送数据,数据包括控制端向扫地机器人发送的控制指令,扫地机器人向控制端反馈当前状态等。
从串口接收数据里解析出来的数据放在FR_Rx
变量中,其结构体为:
/*帧接收记录*/
__packed typedef struct
{
Frame_t tFrame;//帧信息
u8 DataBuf[FRAME_DATA_MAX_LENGTH];//帧数据
u8 NextFrameSeq;//下次应该的序列
u8 ContinueErrNum;//连续错误次数
bool IsStartReceive;//是否开始接收
bool IsFrameNotProcess;//帧数据还未处理
FrameErr_e FrameErrType;//帧错误类型
}Rx_FrameRecord;
这是控制端向扫地机器人发送的数据。
向控制端发送的数据,在放入串口发送缓冲区之前先放在变量FR_Tx
里,其结构体为:
/*帧发送记录*/
__packed typedef struct
{
Frame_t tFrame;//帧信息
u8 DataBuf[FRAME_DATA_MAX_LENGTH];//帧数据
u8 NextFrameSeq;//下次应该的序列
bool IsSendOut;//是否发送了一帧数据?
bool IsReceiveRespond;//是否接受到回应
}Tx_FrameRecord;
这是扫地机器人向控制端发送的数据。
由于FR_Rx
和FR_Tx
是全局变量,可见整个系统同一时刻只处理一条接收数据或者发送数据。
对串口接收数据解析,或者对串口发送数据组帧的任务都在Protocol
文件夹里。
FrameHandle.c
void vFrameDataHandlerTask(void *p)
帧处理函数任务,将串口接收到的数据解析为协议帧数据。
处理步骤:
1、查看串口1缓冲区是否有新接收到的数据,并且FR_Rx
里没有未被处理的接收数据,符合条件则对串口1接收数据进行解析。
2、从串口1接收缓冲区里对数据进行解析,执行代码为:
eFrame_Analy(ucUSART1ReceiveBuffer[ucUSART1ReadBufferIndex],length,&FR_Rx);//解析数据
其中
ucUSART1ReceiveBuffer[ucUSART1ReadBufferIndex]
是串口1接收数据存放缓冲区。
length
是该缓冲区中数据长度。
FR_Rx
是解析出来的有效数据存放的接收数据帧。
3、判断接收到的数据帧类型不是回复帧,就通过
ucCode_RespondFrame(&FR_Tx,&FR_Rx,ucUSART1TrainsmitBuffer[ucWtiteDataToUSART1TransmitGrooveIndex]);
组一个接收数据的回复帧,并放到串口发送缓冲区中等待发送。
4、如果判断到接收数据帧里此刻有未被处理的数据帧,则根据帧类型进行分类数据。
5、调用
vFrameAutoResendByUsart1(&FR_Rx);
判断发送数据是否有回复帧,如果回复帧表示需要重发,或者超时未接收到回应帧(回复帧),则进行重发。
源码:
void vFrameDataHandlerTask(void *p)
{
u8 length=0;
while(1)
{
/*串口接收到数据 并且帧数据已经全部处理完毕*/
if(ucUSART1_ReceiveMessageNumber && FR_Rx.IsFrameNotProcess == false)
{
length=ucUSART1ReceiveBufferLength[ucUSART1ReadBufferIndex];//获取接收数据的长度
eFrame_Analy(ucUSART1ReceiveBuffer[ucUSART1ReadBufferIndex],length,&FR_Rx);//解析数据
USART1ReceiveDataReadDone( );//串口数据读取完毕
/*成功接收到的不是回应帧*/
if( FR_Rx.tFrame.FrameFunction != ffRespond )
{
/*配置回应帧*/
ucCode_RespondFrame(&FR_Tx,&FR_Rx,ucUSART1TrainsmitBuffer[ucWtiteDataToUSART1TransmitGrooveIndex]);