Преглед на файлове

增加了代码规范

deepseek
ywh преди 1 месец
родител
ревизия
e9adda50f6
променени са 3 файла, в които са добавени 665 реда и са изтрити 566 реда
  1. +232
    -251
      Core/Src/main.c
  2. +47
    -63
      Modbus/Inc/modbus_rtu_slave.h
  3. +386
    -252
      Modbus/Src/modbus_rtu_slave.c

+ 232
- 251
Core/Src/main.c Целия файл

@@ -1,20 +1,20 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
@@ -46,7 +46,7 @@
UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart1_tx;
static uint8_t ConnectFlag;
/* USER CODE BEGIN PV */

static OS_STK AppTaskStartStk[APP_TASK_START_STK_SIZE];
@@ -59,148 +59,134 @@ static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
static void AppTaskStart(void *p_arg);


static void AppTaskStart(void *pArg);

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */


static void AppTaskStart(void *p_arg)
static void AppTaskStart(void *pArg)
{

(void)p_arg;

/*
* F4作为Modbus RTU从站,触摸屏作为主站
* 初始化函数会立即启动USART1的DMA空闲接收
*/
ModbusSlaveInit(&huart1, MODBUS_SLAVE_DEFAULT_ADDRESS);
ModbusRetainedRegistersLoad();
while (1)
{
/*
* 维护几个供触摸屏首次联调读取的保持寄存器:
*/
(void)ModbusSlaveSetHoldingRegister(//OS时钟
HMI_REG_UPTIME_SECONDS,
(uint16_t)(OSTimeGet() / OS_TICKS_PER_SEC));
(void)ModbusSlaveSetHoldingRegister(//有效帧计数
HMI_REG_RX_FRAME_COUNT,
(uint16_t)ModbusSlaveStatistics.validFrameCount);

(void)ModbusSlaveSetHoldingRegister(//从站地址不匹配计数
3,
(uint16_t)ModbusSlaveStatistics.ignoredAddressCount);
(void)ModbusSlaveSetHoldingRegister(//非法功能码计数
4,
(uint16_t)ModbusSlaveStatistics.illegalFunctionCount);

(void)ModbusSlaveSetHoldingRegister(//非法地址计数
5,
(uint16_t)ModbusSlaveStatistics.illegalAddressCount);

(void)ModbusSlaveSetHoldingRegister(//非法数据值计数
6,
(uint16_t)ModbusSlaveStatistics.illegalValueCount);

HistorySaveToRegisters();







(void)pArg;

/*
* 每1ms轮询一次,
* F4作为Modbus RTU从站,触摸屏作为主站
* 初始化函数会立即启动USART1的DMA空闲接收
*/
ModbusSlavePoll();
ModbusRetainedRegistersPoll();
// printf("123");
OSTimeDly(1U);
}
(void)ModbusSlaveInit(&huart1, MODBUS_SLAVE_DEFAULT_ADDRESS);
ModbusRetainedRegistersLoad();
while (1)
{
/*
* 维护几个供触摸屏首次联调读取的保持寄存器:
*/
(void)ModbusSlaveSetHoldingRegister( // OS时钟
HMI_REG_UPTIME_SECONDS, (uint16_t)(OSTimeGet() / OS_TICKS_PER_SEC));
(void)ModbusSlaveSetHoldingRegister( // 有效帧计数
HMI_REG_RX_FRAME_COUNT,
(uint16_t)ModbusSlaveStatistics.validFrameCount);

(void)ModbusSlaveSetHoldingRegister( // 从站地址不匹配计数
3, (uint16_t)ModbusSlaveStatistics.ignoredAddressCount);
(void)ModbusSlaveSetHoldingRegister( // 非法功能码计数
4, (uint16_t)ModbusSlaveStatistics.illegalFunctionCount);

(void)ModbusSlaveSetHoldingRegister( // 非法地址计数
5, (uint16_t)ModbusSlaveStatistics.illegalAddressCount);

(void)ModbusSlaveSetHoldingRegister( // 非法数据值计数
6, (uint16_t)ModbusSlaveStatistics.illegalValueCount);

HistorySaveToRegisters();

/*
* 每1ms轮询一次,
*/
ModbusSlavePoll();
ModbusRetainedRegistersPoll();

if (ModbusSlaveIsConnected(MODBUS_CONNECTION_TIMEOUT_MS) != 0U)
{
/* 主站在线 */
ConnectFlag = 1;
}
else
{
/* 主站超时或断开 */
ConnectFlag = 0;
}

OSTimeDly(1U);
}
}


/* USER CODE END 0 */

/**
* @brief The application entry point.
* @retval int
*/
* @brief The application entry point.
* @retval int
*/
int main(void)
{

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */
/* USER CODE BEGIN 1 */

/* USER CODE END Init */
/* USER CODE END 1 */

/* Configure the system clock */
SystemClock_Config();
/* MCU
* Configuration--------------------------------------------------------*/

/* USER CODE BEGIN SysInit */
/* Reset peripherals and initialize the Flash interface and the Systick. */
HAL_Init();

/* USER CODE END SysInit */
/* USER CODE BEGIN Init */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USB_DEVICE_Init();
MX_USART1_UART_Init();
BackupSramInit();
/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN 2 */
INT8U os_err;
/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

OSInit();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USB_DEVICE_Init();
MX_USART1_UART_Init();
(void)BackupSramInit();

/* USER CODE BEGIN 2 */
INT8U osError;

os_err = OSTaskCreateExt(AppTaskStart,
0,
&AppTaskStartStk[APP_TASK_START_STK_SIZE - 1u],
APP_TASK_START_PRIO,
APP_TASK_START_PRIO,
&AppTaskStartStk[0],
APP_TASK_START_STK_SIZE,
0,
(OS_TASK_OPT_STK_CHK |
OS_TASK_OPT_STK_CLR));
OSInit();

if (os_err != OS_ERR_NONE)
{
Error_Handler();
}
osError = OSTaskCreateExt(AppTaskStart, 0,
&AppTaskStartStk[APP_TASK_START_STK_SIZE - 1u],
APP_TASK_START_PRIO, APP_TASK_START_PRIO,
&AppTaskStartStk[0], APP_TASK_START_STK_SIZE, 0,
(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));

if (osError != OS_ERR_NONE)
{
Error_Handler();
}

OSStart();
/* USER CODE END 2 */
OSStart();
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

}
/* USER CODE END 3 */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}

static HAL_StatusTypeDef BackupSramInit(void)
@@ -212,187 +198,182 @@ static HAL_StatusTypeDef BackupSramInit(void)
}

/**
* @brief System Clock Configuration
* @retval None
*/
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 12;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
/** Enables the Clock Security System
*/
HAL_RCC_EnableCSS();
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 12;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
/** Enables the Clock Security System
*/
HAL_RCC_EnableCSS();
}

/**
* @brief USART1 Initialization Function
* @param None
* @retval None
*/
* @brief USART1 Initialization Function
* @param None
* @retval None
*/
static void MX_USART1_UART_Init(void)
{

/* USER CODE BEGIN USART1_Init 0 */

/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 0 */

/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 0 */

/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_9B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_EVEN;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE BEGIN USART1_Init 1 */

/* USER CODE END USART1_Init 2 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_9B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_EVEN;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */

/* USER CODE END USART1_Init 2 */
}

/**
* Enable DMA controller clock
*/
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{

/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();

/* DMA interrupt init */
/* DMA2_Stream2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
/* DMA2_Stream7_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();

/* DMA interrupt init */
/* DMA2_Stream2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
/* DMA2_Stream7_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
}

/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE BEGIN MX_GPIO_Init_1 */

/* USER CODE END MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE BEGIN MX_GPIO_Init_2 */

/* USER CODE END MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
/* 应答发送完成后,协议模块重新启动DMA接收。 */
ModbusSlaveOnTxComplete(huart);
}
if (huart->Instance == USART1)
{
/* 应答发送完成后,协议模块重新启动DMA接收。 */
ModbusSlaveOnTxComplete(huart);
}
}

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if (huart->Instance == USART1)
{
/*
* DMA遇到串口空闲事件后进入这里。
* 仅复制帧并重启DMA
*/
ModbusSlaveOnRxEvent(huart, Size);
}
if (huart->Instance == USART1)
{
ModbusSlaveOnRxEvent(huart, Size);
}
}

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
/* 溢出、噪声、帧错误等异常后恢复USART1 DMA接收。 */
ModbusSlaveOnUartError(huart);
}
if (huart->Instance == USART1)
{
/* 溢出、噪声、帧错误等异常后恢复USART1 DMA接收。 */
ModbusSlaveOnUartError(huart);
}
}

/* USER CODE END 4 */

/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state
*/
__disable_irq();
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
*/
* @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 */
/* USER CODE BEGIN 6 */
/* User can add code to report the file name and line number,
for example: printf("Wrong parameter: %s:%d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

+ 47
- 63
Modbus/Inc/modbus_rtu_slave.h Целия файл

@@ -14,77 +14,67 @@ extern "C"
* 任务要求规定线圈和保持寄存器地址范围均为 0~0x270F,
* 因此每种数据共有 10000 项
*/
#define MODBUS_MAP_LAST_ADDRESS (0x270FU)//保持寄存器或线圈地址
#define MODBUS_MAP_ITEM_COUNT (0x2710U)//保持寄存器或线圈数量
#define MODBUS_MAP_LAST_ADDRESS (0x270FU) // 保持寄存器或线圈地址
#define MODBUS_MAP_ITEM_COUNT (0x2710U) // 保持寄存器或线圈数量




#define MODBUS_SLAVE_DEFAULT_ADDRESS (1U)
#define MODBUS_CONNECTION_TIMEOUT_MS (1000U)
#define MODBUS_SLAVE_DEFAULT_ADDRESS (1U)
#define MODBUS_CONNECTION_TIMEOUT_MS (1000U)

/**
* @brief 与 TouchWin 触摸屏联调使用的演示地址
*
* 可以直接访问以下地址
*/
#define HMI_REG_DEVICE_ID (0U)
#define HMI_REG_UPTIME_SECONDS (1U)
#define HMI_REG_RX_FRAME_COUNT (2U)

#define HMI_REG_DEVICE_ID (0U)
#define HMI_REG_UPTIME_SECONDS (1U)
#define HMI_REG_RX_FRAME_COUNT (2U)

#define HMI_REG_WRITE_TEST (10U)
#define HMI_COIL_WRITE_TEST (0U)
#define HMI_REG_WRITE_TEST (10U)
#define HMI_COIL_WRITE_TEST (0U)

#define MODBUS_RETAINED_D_START (100U)
#define MODBUS_RETAINED_D_END (120U)
#define MODBUS_RETAINED_D_COUNT (21U)

#define MODBUS_RETAINED_D_START (100U)
#define MODBUS_RETAINED_D_END (120U)
#define MODBUS_RETAINED_D_COUNT (21U)

#define MODBUS_BACKUP_MAGIC (0x44313030UL)
#define MODBUS_BACKUP_MAGIC (0x44313030UL)

/**
* @brief 掉电保持寄存器在Backup SRAM中的存储格式
*/
typedef struct
{
uint32_t magic;
uint16_t retainedD[MODBUS_RETAINED_D_COUNT];
uint32_t magic; ///< 掉电保持数据有效标志
uint16_t retainedD[MODBUS_RETAINED_D_COUNT]; ///< D100~D120保持值
} MODBUS_BACKUP_DATA;

static volatile MODBUS_BACKUP_DATA *backupData =(volatile MODBUS_BACKUP_DATA *)BKPSRAM_BASE;


/**
* @brief Modbus 从站通信统计信息
*/
typedef struct
{
uint32_t rxEventCount; ///< 串口接收事件总数
uint32_t validFrameCount; ///< CRC 和从站地址均有效的帧数
uint32_t txFrameCount; ///< 成功启动 DMA 发送的帧数
uint32_t crcErrorCount; ///< CRC 校验错误帧数
uint32_t ignoredAddressCount; ///< 因从站地址不匹配而忽略的帧数
uint32_t illegalFunctionCount; ///< 非法功能码计数
uint32_t illegalAddressCount; ///< 非法数据地址计数
uint32_t illegalValueCount; ///< 非法数据值计数
uint32_t droppedFrameCount; ///< 接收槽占用或长度错误导致的丢帧数
uint32_t uartErrorCount; ///< HAL 串口错误计数
uint32_t rxEventCount; ///< 串口接收事件总数
uint32_t validFrameCount; ///< CRC 和从站地址均有效的帧数
uint32_t txFrameCount; ///< 成功启动 DMA 发送的帧数
uint32_t crcErrorCount; ///< CRC 校验错误帧数
uint32_t ignoredAddressCount; ///< 因从站地址不匹配而忽略的帧数
uint32_t illegalFunctionCount; ///< 非法功能码计数
uint32_t illegalAddressCount; ///< 非法数据地址计数
uint32_t illegalValueCount; ///< 非法数据值计数
uint32_t droppedFrameCount; ///< 接收槽占用或长度错误导致的丢帧数
uint32_t uartErrorCount; ///< HAL 串口错误计数
} MODBUS_SLAVE_STATS;

/**
* @brief 一次Modbus RTU通信的历史记录
*/
typedef struct
{
uint32_t tick;

uint16_t requestLength;
uint16_t responseLength;

uint8_t request[256];
uint8_t response[256];
uint32_t tick; ///< 通信发生时的系统时间
uint16_t requestLength; ///< 请求ADU长度
uint16_t responseLength; ///< 响应ADU长度
uint8_t request[256]; ///< 请求ADU数据
uint8_t response[256]; ///< 响应ADU数据
} MODBUS_HISTORY_ITEM;

/** @brief Modbus 从站通信统计数据 */
extern volatile MODBUS_SLAVE_STATS ModbusSlaveStatistics;

/**
* @brief 初始化 Modbus 从站并启动 USART DMA 空闲接收
* @param[in] huart 已由 HAL 初始化完成的串口句柄
@@ -93,9 +83,8 @@ extern volatile MODBUS_SLAVE_STATS ModbusSlaveStatistics;
* @retval HAL_ERROR 输入参数无效
* @retval HAL_BUSY 串口或 DMA 当前忙
*/
HAL_StatusTypeDef ModbusSlaveInit(UART_HandleTypeDef *huart, uint8_t slaveAddress);

HAL_StatusTypeDef ModbusSlaveInit(UART_HandleTypeDef *huart,
uint8_t slaveAddress);
/**
* @brief 校验并处理一帧待处理请求
*
@@ -103,54 +92,54 @@ HAL_StatusTypeDef ModbusSlaveInit(UART_HandleTypeDef *huart, uint8_t slaveAddres
* CRC 校验、协议解析和响应发送均在任务上下文中执行
*/
void ModbusSlavePoll(void);

/**
* @brief 处理 HAL 串口 DMA 接收事件
* @param[in] huart 产生接收事件的串口句柄
* @param[in] size 本次接收到的字节数
*/
void ModbusSlaveOnRxEvent(UART_HandleTypeDef *huart, uint16_t size);

/**
* @brief 处理 HAL 串口 DMA 发送完成事件
* @param[in] huart 完成发送的串口句柄
*/
void ModbusSlaveOnTxComplete(UART_HandleTypeDef *huart);

/**
* @brief 处理 HAL 串口错误事件并恢复接收
* @param[in] huart 发生错误的串口句柄
*/
void ModbusSlaveOnUartError(UART_HandleTypeDef *huart);

/**
* @brief 写入一个保持寄存器
* @param[in] address 保持寄存器地址
* @param[in] value 待写入的 16 位数据
* @retval 1 写入成功
* @retval 0 保持寄存器地址无效
*/
uint8_t ModbusSlaveSetHoldingRegister(uint16_t address, uint16_t value);

/**
* @brief 读取一个保持寄存器
* @param[in] address 保持寄存器地址
* @param[out] value 用于保存读取结果的指针
* @retval 1 读取成功
* @retval 0 保持寄存器地址无效或输出指针为空
*/
uint8_t ModbusSlaveGetHoldingRegister(uint16_t address, uint16_t *value);

/**
* @brief 设置一个线圈的状态
* @param[in] address 线圈地址
* @param[in] state 0 表示复位,非 0 表示置位
* @retval 1 设置成功
* @retval 0 线圈地址无效
*/
uint8_t ModbusSlaveSetCoil(uint16_t address, uint8_t state);

/**
* @brief 读取一个线圈的状态
* @param[in] address 线圈地址
* @param[out] state 用于保存线圈状态的指针,结果为 0 或 1
* @retval 1 读取成功
* @retval 0 线圈地址无效或输出指针为空
*/
uint8_t ModbusSlaveGetCoil(uint16_t address, uint8_t *state);

/**
* @brief 判断指定时间内是否收到过有效请求
* @param[in] timeoutMs 连接超时时间,单位为毫秒
@@ -161,12 +150,7 @@ uint8_t ModbusSlaveIsConnected(uint32_t timeoutMs);
void ModbusRetainedRegistersLoad(void);
void ModbusRetainedRegistersPoll(void);
void HistorySaveToRegisters(void);
static void ModbusHistorySave(
uint32_t tick,
const uint8_t *request,
uint16_t requestLength,
const uint8_t *response,
uint16_t responseLength);

#ifdef __cplusplus
}
#endif


+ 386
- 252
Modbus/Src/modbus_rtu_slave.c
Файловите разлики са ограничени, защото са твърде много
Целия файл


Зареждане…
Отказ
Запис