在很多串口通信的模块调试过程中,往往会出现一些特定的协议,它规定你需要按照一定的格式发送数据给他,否则模块不能够正常工作,最简单的例子就是ESP8266(AT指令固件版本),想通过串口配置这个模块实现各种功能,你就必须发送AT+XXXXX=XXXX这种格式的内容,具体需要查询手册。而在使用串口屏时,你也需要发送一定格式的数据例如0xff”hello”0xff,诸如此类的通信格式,我们就叫他帧通信。
下面以一个很常见的工业通信协议Modbus为例,介绍何为帧通信
由上图我们可以看出,在modbus协议中,一帧数据包含了起始符、设备地址、功能代码、数据、校验、结束符这么多内容。两个设备要通过该协议通信,那么就必须按照这个协议发送数据,接收方则必须按照该协议解析数据
这就是帧通信。
下面我们自己定义一个帧格式,并通过该格式来与开发板通信并控制LED的亮灭
起始符:0xaa
设备码:1个字符 0x01表示LED灯
功能码:1个字符 0x00表示关灯 0x01表示开灯
结束符:0xff
下面开始代码的编写,此工程承接了串口通信-中短篇的配置
修改main.c代码
在USER CODE BEGIN PV下定义如下变量**
uint8_t Rx_Buff[4];
uint8_t Rx_Flag = 0;
uint8_t Err_Flag =0;
在USER CODE BEGIN 2下添加如下代码,此处用到了串口实现printf可参考串口重定向实现printf
printf("Head->0xaa Device->0x01 LED->0x00/0x01 End->0xff");
HAL_UART_Receive_IT(&huart1,(uint8_t*)Rx_Buff,sizeof(Rx_Buff));
在USER CODE BEGIN3下添加如下代码
if(Rx_Flag == 1)
{
Rx_Flag = 0;
//开始解析数据
if(Rx_Buff[0] == 0xaa && Rx_Buff[3] == 0xff)//判断起始符和结束符
{
if(Rx_Buff[1] == 0x01)//判断设备码
{
if(Rx_Buff[2] == 0x00)//判断功能码
{
HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET);
printf("LED0 is Close!\r\n");
}
else if(Rx_Buff[2] == 0x01)
{
HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_SET);
printf("LED0 is Open\r\n");
}
else
{
Err_Flag = 1;//功能码错误标志
}
}
else
{
Err_Flag = 1;//设备码错误标志
}
}
else
{
Err_Flag = 1;//起始符和结束符错误标志
}
if(Err_Flag == 1)//发送错误提示信息
{
printf("Data error please send again!\r\n");
}
//清楚错误标志和缓冲区,准备下次接收
Err_Flag = 0;
memset(Rx_Buff,0,sizeof(Rx_Buff));//使用该函数需添加string.h
}
实验结果