|
- /**
- * @file main.c
- * @brief 基于 uC/OS-II 的 Modbus RTU 从站主程序。
- * @version 2.0
- * @author zengbingjie
- * @date 2026-07-29
- * @copyright 版权所有 (c) 2026 Xinje Electric。
- * @note 修改记录:2.0 增加帧隔离、连接状态和可靠收发处理。
- */
-
- #include "main.h"
-
- #include "modbus.h"
-
- #define APP_MODBUS_STATUS_REGISTER_COUNT (8U)
- #define APP_MODBUS_FUNCTION_INDEX (1U)
-
- static OS_STK AppTaskStartStk[APP_TASK_START_STK_SIZE];
- static OS_STK AppTaskModbusStk[APP_TASK_MODBUS_STK_SIZE];
- static OS_STK AppTaskT35Stk[APP_TASK_T35_STK_SIZE];
-
- UART_HandleTypeDef Uart1Handle;
-
- static MODBUS_SLAVE ModbusSlave;
- static OS_EVENT *ModbusFrameSem;
- static OS_EVENT *ModbusTxSem;
- static uint8_t ModbusRxBuffer[MODBUS_RX_BUF_SIZE];
- static uint8_t ModbusTxBuffer[MODBUS_TX_BUF_SIZE];
- static volatile uint16_t ModbusRxLength;
- static volatile uint16_t ModbusFrameLength;
- static volatile uint32_t ModbusLastRxTick;
- static volatile uint8_t ModbusFrameReady;
- static volatile uint8_t ModbusRxOverflow;
- static volatile uint32_t ModbusReceiveErrorCount;
- static volatile uint32_t ModbusSemaphoreErrorCount;
- static uint32_t ModbusLastActivityTick;
- static uint32_t ModbusOperationRxCount;
- static uint32_t ModbusOperationTxCount;
- static uint32_t ModbusProtocolErrorCount;
- static uint8_t ModbusHasActivity;
- static MODBUS_STATUS ModbusLastStatus;
-
- static GPIO_TypeDef *const AppOutputPorts[APP_MODBUS_OUTPUT_COIL_COUNT] = {
- PLC_Q0_PORT,
- PLC_Q1_PORT,
- PLC_Q2_PORT,
- PLC_Q3_PORT,
- PLC_Q4_PORT,
- PLC_Q5_PORT,
- PLC_Q6_PORT,
- PLC_Q7_PORT
- };
-
- static const uint16_t AppOutputPins[APP_MODBUS_OUTPUT_COIL_COUNT] = {
- PLC_Q0_PIN,
- PLC_Q1_PIN,
- PLC_Q2_PIN,
- PLC_Q3_PIN,
- PLC_Q4_PIN,
- PLC_Q5_PIN,
- PLC_Q6_PIN,
- PLC_Q7_PIN
- };
-
- void SystemClock_Config(void);
-
- static void AppTaskStart(void *argument);
- static void AppTaskModbus(void *argument);
- static void AppTaskT35(void *argument);
- static void AppInitGpio(void);
- static void AppInitUart1(void);
- static INT8U AppCreateTasks(void);
- static HAL_StatusTypeDef AppStartUartReception(void);
- static HAL_StatusTypeDef AppTransmitResponse(uint16_t txLength);
- static uint8_t AppSealReceivedFrame(void);
- static uint16_t AppGetReadyFrameLength(void);
- static INT8U AppPostModbusFrameSem(void);
- static uint8_t AppIsModbusStatusAccepted(MODBUS_STATUS status);
- static uint8_t AppIsModbusWriteFunction(uint8_t functionCode);
- static MODBUS_STATUS AppUpdateStatusRegisters(void);
- static MODBUS_STATUS AppSyncCoilsToGpio(void);
- static void AppProcessFrame(uint16_t rxLength);
- static void AppRecordIsrError(void);
-
- /**
- * @brief 应用程序入口。
- * @return 该函数不返回。
- */
- int main(void)
- {
- INT8U osError;
-
- HAL_Init();
- SystemClock_Config();
- AppInitGpio();
- AppInitUart1();
-
- OSInit();
- osError = OSTaskCreateExt(
- AppTaskStart, NULL,
- &AppTaskStartStk[APP_TASK_START_STK_SIZE - 1U],
- APP_TASK_START_PRIO, APP_TASK_START_PRIO, &AppTaskStartStk[0],
- APP_TASK_START_STK_SIZE, NULL,
- OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
- if (osError != OS_ERR_NONE) {
- Error_Handler();
- }
-
- OSStart();
-
- while (1) {
- }
- }
-
- /**
- * @brief 配置 STM32F407 的 168 MHz 系统时钟。
- * @note 使用板载 12 MHz 外部晶振作为 PLL 时钟源。
- */
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef oscillatorConfig = {0};
- RCC_ClkInitTypeDef clockConfig = {0};
-
- __HAL_RCC_PWR_CLK_ENABLE();
- __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
-
- oscillatorConfig.OscillatorType = RCC_OSCILLATORTYPE_HSE;
- oscillatorConfig.HSEState = RCC_HSE_ON;
- oscillatorConfig.PLL.PLLState = RCC_PLL_ON;
- oscillatorConfig.PLL.PLLSource = RCC_PLLSOURCE_HSE;
- oscillatorConfig.PLL.PLLM = 12U;
- oscillatorConfig.PLL.PLLN = 336U;
- oscillatorConfig.PLL.PLLP = RCC_PLLP_DIV2;
- oscillatorConfig.PLL.PLLQ = 7U;
- if (HAL_RCC_OscConfig(&oscillatorConfig) != HAL_OK) {
- Error_Handler();
- }
-
- clockConfig.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
- | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
- clockConfig.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
- clockConfig.AHBCLKDivider = RCC_SYSCLK_DIV1;
- clockConfig.APB1CLKDivider = RCC_HCLK_DIV4;
- clockConfig.APB2CLKDivider = RCC_HCLK_DIV2;
- if (HAL_RCC_ClockConfig(&clockConfig, FLASH_LATENCY_5) != HAL_OK) {
- Error_Handler();
- }
- }
-
- /**
- * @brief 初始化 XDM-60T4-E 的 Q0 至 Q7 输出引脚。
- * @note 板卡输出为低电平有效,初始状态全部关闭。
- */
- static void AppInitGpio(void)
- {
- GPIO_InitTypeDef gpioConfig = {0};
-
- __HAL_RCC_GPIOE_CLK_ENABLE();
- __HAL_RCC_GPIOF_CLK_ENABLE();
- __HAL_RCC_GPIOI_CLK_ENABLE();
-
- gpioConfig.Mode = GPIO_MODE_OUTPUT_PP;
- gpioConfig.Pull = GPIO_PULLUP;
- gpioConfig.Speed = GPIO_SPEED_FREQ_LOW;
-
- gpioConfig.Pin = PLC_Q0_PIN | PLC_Q1_PIN | PLC_Q2_PIN | PLC_Q3_PIN;
- HAL_GPIO_Init(GPIOF, &gpioConfig);
-
- gpioConfig.Pin = PLC_Q4_PIN;
- HAL_GPIO_Init(GPIOI, &gpioConfig);
-
- gpioConfig.Pin = PLC_Q5_PIN | PLC_Q6_PIN | PLC_Q7_PIN;
- HAL_GPIO_Init(GPIOE, &gpioConfig);
-
- HAL_GPIO_WritePin(GPIOF, PLC_Q0_PIN | PLC_Q1_PIN | PLC_Q2_PIN
- | PLC_Q3_PIN, GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOI, PLC_Q4_PIN, GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOE, PLC_Q5_PIN | PLC_Q6_PIN | PLC_Q7_PIN,
- GPIO_PIN_SET);
- }
-
- /**
- * @brief 初始化 Modbus RTU 使用的 USART1。
- */
- static void AppInitUart1(void)
- {
- Uart1Handle.Instance = USART1;
- Uart1Handle.Init.BaudRate = APP_MODBUS_BAUD_RATE;
- Uart1Handle.Init.WordLength = UART_WORDLENGTH_8B;
- Uart1Handle.Init.StopBits = UART_STOPBITS_1;
- Uart1Handle.Init.Parity = UART_PARITY_NONE;
- Uart1Handle.Init.Mode = UART_MODE_TX_RX;
- Uart1Handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- Uart1Handle.Init.OverSampling = UART_OVERSAMPLING_16;
- if (HAL_UART_Init(&Uart1Handle) != HAL_OK) {
- Error_Handler();
- }
- }
-
- /**
- * @brief 创建 Modbus 工作任务与帧间隔检测任务。
- * @return uC/OS-II 错误码。
- */
- static INT8U AppCreateTasks(void)
- {
- INT8U osError;
-
- osError = OSTaskCreateExt(
- AppTaskModbus, NULL,
- &AppTaskModbusStk[APP_TASK_MODBUS_STK_SIZE - 1U],
- APP_TASK_MODBUS_PRIO, APP_TASK_MODBUS_PRIO,
- &AppTaskModbusStk[0], APP_TASK_MODBUS_STK_SIZE, NULL,
- OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
- if (osError != OS_ERR_NONE) {
- return osError;
- }
-
- osError = OSTaskCreateExt(
- AppTaskT35, NULL, &AppTaskT35Stk[APP_TASK_T35_STK_SIZE - 1U],
- APP_TASK_T35_PRIO, APP_TASK_T35_PRIO, &AppTaskT35Stk[0],
- APP_TASK_T35_STK_SIZE, NULL,
- OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
-
- return osError;
- }
-
- /**
- * @brief 启动任务,创建同步对象并启动应用任务。
- * @param[in] argument 未使用。
- */
- static void AppTaskStart(void *argument)
- {
- INT8U osError;
-
- (void)argument;
- ModbusFrameSem = OSSemCreate(0U);
- ModbusTxSem = OSSemCreate(0U);
- if ((ModbusFrameSem == NULL) || (ModbusTxSem == NULL)) {
- Error_Handler();
- }
-
- osError = AppCreateTasks();
- if (osError != OS_ERR_NONE) {
- Error_Handler();
- }
-
- OSTaskSuspend(OS_PRIO_SELF);
- while (1) {
- }
- }
-
- /**
- * @brief 清空接收状态并启动 USART1 单字节中断接收。
- * @return HAL 状态码。
- */
- static HAL_StatusTypeDef AppStartUartReception(void)
- {
- OS_CPU_SR cpu_sr = 0U;
- HAL_StatusTypeDef halStatus;
-
- OS_ENTER_CRITICAL();
- ModbusRxLength = 0U;
- ModbusFrameLength = 0U;
- ModbusFrameReady = 0U;
- ModbusRxOverflow = 0U;
- ModbusLastRxTick = OSTimeGet();
- OS_EXIT_CRITICAL();
-
- halStatus = HAL_UART_Receive_IT(&Uart1Handle, &ModbusRxBuffer[0], 1U);
-
- return halStatus;
- }
-
- /**
- * @brief 通过 USART1 发送 Modbus 从站响应帧。
- * @param[in] txLength 响应帧长度。
- * @return HAL 状态码。
- */
- static HAL_StatusTypeDef AppTransmitResponse(uint16_t txLength)
- {
- HAL_StatusTypeDef halStatus;
- INT8U osError;
-
- if ((txLength == 0U) || (txLength > MODBUS_TX_BUF_SIZE)) {
- return HAL_ERROR;
- }
-
- halStatus = HAL_UART_Transmit_IT(&Uart1Handle, ModbusTxBuffer, txLength);
- if (halStatus != HAL_OK) {
- return halStatus;
- }
-
- OSSemPend(ModbusTxSem, APP_MODBUS_TX_TIMEOUT_TICKS, &osError);
- if (osError != OS_ERR_NONE) {
- (void)HAL_UART_AbortTransmit_IT(&Uart1Handle);
- return HAL_TIMEOUT;
- }
-
- return HAL_OK;
- }
-
- /**
- * @brief 根据 T3.5 静默时间将接收缓冲区封存为完整帧。
- * @return 1 表示已封存完整帧;0 表示未满足封帧条件。
- */
- static uint8_t AppSealReceivedFrame(void)
- {
- OS_CPU_SR cpu_sr = 0U;
- HAL_StatusTypeDef halStatus;
- uint32_t currentTick;
- uint32_t elapsedTicks;
- uint8_t frameSealed;
-
- frameSealed = 0U;
- currentTick = OSTimeGet();
- OS_ENTER_CRITICAL();
- elapsedTicks = currentTick - ModbusLastRxTick;
- if ((ModbusRxLength > 0U) && (ModbusFrameReady == 0U)
- && (elapsedTicks >= APP_MODBUS_T35_TICKS)) {
- ModbusFrameLength = ModbusRxLength;
- ModbusFrameReady = 1U;
- frameSealed = 1U;
- }
- OS_EXIT_CRITICAL();
-
- if (frameSealed == 0U) {
- return 0U;
- }
-
- halStatus = HAL_UART_AbortReceive_IT(&Uart1Handle);
- if (halStatus != HAL_OK) {
- AppRecordIsrError();
- }
-
- if (AppPostModbusFrameSem() != OS_ERR_NONE) {
- AppRecordIsrError();
- }
-
- return 1U;
- }
-
- /**
- * @brief 原子读取已封存 Modbus 帧的长度。
- * @return 完整帧长度;无完整帧时返回 0。
- */
- static uint16_t AppGetReadyFrameLength(void)
- {
- OS_CPU_SR cpu_sr = 0U;
- uint16_t frameLength;
-
- frameLength = 0U;
- OS_ENTER_CRITICAL();
- if (ModbusFrameReady != 0U) {
- frameLength = ModbusFrameLength;
- }
- OS_EXIT_CRITICAL();
-
- return frameLength;
- }
-
- /**
- * @brief 通知 Modbus 任务处理完整帧或刷新通信状态。
- * @return uC/OS-II 错误码。
- */
- static INT8U AppPostModbusFrameSem(void)
- {
- INT8U osError;
-
- osError = OSSemPost(ModbusFrameSem);
-
- return osError;
- }
-
- /**
- * @brief 判断协议处理结果是否代表已寻址的有效通信。
- * @param[in] status Modbus 协议处理结果。
- * @return 1 表示有效通信;0 表示无效通信。
- */
- static uint8_t AppIsModbusStatusAccepted(MODBUS_STATUS status)
- {
- if ((status == MODBUS_STATUS_OK) || (status == MODBUS_STATUS_BROADCAST)
- || (status == MODBUS_STATUS_EXCEPTION)) {
- return 1U;
- }
-
- return 0U;
- }
-
- /**
- * @brief 判断功能码是否为触摸屏的写操作。
- * @param[in] functionCode Modbus 功能码。
- * @return 写操作返回 1,否则返回 0。
- */
- static uint8_t AppIsModbusWriteFunction(uint8_t functionCode)
- {
- switch (functionCode) {
- case MODBUS_FC_WRITE_SINGLE_COIL:
- case MODBUS_FC_WRITE_SINGLE_REG:
- case MODBUS_FC_WRITE_MULTIPLE_COILS:
- case MODBUS_FC_WRITE_MULTIPLE_REGS:
- return 1U;
-
- default:
- return 0U;
- }
- }
-
- /**
- * @brief 更新供触摸屏读取的通信状态寄存器。
- * @return 成功返回 MODBUS_STATUS_OK;失败返回错误状态。
- */
- static MODBUS_STATUS AppUpdateStatusRegisters(void)
- {
- MODBUS_STATUS status;
- uint32_t currentTick;
- uint8_t linkState;
- uint16_t registerValue;
-
- currentTick = OSTimeGet();
- linkState = APP_MODBUS_LINK_DISCONNECTED;
- if ((ModbusHasActivity != 0U)
- && ((currentTick - ModbusLastActivityTick)
- < APP_MODBUS_LINK_TIMEOUT_TICKS)) {
- linkState = APP_MODBUS_LINK_CONNECTED;
- }
-
- status = ModbusSetHoldingRegister(&ModbusSlave,
- APP_MODBUS_REG_LINK_STATE, linkState);
- if (status != MODBUS_STATUS_OK) {
- return status;
- }
-
- registerValue = (uint16_t)(ModbusOperationRxCount & 0xFFFFU);
- status = ModbusSetHoldingRegister(&ModbusSlave,
- APP_MODBUS_REG_OPERATION_RX_COUNT,
- registerValue);
- if (status != MODBUS_STATUS_OK) {
- return status;
- }
-
- registerValue = (uint16_t)(ModbusOperationTxCount & 0xFFFFU);
- status = ModbusSetHoldingRegister(&ModbusSlave,
- APP_MODBUS_REG_OPERATION_TX_COUNT,
- registerValue);
- if (status != MODBUS_STATUS_OK) {
- return status;
- }
-
- registerValue = (uint16_t)((ModbusProtocolErrorCount
- + ModbusReceiveErrorCount + ModbusSemaphoreErrorCount) & 0xFFFFU);
- status = ModbusSetHoldingRegister(&ModbusSlave,
- APP_MODBUS_REG_ERROR_COUNT,
- registerValue);
- if (status != MODBUS_STATUS_OK) {
- return status;
- }
-
- status = ModbusSetHoldingRegister(&ModbusSlave,
- APP_MODBUS_REG_SYSTEM_TICK_LOW,
- (uint16_t)(currentTick & 0xFFFFU));
- if (status != MODBUS_STATUS_OK) {
- return status;
- }
-
- status = ModbusSetHoldingRegister(&ModbusSlave,
- APP_MODBUS_REG_SYSTEM_TICK_HIGH,
- (uint16_t)(currentTick >> 16U));
- if (status != MODBUS_STATUS_OK) {
- return status;
- }
-
- status = ModbusSetHoldingRegister(&ModbusSlave,
- APP_MODBUS_REG_LAST_STATUS,
- (uint16_t)ModbusLastStatus);
- if (status != MODBUS_STATUS_OK) {
- return status;
- }
-
- status = ModbusSetHoldingRegister(&ModbusSlave,
- APP_MODBUS_REG_LAST_FRAME_LENGTH,
- ModbusFrameLength);
-
- return status;
- }
-
- /**
- * @brief 将线圈 0 至 7 的状态同步到 PLC Q0 至 Q7 输出。
- * @return 成功返回 MODBUS_STATUS_OK;失败返回错误状态。
- */
- static MODBUS_STATUS AppSyncCoilsToGpio(void)
- {
- MODBUS_STATUS status;
- uint16_t coilAddress;
- uint8_t coilValue;
- GPIO_PinState pinState;
-
- for (coilAddress = 0U; coilAddress < APP_MODBUS_OUTPUT_COIL_COUNT;
- coilAddress++) {
- status = ModbusGetCoil(&ModbusSlave, coilAddress, &coilValue);
- if (status != MODBUS_STATUS_OK) {
- return status;
- }
-
- pinState = (coilValue != 0U) ? GPIO_PIN_RESET : GPIO_PIN_SET;
- HAL_GPIO_WritePin(AppOutputPorts[coilAddress],
- AppOutputPins[coilAddress], pinState);
- }
-
- return MODBUS_STATUS_OK;
- }
-
- /**
- * @brief 处理已封存的 Modbus RTU 请求帧。
- * @param[in] rxLength 请求帧长度。
- */
- static void AppProcessFrame(uint16_t rxLength)
- {
- HAL_StatusTypeDef halStatus;
- MODBUS_STATUS status;
- uint16_t txLength;
- uint8_t isWriteOperation;
-
- isWriteOperation = 0U;
-
- if ((rxLength == 0U) || (rxLength > MODBUS_RX_BUF_SIZE)) {
- ModbusLastStatus = MODBUS_STATUS_FRAME_ERROR;
- ModbusProtocolErrorCount++;
- return;
- }
-
- if (ModbusRxOverflow != 0U) {
- ModbusLastStatus = MODBUS_STATUS_FRAME_ERROR;
- ModbusProtocolErrorCount++;
- return;
- }
-
- status = ModbusProcessFrame(&ModbusSlave, ModbusRxBuffer, rxLength,
- ModbusTxBuffer, MODBUS_TX_BUF_SIZE,
- &txLength);
- ModbusLastStatus = status;
- if (AppIsModbusStatusAccepted(status) != 0U) {
- ModbusLastActivityTick = OSTimeGet();
- ModbusHasActivity = 1U;
- if (AppIsModbusWriteFunction(
- ModbusRxBuffer[APP_MODBUS_FUNCTION_INDEX]) != 0U) {
- ModbusOperationRxCount++;
- isWriteOperation = 1U;
- }
- }
- else if (status != MODBUS_STATUS_IGNORED) {
- ModbusProtocolErrorCount++;
- }
-
- if ((status == MODBUS_STATUS_OK) || (status == MODBUS_STATUS_BROADCAST)) {
- status = AppSyncCoilsToGpio();
- if (status != MODBUS_STATUS_OK) {
- ModbusProtocolErrorCount++;
- }
- }
-
- status = AppUpdateStatusRegisters();
- if (status != MODBUS_STATUS_OK) {
- ModbusProtocolErrorCount++;
- }
-
- if (txLength > 0U) {
- halStatus = AppTransmitResponse(txLength);
- if (halStatus != HAL_OK) {
- ModbusProtocolErrorCount++;
- }
- else if (isWriteOperation != 0U) {
- ModbusOperationTxCount++;
- }
- }
- }
-
- /**
- * @brief 记录中断上下文中无法立即恢复的通信错误。
- */
- static void AppRecordIsrError(void)
- {
- ModbusReceiveErrorCount++;
- }
-
- /**
- * @brief Modbus 协议处理任务。
- * @param[in] argument 未使用。
- */
- static void AppTaskModbus(void *argument)
- {
- HAL_StatusTypeDef halStatus;
- INT8U osError;
- uint16_t rxLength;
-
- (void)argument;
- if (ModbusSlaveInit(&ModbusSlave, MODBUS_SLAVE_ADDR_DEFAULT)
- != MODBUS_STATUS_OK) {
- Error_Handler();
- }
-
- if (AppSyncCoilsToGpio() != MODBUS_STATUS_OK) {
- Error_Handler();
- }
-
- if (AppUpdateStatusRegisters() != MODBUS_STATUS_OK) {
- Error_Handler();
- }
-
- halStatus = AppStartUartReception();
- if (halStatus != HAL_OK) {
- Error_Handler();
- }
-
- while (1) {
- OSSemPend(ModbusFrameSem, 0U, &osError);
- if (osError != OS_ERR_NONE) {
- ModbusSemaphoreErrorCount++;
- continue;
- }
-
- rxLength = AppGetReadyFrameLength();
- if (rxLength > 0U) {
- AppProcessFrame(rxLength);
-
- halStatus = AppStartUartReception();
- if (halStatus != HAL_OK) {
- ModbusReceiveErrorCount++;
- }
- }
- else if (AppUpdateStatusRegisters() != MODBUS_STATUS_OK) {
- ModbusProtocolErrorCount++;
- }
- }
- }
-
- /**
- * @brief 定期检测接收静默时间并判断 Modbus RTU 帧结束。
- * @param[in] argument 未使用。
- */
- static void AppTaskT35(void *argument)
- {
- INT8U osError;
- uint16_t updateElapsedTicks;
-
- (void)argument;
- updateElapsedTicks = 0U;
-
- while (1) {
- OSTimeDly(APP_MODBUS_T35_CHECK_TICKS);
- (void)AppSealReceivedFrame();
-
- updateElapsedTicks += APP_MODBUS_T35_CHECK_TICKS;
- if (updateElapsedTicks >= APP_MODBUS_STATUS_UPDATE_TICKS) {
- updateElapsedTicks = 0U;
- osError = AppPostModbusFrameSem();
- if (osError != OS_ERR_NONE) {
- ModbusSemaphoreErrorCount++;
- }
- }
- }
- }
-
- /**
- * @brief USART1 单字节接收完成回调。
- * @param[in] uartHandle 触发回调的串口句柄。
- */
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *uartHandle)
- {
- HAL_StatusTypeDef halStatus;
-
- if ((uartHandle == NULL) || (uartHandle->Instance != USART1)) {
- return;
- }
-
- if (ModbusFrameReady != 0U) {
- return;
- }
-
- if (ModbusRxLength >= MODBUS_RX_BUF_SIZE) {
- ModbusRxOverflow = 1U;
- return;
- }
-
- ModbusRxLength++;
- ModbusLastRxTick = OSTimeGet();
- if (ModbusRxLength >= MODBUS_RX_BUF_SIZE) {
- ModbusRxOverflow = 1U;
- return;
- }
-
- halStatus = HAL_UART_Receive_IT(&Uart1Handle,
- &ModbusRxBuffer[ModbusRxLength], 1U);
- if (halStatus != HAL_OK) {
- AppRecordIsrError();
- }
- }
-
- /**
- * @brief USART1 通信错误回调。
- * @param[in] uartHandle 触发回调的串口句柄。
- */
- void HAL_UART_ErrorCallback(UART_HandleTypeDef *uartHandle)
- {
- if ((uartHandle == NULL) || (uartHandle->Instance != USART1)) {
- return;
- }
-
- ModbusRxOverflow = 1U;
- ModbusLastRxTick = OSTimeGet();
- AppRecordIsrError();
- }
-
- /**
- * @brief USART1 中断发送完成回调。
- * @param[in] uartHandle 触发回调的串口句柄。
- */
- void HAL_UART_TxCpltCallback(UART_HandleTypeDef *uartHandle)
- {
- INT8U osError;
-
- if ((uartHandle == NULL) || (uartHandle->Instance != USART1)) {
- return;
- }
-
- osError = OSSemPost(ModbusTxSem);
- if (osError != OS_ERR_NONE) {
- ModbusSemaphoreErrorCount++;
- }
- }
-
- /**
- * @brief 进入不可恢复错误状态。
- */
- void Error_Handler(void)
- {
- __disable_irq();
-
- while (1) {
- }
- }
|