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

相关推荐
yrx020307几秒前
stm32 IIC总线busy解决方法
stm32·单片机·嵌入式硬件
YHPsophie1 小时前
ATGM331C-5T杭州中科微BDS/GNSS全星座定位授时模块应用领域
经验分享·笔记·单片机·信息与通信·交通物流
Archie_IT2 小时前
【STM32系统】基于STM32设计的SD卡数据读取与上位机显示系统(SDIO接口驱动、雷龙SD卡)——文末资料下载
arm开发·stm32·单片机·嵌入式硬件
辰哥单片机设计2 小时前
1×4矩阵键盘详解(STM32)
stm32·单片机·嵌入式硬件·矩阵·传感器
wmkswd2 小时前
CAN总线-STM32上CAN外设
stm32·单片机·嵌入式硬件
Ruohongxu2 小时前
LAN8720A-CP-TR-ABC QFN-24 以太网收发器芯片
单片机
努力看懂帖子3 小时前
关于STM32项目面试题02:ADC与DAC篇(输入部分NTC、AV:0-5V、AI:4-20mA和DAC的两个引脚)
嵌入式硬件
嵌入式大圣4 小时前
STM32 单片机最小系统全解析
stm32·单片机·嵌入式硬件
LN花开富贵9 小时前
stm32g431rbt6芯片中VREF+是什么?在电路中怎么设计?
笔记·stm32·单片机·嵌入式硬件·学习
qq21084629539 小时前
【stm32笔记】使用rtt-studio与stm32CubeMx联合创建项目
笔记·stm32·嵌入式硬件