stm32 Modbus-RTU Master 主机程序

stm32 Modbus-RTU Master 主机程序源码,modbus slave

ModbusRTU_Master.c ModbusRTU_Master.h 加入到工程中

初始化串口设备

调用函数接口

cpp 复制代码
/*
 * ModbusRTU_Master.c
 *
 */

#include <ModbusRTU_Master.h>
#include "main.h"


extern UART_HandleTypeDef huart2;
uint8_t BytetoBit[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};


funcState_t sendMessage(char *msg, uint16_t len)
{
	uartState_t stateTx;

	stateTx = HAL_UART_Transmit_IT(&huart2, (uint8_t *)msg, len);

	if(stateTx == uartOkState)
	{
		return funcOk;
	}
	else
	{
		return funcErr;
	}
}

funcState_t takeMessage(char *msg, uint16_t len, uint8_t SlaveID)
{
	uartState_t stateRx;
	crcState_t crcCheck;
	uint16_t CRCVal, rxCRC;

	stateRx = HAL_UART_Receive(&huart2, (uint8_t *)msg, len, 100);


	rxCRC = (msg[len -1] << 8) | (msg[len - 2]);
	CRCVal = MODBUS_CRC16(msg, len - 2);

	if(CRCVal == rxCRC)
	{
		crcCheck = crcOk;
	}
	else
	{
		crcCheck = crcErr;
	}

	if(stateRx == uartOkState && crcCheck == crcOk && msg[0] == SLAVEID)
	{
		return funcOk;
	}
	else
	{
		return funcErr;
	}

}


/*
 * @brief Modbus_ReadHoldingRegister, Reads Holding Register #0x03
 *
 * @param SlaveID = Slave address to be read
 *
 * @param StartAddress = First address of the register to be read
 *
 * @param NumberOfReg = Number of register to be read
 *
 * @funcState_t returns funcOk if the received data CRC and SlaveID is true after the sent data
 */
funcState_t Modbus_ReadHoldingRegister(uint8_t SlaveID, uint16_t StartAddress, uint16_t NumberOfReg)
{
	uint16_t CRCVal = 0;
	funcState_t funcTxState, funcRxState;
	uint8_t i, m = 0;

	char ModbusRx[BUFFERSIZE];
	char ModbusTx[8];

	memset(ModbusTx, 0, 8);

	ModbusTx[0] = SlaveID;
	ModbusTx[1] = ReadHoldingRegister;
	ModbusTx[2] = StartAddress >> 8;
	ModbusTx[3] = (uint8_t)(StartAddress & 0x00FF);
	ModbusTx[4] = NumberOfReg >> 8;
	ModbusTx[5] = (uint8_t)(NumberOfReg & 0x00FF);

	CRCVal = MODBUS_CRC16(ModbusTx, 6);

	ModbusTx[6] = (uint8_t)(CRCVal & 0x00FF);
	ModbusTx[7] = CRCVal >> 8;

	funcTxState = sendMessage(&ModbusTx[0], 8);

	if(funcTxState == funcOk)
	{
		funcRxState = takeMessage(ModbusRx, 5 + (NumberOfReg * 2), SlaveID);
	}
	if(funcRxState == funcOk)
	{
		for(i = 0; i < NumberOfReg; i++)
		{
			ModbusRegister[StartAddress + i] = (uint16_t)((ModbusRx[3 + m] << 8) | (ModbusRx[4 + m]));
			m += 2;
		}
	}

	return funcRxState;
}

/*
 * @brief Modbus_ReadHoldingRegister, Reads Holding Register #0x03
 *
 * @param SlaveID = Slave address to be read
 *
 * @param RegAddress = Address of the register to be write
 *
 * @param RegValue = Value to be write to register
 *
 * @funcState_t returns funcOk if the received data CRC and SlaveID is true after the sent data
 */
funcState_t Modbus_WriteSingleRegister(uint8_t SlaveID, uint16_t RegAddress, uint16_t RegValue)
{
	uint16_t CRCVal = 0;
	funcState_t funcTxState, funcRxState;

	char ModbusRx[BUFFERSIZE];
	char ModbusTx[8];

	memset(ModbusTx, 0, 8);

	ModbusTx[0] = SlaveID;
	ModbusTx[1] = WriteSingleRegister;
	ModbusTx[2] = (uint8_t)(RegAddress >> 8);
	ModbusTx[3] = (uint8_t)(RegAddress & 0x00FF);
	ModbusTx[4] = (uint8_t)(RegValue >> 8);
	ModbusTx[5] = (uint8_t)(RegValue & 0x00FF);

	CRCVal = MODBUS_CRC16(ModbusTx, 6);

	ModbusTx[6] = (uint8_t)(CRCVal & 0x00FF);
	ModbusTx[7] = CRCVal >> 8;

	funcTxState = sendMessage(&ModbusTx[0], 8);

	if(funcTxState == funcOk)
	{
		funcRxState = takeMessage(ModbusRx, 8, SlaveID);
	}

	return funcRxState; //CRC and ID is true.
}


/*
 * @brief Modbus_ReadCoil, Reads Coils #0x01
 *
 * @param SlaveID = Slave address to be read
 *
 * @param StartAddress = First address of the coil to be read
 *
 * @param NumberOfCoil = Number of coils to be read
 *
 * @funcState_t returns funcOk if the received data CRC and SlaveID is true after the sent data
 */
funcState_t Modbus_ReadCoil(uint8_t SlaveID, uint16_t StartAddress, int16_t NumberOfCoil)
{
	uint16_t CRCVal = 0, Modbus_i, ByteCounter = 0, BitCounter = 0;

	funcState_t funcTxState, funcRxState;
	char ModbusRx[BUFFERSIZE];
	char ModbusTx[8];

	uint8_t NumberOfByte;

	NumberOfByte = findByte(NumberOfCoil);

	ModbusTx[0] = SlaveID;
	ModbusTx[1] = ReadCoil;
	ModbusTx[2] = (uint8_t)(StartAddress >> 8);
	ModbusTx[3] = (uint8_t)(StartAddress & 0x00FF);
	ModbusTx[4] = (uint8_t)(NumberOfCoil >> 8);
	ModbusTx[5] = (uint8_t)(NumberOfCoil & 0x00FF);

	CRCVal = MODBUS_CRC16(ModbusTx, 6);

	ModbusTx[6] = (uint8_t)(CRCVal & 0x00FF);
	ModbusTx[7] = CRCVal >> 8;

	funcTxState = sendMessage(&ModbusTx[0], 8);

	if(funcTxState == funcOk)
	{
		funcRxState = takeMessage(ModbusRx, 5 + NumberOfByte, SlaveID);
	}

	if(funcRxState == funcOk)
	{
		for(Modbus_i = 0; Modbus_i < NumberOfCoil; Modbus_i++)
		{
			ModbusCoil[StartAddress + Modbus_i] = (bool)(ModbusRx[3 + ByteCounter] & BytetoBit[BitCounter]);

			BitCounter++;

			if(Modbus_i % 8 == 7)
			{
				ByteCounter++;
				BitCounter = 0;
			}
		}
	}
	return funcRxState;
}

/*
 * @brief Modbus_WriteSingleCoil, Writes Holding Register #0x05
 *
 * @param SlaveID = Slave address to be read
 *
 * @param RegAddress = First address of the coil to be write
 *
 * @param CoilState = coilOn or coilOff @def group coilState_t
 *
 * @funcState_t returns funcOk if the received data CRC and SlaveID is true after the sent data
 */
funcState_t Modbus_WriteSingleCoil(uint8_t SlaveID, uint16_t RegAddress, coilState_t CoilState)
{
	uint16_t CRCVal = 0;

	funcState_t funcTxState, funcRxState;
	char ModbusRx[BUFFERSIZE];
	char ModbusTx[8];

	ModbusTx[0] = SlaveID;
	ModbusTx[1] = WriteSingleCoil;
	ModbusTx[2] = (uint8_t)(RegAddress >> 8);
	ModbusTx[3] = (uint8_t)(RegAddress & 0x00FF);
	ModbusTx[4] = CoilState;
	ModbusTx[5] = 0x00;

	CRCVal = MODBUS_CRC16(ModbusTx, 6);

	ModbusTx[6] = (uint8_t)(CRCVal & 0x00FF);
	ModbusTx[7] = CRCVal >> 8;

	funcTxState = sendMessage(&ModbusTx[0], 8);

	if(funcTxState == funcOk)
	{
		funcRxState = takeMessage(ModbusRx, 8, SlaveID);
	}

	return funcRxState; //CRC and ID is true.
}

/*
 * @brief Modbus_WriteSingleCoil, Writes Holding Register #0x15
 *
 * @param SlaveID = Slave address to be read
 *
 * @param StartAddress = First address of the coil to be read
 *
 * @param NumberOfCoils = Number of coils to be write
 *
 * @param coilValue = Array of values to write to coils
 *
 * @funcState_t returns funcOk if the received data CRC and SlaveID is true after the sent data
 */
funcState_t Modbus_WriteMultipleCoils(uint8_t SlaveID, uint16_t StartAddress, uint16_t NumberOfCoils, char *coilValue)
{
	uint16_t CRCVal = 0;
	uint8_t i, NumberOfByte;
	funcState_t funcTxState, funcRxState;
	char ModbusRx[BUFFERSIZE];
	char ModbusTx[8];

	ModbusTx[0] = SlaveID;
	ModbusTx[1] = WriteMultipleCoils;
	ModbusTx[2] = (uint8_t)(StartAddress >> 8);
	ModbusTx[3] = (uint8_t)(StartAddress & 0x00FF);
	ModbusTx[4] = (uint8_t)(NumberOfCoils >> 8);
	ModbusTx[5] = (uint8_t)(NumberOfCoils & 0x00FF);

	NumberOfByte = findByte(NumberOfCoils - 1);

	ModbusTx[6] = NumberOfByte;

	for(i = 0; i < NumberOfByte ; i++)
	{
		ModbusTx[7 + i] = coilValue[i];
	}

	CRCVal = MODBUS_CRC16(ModbusTx, 8 + i);

	ModbusTx[8 + i] = (uint8_t)(CRCVal & 0x00FF);
	ModbusTx[9 + i] = CRCVal >> 8;

	funcTxState = sendMessage(&ModbusTx[0], 10 + i);

	if(funcTxState == funcOk)
	{
		funcRxState = takeMessage(ModbusRx, 8, SlaveID);
	}

	return funcRxState; //CRC and ID is true.
}

/*
 * @brief Modbus_WriteSingleCoil, Writes Holding Register #0x16
 *
 * @param SlaveID = Slave address to be read
 *
 * @param StartAddress = First address of the coil to be read
 *
 * @param NumberOfReg = Number of registers to be write
 *
 * @param regValue = Array of values to write to registers
 *
 * @funcState_t returns funcOk if the received data CRC and SlaveID is true after the sent data
 */
funcState_t Modbus_WriteMultipleRegisters(uint8_t SlaveID, uint16_t StartAddress, uint16_t NumberOfReg, uint16_t *regValue)
{
	uint16_t CRCVal = 0;
	uint8_t i, m = 0;
	funcState_t funcTxState, funcRxState;
	char ModbusRx[BUFFERSIZE];
	char ModbusTx[8];

	ModbusTx[0] = SlaveID;
	ModbusTx[1] = WriteMultipleRegisters;
	ModbusTx[2] = (uint8_t)(StartAddress >> 8);
	ModbusTx[3] = (uint8_t)(StartAddress & 0x00FF);
	ModbusTx[4] = (uint8_t)(NumberOfReg >> 8);
	ModbusTx[5] = (uint8_t)(NumberOfReg & 0x00FF);
	ModbusTx[6] = NumberOfReg * 2;

	for(i = 0; i < NumberOfReg * 2 ; i += 2)
	{
		ModbusTx[7 + i] = (uint8_t)(regValue[m] >> 8);
		ModbusTx[8 + i] = (uint8_t)(regValue[m] & 0x00FF);
		m++;
	}

	CRCVal = MODBUS_CRC16(ModbusTx, 8 + i);

	ModbusTx[8 + i] = (uint8_t)(CRCVal & 0x00FF);
	ModbusTx[9 + i] = CRCVal >> 8;

	funcTxState = sendMessage(&ModbusTx[0], 10 + i);

	if(funcTxState == funcOk)
	{
		funcRxState = takeMessage(ModbusRx, 8, SlaveID);
	}

	return funcRxState; //CRC and ID is true.
}


uint8_t findByte(int16_t NumberOfCoil)
{
	volatile uint8_t NumberOfByte = 0;

	while(NumberOfCoil >= 0)
	{
		NumberOfCoil -= 8;

		NumberOfByte++;
		if(NumberOfCoil < 0)
		{
			break;
		}
	}
	return NumberOfByte;
}

uint16_t MODBUS_CRC16(char *buf, uint8_t len )
{
	static const uint16_t table[2] = { 0x0000, 0xA001 };
	uint16_t crc = 0xFFFF;
	unsigned int i = 0;
	char bit = 0;
	unsigned int xor = 0;

	for( i = 0; i < len; i++ )
	{
		crc ^= buf[i];

		for( bit = 0; bit < 8; bit++ )
		{
			xor = crc & 0x01;
			crc >>= 1;
			crc ^= table[xor];
		}
	}

	return crc;
}
cpp 复制代码
/*
 * ModbusRTU_Master.h
 *
 */

#ifndef INC_MODBUSRTU_MASTER_H_
#define INC_MODBUSRTU_MASTER_H_

#include "stdbool.h"
#include "stdio.h"
#include "stdint.h"
#include "string.h"
#include "stdbool.h"

#define SLAVEID    1
#define NUMBER_OF_REGISTER 10
#define NUMBER_OF_COIL 16
#define BUFFERSIZE (NUMBER_OF_REGISTER * 2 + 5)

uint16_t ModbusRegister[NUMBER_OF_REGISTER];
bool ModbusCoil[NUMBER_OF_COIL];

enum
{
	ReadCoil = 0x01,
	ReadHoldingRegister = 0x03,
	WriteSingleCoil = 0x05,
	WriteSingleRegister = 0x06,
	WriteMultipleCoils = 0x0F,
	WriteMultipleRegisters = 0x10,
};

typedef enum
{
	uartOkState,
	uartErrState,
}uartState_t;

typedef enum
{
	crcOk,
	crcErr,
}crcState_t;

typedef enum
{
	funcOk,
	funcErr,
}funcState_t;

typedef enum
{
	coilOff = 0x00,
	coilOn = 0xFF,
}coilState_t;

/*Data transmit and receive func*/
funcState_t sendMessage(char *msg, uint16_t len);
funcState_t takeMessage(char *msg, uint16_t len, uint8_t SlaveID);

/****************************************** MODBUS Command Function ******************************************************/
funcState_t Modbus_ReadHoldingRegister(uint8_t SlaveID, uint16_t StartAddress, uint16_t NumberOfReg);
funcState_t Modbus_WriteSingleRegister(uint8_t SlaveID, uint16_t RegAddress, uint16_t RegValue);

funcState_t Modbus_ReadCoil(uint8_t SlaveID, uint16_t StartAddress, int16_t NumberOfCoil);
funcState_t Modbus_WriteSingleCoil(uint8_t SlaveID, uint16_t RegAddress, coilState_t CoilState);

funcState_t Modbus_WriteMultipleCoils(uint8_t SlaveID, uint16_t StartAddress, uint16_t NumberOfCoils, char *coilValue);
funcState_t Modbus_WriteMultipleRegisters(uint8_t SlaveID, uint16_t StartAddress, uint16_t NumberOfReg, uint16_t *regValue);
/**************************************************************************************************************************/
uint8_t findByte(int16_t NumberOfCoil);
uint16_t MODBUS_CRC16(char *buf, uint8_t len );

#endif /* INC_MODBUSRTU_MASTER_H_ */

stm32 Modbus-RTU Master 主机程序源码,modbus-RTU slave,modbus slave

相关推荐
Mortal_hhh13 分钟前
VScode的C/C++点击转到定义,不是跳转定义而是跳转声明怎么办?(内附详细做法)
ide·vscode·stm32·编辑器
深圳市青牛科技实业有限公司26 分钟前
【青牛科技】应用方案|D2587A高压大电流DC-DC
人工智能·科技·单片机·嵌入式硬件·机器人·安防监控
Mr.谢尔比1 小时前
电赛入门之软件stm32keil+cubemx
stm32·单片机·嵌入式硬件·mcu·信息与通信·信号处理
LightningJie1 小时前
STM32中ARR(自动重装寄存器)为什么要减1
stm32·单片机·嵌入式硬件
鹿屿二向箔2 小时前
STM32外设之SPI的介绍
stm32
西瓜籽@2 小时前
STM32——毕设基于单片机的多功能节能窗控制系统
stm32·单片机·课程设计
远翔调光芯片^138287988724 小时前
远翔升压恒流芯片FP7209X与FP7209M什么区别?做以下应用市场摄影补光灯、便携灯、智能家居(调光)市场、太阳能、车灯、洗墙灯、舞台灯必看!
科技·单片机·智能家居·能源
极客小张5 小时前
基于STM32的智能充电桩:集成RTOS、MQTT与SQLite的先进管理系统设计思路
stm32·单片机·嵌入式硬件·mqtt·sqlite·毕业设计·智能充电桩
m0_739312878 小时前
【STM32】项目实战——OV7725/OV2604摄像头颜色识别检测(开源)
stm32·单片机·嵌入式硬件
嵌入式小章8 小时前
基于STM32的实时时钟(RTC)教学
stm32·嵌入式硬件·实时音视频