目录
一、简介
1.1、开发环境
STM32CubeIDE V1.9。
1.2、摘要
用STM32实现Modbus-RTU模式的接收结束判断程序。
二、串口1程序内容
头文件声明串口1的内容:
#define ReceiveBufferSize 255 //接收缓存大小
extern uint8_t ReceiveBuffer[]; //串口1接收缓存数组
typedef enum
{
ReceiveFree, //接收空闲
ReceiveFinish, //接收完成
}UartReceiveState_TypeDef; //串口接收状态
extern struct UartFlag //串口标志位
{
UartReceiveState_TypeDef receive_state; //接收状态标志
}
U1FG;
extern struct UartVariable //串口变量
{
uint8_t receive_size; //接收长度
}
U1VE;
工程文件定义串口1的内容:
uint8_t ReceiveBuffer[ReceiveBufferSize]; //定义接收缓存数组
struct UartFlag U1FG = //串口1标志位
{
ReceiveFree, //初始化:接收状态=接收空闲
};
struct UartVariable U1VE = //串口1变量
{
0, //初始化:接收字节长度为0
};
串口1的子函数:
/*
* 功能:重新定义串口回调函数,处理串口1接收完成
* 输入:@huart:串口号,用于区别哪个串口产生的回调
* @Size:本次接收的字节长度
* 输出:无
*/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart == &huart1) //判定:串口1接收
{
U1FG.receive_state = ReceiveFinish; //设置:串口1接收完成
U1VE.receive_size = Size; //读取:串口1接收长度
}
}
三、Modbus程序内容
头文件声明Modbus的内容:
typedef enum
{
Modbus_OK, //执行完成
Modbus_ERROR, //执行错误
Modbus_NOP, //空操作
}ModbusResult_TypeDef; //Modbus程序执行结果
typedef enum
{
CRC_Nop, //未进行CRC校验
CRC_Success, //CRC校验成功
CRC_Error, //CRC校验错误
}CrcResult_TypeDef; //CRC校验结果
ModbusResult_TypeDef ModbusInitialize();
CrcResult_TypeDef ModbusEnd();
Modbus子函数:
/*
* 功能:Modbus初始化
* 输入:无
* 输出:Modbus函数执行结果
*/
ModbusResult_TypeDef ModbusInitialize()
{
HAL_StatusTypeDef result;
U1VE.receive_size = 0; //清零:串口1接收长度
result = HAL_UARTEx_ReceiveToIdle_IT(
&huart1, //串口1
ReceiveBuffer, //接收缓存
ReceiveBufferSize); //接收缓存字节长度
if(result == HAL_OK) return Modbus_OK; //初始化成功
else return Modbus_ERROR; //初始化失败
}
/*
* 功能:ModBus接收结束判断
* 输入:无
* 输出:CRC校验结果
*/
CrcResult_TypeDef ModbusEnd()
{
uint16_t crc_buffer = 0;
if(U1FG.receive_state == ReceiveFinish) //判断:串口接收完成
{
U1FG.receive_state = ReceiveFree;
crc_buffer = ReceiveBuffer[-- U1VE.receive_size];
crc_buffer <<= 8;
crc_buffer += ReceiveBuffer[-- U1VE.receive_size];
if(crc_buffer == MdobusCRC(U1VE.receive_size,ReceiveBuffer))//判断:CRC校验成功
{
return CRC_Success; //返回:执行完成
}
else //判断:CRC校验失败
{
return CRC_Error; //返回:执行完成
}
}
else
{
return CRC_Nop; //返回:未执行
}
}
注:使用的函数“MdobusCRC”,详见Modbus查表法CRC校验程序_VIFIN的博客-优快云博客
四、使用示例
/*
* 功能:ModBus主程序
* 输入:无
* 输出:无
*/
void ModbusMain()
{
switch(ModbusEnd())
{
case CRC_Success:
//此处执行Modbus解码程序
while(ModbusInitialize() == Modbus_ERROR); //初始化:串口1的Modbus接收
break;
case CRC_Error:
//此处执行Modbus校验错误程序
while(ModbusInitialize() == Modbus_ERROR); //初始化:串口1的Modbus接收
break;
default:
//此处执行Modbus等待数据接收程序
break;
}
}