如题,首先要感谢一下“木蓝创智”在博客中分享他的Modbus Master的库,他的博文地址是:http://www.cnblogs.com/foxclever/p/7441384.html
最近需要搞一下关于Modbus主从一体的设备,之前只弄过一个Modbus从站设备,是移植FreeModbus的,个人比较懒,网上有现成的一般我也就不想细究了。所以到现在对Modbus协议本身还不是很精通,弄主站设备时就有一种茫然的感觉。在这里就不得不感谢一下互联网了,在我的耐心寻找下就找到了上面所说的那篇博文。
话不多说了,我立马就把别人写好的代码给下下来了,打开一看,我又要感慨一下了,注释很详尽,还有一个函数开发功能文档。这对于一个懒人来说真是太好了。随后我就把他放到我的工程里,编译下载一切都很顺利。
但是在测试的时候出现问题了,我使用的是主站功能,但是从站总是会返回03的错误码,检查一看是主站数据发错了,又开始仔细的看代码,然后发现博主不小心留了几个错误给我,另外我也在这个基础上稍微改了几个地方,现在把它们贴出来吧
1、头文件修改
mbpdu.h
原文:
/*作为RTU主站(TCP客户端)时,生成读写RTU从站(TCP服务器)对象的命令*/
uint16_t GenerateReadWriteCommand(ObjAccessInfo objInfo,bool *statusList,uint16_t *registerList,uint8_t commandBytes[]);
改成
/*作为RTU主站(TCP客户端)时,生成读写RTU从站(TCP服务器)对象的命令*/
uint16_t GenerateReadWriteCommand(ObjAccessInfo *objInfo,bool *statusList,uint16_t *registerList,uint8_t commandBytes[]);
mbrtu.h
原文
/*生成读写从站数据对象的命令,命令长度包括2个校验字节*/
uint16_t SyntheticReadWriteSlaveCommand(ObjAccessInfo slaveInfo,bool *statusList,uint16_t *registerList,uint8_t *commandBytes);
改成
/*生成读写从站数据对象的命令,命令长度包括2个校验字节*/
uint16_t SyntheticReadWriteSlaveCommand(ObjAccessInfo *slaveInfo,bool *statusList,uint16_t *registerList,uint8_t *commandBytes);
mbrtumaster.h
原文
/*生成访问服务器的命令*/
uint16_t CreateAccessSlaveCommand(ObjAccessInfo objInfo,void *dataList,uint8_t *commandBytes);
/*解析收到的服务器相应信息*/
void ParsingSlaveRespondMessage(uint8_t *recievedMessage,uint8_t *command);
改成
/*生成访问服务器的命令*/
uint16_t CreateAccessSlaveCommand(ObjAccessInfo *objInfo,void *dataList,uint8_t *commandBytes);
/*解析收到的服务器相应信息*/
void ParsingSlaveRespondMessage(uint8_t *recievedMessage,uint8_t *command, uint16_t length);
mbtcp.h
原文
//生成读写服务器对象的命令
uint16_t SyntheticReadWriteTCPServerCommand(ObjAccessInfo objInfo,bool *statusList,uint16_t *registerList,uint8_t *commandBytes);
改成
//生成读写服务器对象的命令
uint16_t SyntheticReadWriteTCPServerCommand(ObjAccessInfo *objInfo,bool *statusList,uint16_t *registerList,uint8_t *commandBytes);
mbtcpclient.h
原文
/*生成访问服务器的命令*/
uint16_t CreateAccessServerCommand(ObjAccessInfo objInfo,void *dataList,uint8_t *commandBytes);
改成
/*生成访问服务器的命令*/
uint16_t CreateAccessServerCommand(ObjAccessInfo *objInfo,void *dataList,uint8_t *commandBytes);
2、源文件修改
mbpdu.c
原文
/*作为RTU主站(TCP客户端)时,生成读写RTU从站(TCP服务器)对象的命令*/
uint16_t GenerateReadWriteCommand(ObjAccessInfo objInfo,bool *statusList,uint16_t *registerList,uint8_t *commandBytes)
{
uint16_t index=0;
commandBytes[index++]=objInfo.unitID; //从站地址
commandBytes[index++]=objInfo.functionCode; //功能码
commandBytes[index++]=objInfo.startingAddress>>8; //起始地址高字节
commandBytes[index++]=objInfo.startingAddress; //起始地址低字节
/*读从站对象*/
if((objInfo.functionCode>=ReadCoilStatus)&&(objInfo.functionCode <= ReadInputStatus))
{
commandBytes[index++]=objInfo.quantity>>8;
commandBytes[index++]=objInfo.quantity;
}
/*写单个线圈数据对象*/
if((WriteSingleCoil==objInfo.functionCode)&&(statusList!=NULL))
{
commandBytes[index++]=(*statusList)?0xFF:0x00;
commandBytes[index++]=0x00;
}
/*写单个寄存器数据对象*/
if((objInfo.functionCode==WriteSingleRegister)&&(registerList!=NULL))
{
commandBytes[index++]=(*registerList)>>8;
commandBytes[index++]=(*registerList);
}
/*写多个线圈*/
if((objInfo.functionCode==WriteMultipleCoil)&&(statusList!=NULL))
{
commandBytes[index++]=objInfo.quantity>>8;
commandBytes[index++]=objInfo.quantity;
uint8_t byteArray[250];
uint16_t bytesCount=ConvertBoolArrayToMBByteArray(statusList,objInfo.quantity,byteArray);
commandBytes[index++]=bytesCount;
for(int i=0;i>8; //数量高字节
commandBytes[index++]=objInfo.quantity; //数量低字节
uint8_t byteArray[250];
uint16_t bytesCount=ConvertRegisterArrayToMBByteArray(registerList,objInfo.quantity,byteArray);
commandBytes[index++]=bytesCount; //字节数量
for(int i=0;i
改成
/*作为RTU主站(TCP客户端)时,生成读写RTU从站(TCP服务器)对象的命令*/
uint16_t GenerateReadWriteCommand(ObjAccessInfo *objInfo,bool *statusList,uint16_t *registerList,uint8_t *commandBytes)
{
uint16_t index=0;
commandBytes[index++]=objInfo->unitID; //从站地址
commandBytes[index++]=objInfo->functionCode; //功能码
commandBytes[index++]=objInfo->startingAddress>>8; //起始地址高字节
commandBytes[index++]=objInfo->startingAddress; //起始地址低字节
/*读从站对象*/
if((objInfo->functionCode>=ReadCoilStatus)&&(objInfo->functionCode <= ReadInputRegister))
{
commandBytes[index++]=objInfo->quantity>>8;
commandBytes[index++]=objInfo->quantity;
}
/*写单个线圈数据对象*/
if((WriteSingleCoil==objInfo->functionCode)&&(statusList!=NULL))
{
commandBytes[index++]=(*statusList)?0xFF:0x00;
commandBytes[index++]=0x00;
}
/*写单个寄存器数据对象*/
if((objInfo->functionCode==WriteSingleRegister)&&(registerList!=NULL))
{
commandBytes[index++]=(*registerList)>>8;
commandBytes[index++]=(*registerList);
}
/*写多个线圈*/
if((objInfo->functionCode==WriteMultipleCoil)&&(statusList!=NULL))
{
commandBytes[index++]=objInfo->quantity>>8;
commandBytes[index++]=objInfo->quantity;
uint8_t byteArray[250];
uint16_t bytesCount=ConvertBoolArrayToMBByteArray(statusList,objInfo->quantity,byteArray);
commandBytes[index++]=bytesCount;
for(int i=0;ifunctionCode==WriteMultipleRegister)&&(registerList!=NULL))
{
commandBytes[index++]=objInfo->quantity>>8; //数量高字节
commandBytes[index++]=objInfo->quantity; //数量低字节
uint8_t byteArray[250];
uint16_t bytesCount=ConvertRegisterArrayToMBByteArray(registerList,objInfo->quantity,byteArray);
commandBytes[index++]=bytesCount; //字节数量
for(int i=0;i
mbrtu.c
原文
/*生成读写从站数据对象的命令,命令长度包括2个校验字节*/
uint16_t SyntheticReadWriteSlaveCommand(ObjAccessInfo slaveInfo,bool *statusList,uint16_t *registerList,uint8_t *commandBytes)
改成
/*生成读写从站数据对象的命令,命令长度包括2个校验字节*/
uint16_t SyntheticReadWriteSlaveCommand(ObjAccessInfo *slaveInfo,bool *statusList,uint16_t *registerList,uint8_t *commandBytes)
mbrtumaster.c
原文
/*处理读从站状态量返回信息,读线圈状态位0x012功能码*/
static void HandleReadCoilStatusRespond(uint8_t *receivedMesasage,uint16_t startAddress,uint16_t quantity);
/*处理读从站状态量返回信息,读输入状态位0x02功能码*/
static void HandleReadInputStatusRespond(uint8_t *receivedMesasage,uint16_t startAddress,uint16_t quantity);
/*处理读从站寄存器值的返回信息,读保持寄存器0x03功能码)*/
static void HandleReadHoldingRegisterRespond(uint8_t *receivedMesasage,uint16_t startAddress,uint16_t quantity);
/*处理读从站寄存器值的返回信息,读输入寄存器0x04功能码*/
static void HandleReadInputRegisterRespond(uint8_t *receivedMesasage,uint16_t startAddress,uint16_t quantity);
/*判断接收到的信息是否是发送命令的返回信息*/
static bool CheckMessageAgreeWithCommand(uint8_t *recievedMessage,uint8_t *command);
void (*HandleSlaveRespond[])(uint8_t *,uint16_t,uint16_t)={HandleReadCoilStatusRespond,
HandleReadInputStatusRespond,
HandleReadHoldingRegisterRespond,
HandleReadInputRegisterRespond};
改为
/*处理读从站状态量返回信息,读线圈状态位0x012功能码*/
static void HandleReadCoilStatusRespond(uint8_t *receivedMesasage, uint8_t slaveID, uint16_t startAddress, uint16_t quantity);
/*处理读从站状态量返回信息,读输入状态位0x02功能码*/
static void HandleReadInputStatusRespond(uint8_t *receivedMesasage, uint8_t slaveID, uint16_t startAddress, uint16_t quantity);
/*处理读从站寄存器值的返回信息,读保持寄存器0x03功能码)*/
static void HandleReadHoldingRegisterRespond(uint8_t *receivedMesasage, uint8_t slaveID, uint16_t startAddress, uint16_t quantity);
/*处理读从站寄存器值的返回信息,读输入寄存器0x04功能码*/
static void HandleReadInputRegisterRespond(uint8_t *receivedMesasage, uint8_t slaveID, uint16_t startAddress, uint16_t quantity);
/*判断接收到的信息是否是发送命令的返回信息*/
static bool CheckMessageAgreeWithCommand(uint8_t *recievedMessage,uint8_t *command);
void (*HandleSlaveRespond[])(uint8_t *,uint8_t, uint16_t,uint16_t)={HandleReadCoilStatusRespond,
HandleReadInputStatusRespond,
HandleReadHoldingRegisterRespond,
HandleReadInputRegisterRespond};
原文
/*生成访问服务器的命令*/
uint16_t CreateAccessSlaveCommand(ObjAccessInfo objInfo,void *dataList,uint8_t *commandBytes)
{
uint16_t commandLength=0;
/*生成读服务器对象的命令,功能码0x01、0x02、0x03、0x04,命令长度12个字节*/
if((objInfo.functionCode>=ReadCoilStatus)&&(objInfo.functionCode <= ReadInputStatus))
{
commandLength=SyntheticReadWriteSlaveCommand(objInfo,NULL,NULL,commandBytes);
AddCommandBytesToList(commandBytes); /*记录发送的读命令*/
}
/*生成预置服务器对象的命令,功能码0x05,0x0F,命令长度随发送数据而变*/
if((objInfo.functionCode==WriteSingleCoil)&&(objInfo.functionCode==WriteMultipleCoil))
{
bool *statusList=(bool*)dataList;
commandLength=SyntheticReadWriteSlaveCommand(objInfo,statusList,NULL,commandBytes);
}
/*生成预置服务器对象的命令,功能码0x06,0x10,命令长度随发送数据而变*/
if((objInfo.functionCode==WriteSingleRegister)&&(objInfo.functionCode==WriteMultipleRegister))
{
uint16_t *registerList=(uint16_t*)dataList;
commandLength=SyntheticReadWriteSlaveCommand(objInfo,NULL,registerList,commandBytes);
}
return commandLength;
}
改为
/*生成访问服务器的命令*/
uint16_t CreateAccessSlaveCommand(ObjAccessInfo *objInfo,void *dataList,uint8_t *commandBytes)
{
uint16_t commandLength=0;
/*生成读服务器对象的命令,功能码0x01、0x02、0x03、0x04,命令长度12个字节*/
if((objInfo->functionCode>=ReadCoilStatus)&&(objInfo->functionCode <= ReadInputRegister))
{
commandLength=SyntheticReadWriteSlaveCommand(objInfo,NULL,NULL,commandBytes);
AddCommandBytesToList(commandBytes); /*记录发送的读命令*/
}
/*生成预置服务器对象的命令,功能码0x05,0x0F,命令长度随发送数据而变*/
if((objInfo->functionCode==WriteSingleCoil)&&(objInfo->functionCode==WriteMultipleCoil))
{
bool *statusList=(bool*)dataList;
commandLength=SyntheticReadWriteSlaveCommand(objInfo,statusList,NULL,commandBytes);
}
/*生成预置服务器对象的命令,功能码0x06,0x10,命令长度随发送数据而变*/
if((objInfo->functionCode==WriteSingleRegister)&&(objInfo->functionCode==WriteMultipleRegister))
{
uint16_t *registerList=(uint16_t*)dataList;
commandLength=SyntheticReadWriteSlaveCommand(objInfo,NULL,registerList,commandBytes);
}
return commandLength;
}
原文
/*解析收到的服务器相应信息*/
void ParsingSlaveRespondMessage(uint8_t *recievedMessage,uint8_t *command)
{
/*如果不是读操作的反回信息不需要处理*/
if(recievedMessage[1]>0x04)
{
return;
}
if(command==NULL)
{
/*判断接收到的信息是否有相应的命令*/
int cmdIndex=FindCommandForRecievedMessage(recievedMessage);
if((cmdIndex<0))
{
return;
}
command=commandMasterList[cmdIndex];
}
FunctionCode fuctionCode=(FunctionCode)recievedMessage[1];
uint16_t startAddress=(uint16_t)command[2];
startAddress=(startAddress<<8)+(uint16_t)command[3];
uint16_t quantity=(uint16_t)command[4];
quantity=(quantity<<8)+(uint16_t)command[5];
if((fuctionCode>=ReadCoilStatus)&&(fuctionCode<=ReadInputRegister))
{
HandleSlaveRespond[fuctionCode-1](recievedMessage,startAddress,quantity);
}
}
改为
/*解析收到的服务器相应信息*/
void ParsingSlaveRespondMessage(uint8_t *recievedMessage,uint8_t *command, uint16_t length)
{
/*如果不是读操作的反回信息不需要处理*/
if(recievedMessage[1] > 0x04)return;
if(CheckRTUMessageIntegrity(recievedMessage,length) == false)return;
if(command==NULL)
{
/*判断接收到的信息是否有相应的命令*/
int cmdIndex=FindCommandForRecievedMessage(recievedMessage);
if((cmdIndex<0))
{
return;
}
command=commandMasterList[cmdIndex];
}
uint8_t slaveID = recievedMessage[0];
FunctionCode fuctionCode=(FunctionCode)recievedMessage[1];
uint16_t startAddress=(uint16_t)command[2];
startAddress=(startAddress<<8)+(uint16_t)command[3];
uint16_t quantity=(uint16_t)command[4];
quantity=(quantity<<8)+(uint16_t)command[5];
if((fuctionCode>=ReadCoilStatus)&&(fuctionCode<=ReadInputRegister))
{
HandleSlaveRespond[fuctionCode-1](recievedMessage, slaveID, startAddress, quantity);
}
}
原文
/*处理读从站状态量返回信息,读线圈状态位0x012功能码*/
static void HandleReadCoilStatusRespond(uint8_t *receivedMessage,uint16_t startAddress,uint16_t quantity)
{
bool coilStatus[256];
TransformClientReceivedData(receivedMessage,quantity,coilStatus,NULL);
UpdateCoilStatus(startAddress,quantity,coilStatus);
}
/*处理读从站状态量返回信息,读输入状态位0x02功能码*/
static void HandleReadInputStatusRespond(uint8_t *receivedMessage,uint16_t startAddress,uint16_t quantity)
{
bool inputStatus[256];
TransformClientReceivedData(receivedMessage,quantity,inputStatus,NULL);
UpdateInputStatus(startAddress,quantity,inputStatus);
}
/*处理读从站寄存器值的返回信息,读保持寄存器0x03功能码)*/
static void HandleReadHoldingRegisterRespond(uint8_t *receivedMessage,uint16_t startAddress,uint16_t quantity)
{
uint16_t holdingRegister[125];
TransformClientReceivedData(receivedMessage,quantity,NULL,holdingRegister);
UpdateHoldingRegister(startAddress,quantity,holdingRegister);
}
/*处理读从站寄存器值的返回信息,读输入寄存器0x04功能码*/
static void HandleReadInputRegisterRespond(uint8_t *receivedMessage,uint16_t startAddress,uint16_t quantity)
{
uint16_t inputRegister[125];
TransformClientReceivedData(receivedMessage,quantity,NULL,inputRegister);
UpdateInputResgister(startAddress,quantity,inputRegister);
}
改为
/*处理读从站状态量返回信息,读线圈状态位0x012功能码*/
static void HandleReadCoilStatusRespond(uint8_t *receivedMessage, uint8_t slaveID, uint16_t startAddress,uint16_t quantity)
{
bool coilStatus[256];
TransformClientReceivedData(receivedMessage,quantity,coilStatus,NULL);
UpdateCoilStatus(startAddress,quantity,coilStatus);
}
/*处理读从站状态量返回信息,读输入状态位0x02功能码*/
static void HandleReadInputStatusRespond(uint8_t *receivedMessage, uint8_t slaveID, uint16_t startAddress,uint16_t quantity)
{
bool inputStatus[256];
TransformClientReceivedData(receivedMessage,quantity,inputStatus,NULL);
UpdateInputStatus(startAddress,quantity,inputStatus);
}
/*处理读从站寄存器值的返回信息,读保持寄存器0x03功能码)*/
static void HandleReadHoldingRegisterRespond(uint8_t *receivedMessage, uint8_t slaveID, uint16_t startAddress, uint16_t quantity)
{
uint16_t holdingRegister[125];
TransformClientReceivedData(receivedMessage,quantity,NULL,holdingRegister);
UpdateHoldingRegister(startAddress,quantity,holdingRegister);
}
/*处理读从站寄存器值的返回信息,读输入寄存器0x04功能码*/
static void HandleReadInputRegisterRespond(uint8_t *receivedMessage, uint8_t slaveID, uint16_t startAddress, uint16_t quantity)
{
uint16_t inputRegister[125];
TransformClientReceivedData(receivedMessage,quantity,NULL,inputRegister);
UpdateInputResgister(startAddress,quantity,inputRegister);
}
mbtcp.c
原文
/*生成读写服务器对象的命令*/
uint16_t SyntheticReadWriteTCPServerCommand(ObjAccessInfo objInfo,bool *statusList,uint16_t *registerList,uint8_t *commandBytes)
改为
/*生成读写服务器对象的命令*/
uint16_t SyntheticReadWriteTCPServerCommand(ObjAccessInfo *objInfo,bool *statusList,uint16_t *registerList,uint8_t *commandBytes)
mbtcpclient.c
原文
/*生成访问服务器的命令*/
uint16_t CreateAccessServerCommand(ObjAccessInfo objInfo,void *dataList,uint8_t *commandBytes)
{
uint16_t commandLength=0;
/*生成读服务器对象的命令,功能码0x01、0x02、0x03、0x04,命令长度12个字节*/
if((objInfo.functionCode>=ReadCoilStatus)&&(objInfo.functionCode <= ReadInputStatus))
{
commandLength=SyntheticReadWriteTCPServerCommand(objInfo,NULL,NULL,commandBytes);
AddCommandBytesToList(commandBytes); /*记录发送的读命令*/
}
/*生成预置服务器对象的命令,功能码0x05,0x0F,命令长度随发送数据而变*/
if((objInfo.functionCode==WriteSingleCoil)&&(objInfo.functionCode==WriteMultipleCoil))
{
bool *statusList=(bool*)dataList;
commandLength=SyntheticReadWriteTCPServerCommand(objInfo,statusList,NULL,commandBytes);
}
/*生成预置服务器对象的命令,功能码0x06,0x10,命令长度随发送数据而变*/
if((objInfo.functionCode==WriteSingleRegister)&&(objInfo.functionCode==WriteMultipleRegister))
{
uint16_t *registerList=(uint16_t*)dataList;
commandLength=SyntheticReadWriteTCPServerCommand(objInfo,NULL,registerList,commandBytes);
}
return commandLength;
}
改为
/*生成访问服务器的命令*/
uint16_t CreateAccessServerCommand(ObjAccessInfo *objInfo,void *dataList,uint8_t *commandBytes)
{
uint16_t commandLength=0;
/*生成读服务器对象的命令,功能码0x01、0x02、0x03、0x04,命令长度12个字节*/
if((objInfo->functionCode>=ReadCoilStatus)&&(objInfo->functionCode <= ReadInputStatus))
{
commandLength=SyntheticReadWriteTCPServerCommand(objInfo,NULL,NULL,commandBytes);
AddCommandBytesToList(commandBytes); /*记录发送的读命令*/
}
/*生成预置服务器对象的命令,功能码0x05,0x0F,命令长度随发送数据而变*/
if((objInfo->functionCode==WriteSingleCoil)&&(objInfo->functionCode==WriteMultipleCoil))
{
bool *statusList=(bool*)dataList;
commandLength=SyntheticReadWriteTCPServerCommand(objInfo,statusList,NULL,commandBytes);
}
/*生成预置服务器对象的命令,功能码0x06,0x10,命令长度随发送数据而变*/
if((objInfo->functionCode==WriteSingleRegister)&&(objInfo->functionCode==WriteMultipleRegister))
{
uint16_t *registerList=(uint16_t*)dataList;
commandLength=SyntheticReadWriteTCPServerCommand(objInfo,NULL,registerList,commandBytes);
}
return commandLength;
}
至此库文件改完了。我再主程序里创建了一个任务来跑主站代码,如下
bspmodbus.c
#include "bsp_modbus.h"
#include "bsp_init.h"
Modbus_Rev_Type Modbus_Rev_Info;
void Bsp_Modbus_Send(uint8_t *pdata, uint16_t len)
{
while(len--)
{
while((HAL_USART_Modbus.Instance->ISR & UART_FLAG_TC) == 0);
HAL_USART_Modbus.Instance->TDR = (*pdata++ & (uint8_t)0xFF);
}
}
#if MB_RTU_MASTER_ENABLED
/*************************************************
* @author: mark.zhu
* @param:
* @function: This function requires timing (100ms) to be called
*************************************************/
void Bsp_ModbusRTUMaster_Poll(void)
{
uint16_t adu_len = 0;
uint8_t adu_buf[255];
ObjAccessInfo objInfo;
objInfo.unitID = 1;
objInfo.functionCode = ReadHoldingRegister;
objInfo.startingAddress = 0;
objInfo.quantity = 4;
adu_len = CreateAccessSlaveCommand(&objInfo, NULL, adu_buf);
Bsp_Modbus_Send(adu_buf, adu_len);
}
#endif
bsp_modbus.h
#ifndef __BSP_MODBUS_H__
#define __BSP_MODBUS_H__
/*************************************************
* @author: mark.zhu
* @param: include file
* @function: config modbus params
*************************************************/
#include "mbconfig.h"
typedef struct
{
uint8_t Buffer[255];
uint16_t Count;
uint8_t BaseTime;
}Modbus_Rev_Type;
extern Modbus_Rev_Type Modbus_Rev_Info;
void Bsp_ModbusRTUMaster_Poll(void);
#endif
bsp_isr.c
#include "bsp_init.h"
#include "bsp_modbus.h"
/*************************************************
* @author: mark.zhu
* @param: null
* @function: Period elapsed callback in non blocking mode
*************************************************/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(Modbus_Rev_Info.BaseTime)
{
Modbus_Rev_Info.BaseTime--;
if(Modbus_Rev_Info.BaseTime == 0)
{
ParsingSlaveRespondMessage(Modbus_Rev_Info.Buffer, NULL, Modbus_Rev_Info.Count);
Modbus_Rev_Info.Count = 0;
}
}
}
/*************************************************
* @author: mark.zhu
* @param: null
* @function: Rx Transfer completed callback
*************************************************/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
uint8_t rev;
if(__HAL_UART_GET_FLAG(&HAL_USART_Modbus,UART_FLAG_ORE))
{
rev = HAL_USART_Modbus.Instance->RDR;
__HAL_UART_CLEAR_FLAG(&HAL_USART_Modbus,UART_FLAG_ORE);
}
if(__HAL_UART_GET_FLAG(&HAL_USART_Modbus, UART_FLAG_RXNE)!= RESET)
{
rev = HAL_USART_Modbus.Instance->RDR;
Modbus_Rev_Info.Buffer[Modbus_Rev_Info.Count++] = rev;
Modbus_Rev_Info.BaseTime = 3;
}
}
main.c
/* Includes ------------------------------------------------------------------*/
#include "bsp_init.h"
#include "bsp_modbus.h"
#include "cmsis_os.h"
/* Private variables ---------------------------------------------------------*/
osThreadId ModbusPollTaskHandle;
/* Private function prototypes -----------------------------------------------*/
void StartModbusPollTask(void const * argument);
int main(void)
{
/* MCU Configuration----------------------------------------------------------*/
Bsp_Peripherals_Init();
/* add mutexes, ... */
/* add semaphores, ... */
/* start timers, add new ones, ... */
/* Create the thread(s) */
/* definition and creation of defaultTask */
osThreadDef(ModbusPollTask, StartModbusPollTask, osPriorityNormal, 0, 128);
ModbusPollTaskHandle = osThreadCreate(osThread(ModbusPollTask), NULL);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/* StartModbusPollTask function */
void StartModbusPollTask(void const * argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
for(;;)
{
Bsp_ModbusRTUMaster_Poll();
osDelay(300);
}
/* USER CODE END 5 */
}
/**
* @brief This function is executed in case of error occurrence.
* @param None
* @retval None
*/
void _Error_Handler(char * file, int line)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
while(1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
另外mbconfig.h的配置如下
/******************************************************************************/
/** 模块名称:Modbus通讯 **/
/** 文件名称:mbconfig.h **/
/** 版 本:V1.0.0 **/
/** 简 介:用于配置Modbus协议栈使用的相关定义 **/
/**--------------------------------------------------------------------------**/
/** 修改记录: **/
/** 版本 日期 作者 说明 **/
/** V1.0.0 2015-07-18 尹家军 创建文件 **/
/** **/
/******************************************************************************/
#ifndef _MB_CONFIG_H
#define _MB_CONFIG_H
/*定义是否使能RTU主站功能,0为禁用,1为使能*/
#define MB_RTU_MASTER_ENABLED (1)
/*定义是否使能RTU从站功能,0为禁用,1为使能*/
#define MB_RTU_SLAVE_ENABLED (1)
/*定义是否使能ASCII主站功能,0为禁用,1为使能*/
#define MB_ACSII_MASTER_ENABLED (0)
/*定义是否使能ASCII从站功能,0为禁用,1为使能*/
#define MB_ASCII_SLAVE_ENABLED (0)
/*定义是否使能TCP服务器功能,0为禁用,1为使能*/
#define MB_TCP_SERVER_ENABLED (0)
/*定义是否使能TCP客户端功能,0为禁用,1为使能*/
#define MB_TCP_CLIENT_ENABLED (0)
#if MB_RTU_MASTER_ENABLED > (0)
#include "mbrtumaster.h"
#endif
#if MB_RTU_SLAVE_ENABLED > (0)
#include "mbrtuslave.h"
#endif
#if MB_TCP_CLIENT_ENABLED > (0)
#include "mbtcpclient.h"
#endif
#if MB_TCP_SERVER_ENABLED > (0)
#include "mbtcpserver.h"
#endif
#include "mbcommon.h"
#endif
/*********** (C) COPYRIGHT 1999-2016 Moonan Technology *********END OF FILE****/