#include "stm32g4xx_hal.h" #include #include #include "modbus.h" #include "usart.h" void Modbus_Master_Send(uint8_t *data, uint8_t length); uint16_t holdingRegisters[REGISTER_COUNT] = { 0x0032, 0x0032, 0x0032, 0x0032, 0x0032, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; // 寄存器可写标志位(1:可写,0:只读) uint8_t registerWritable[REGISTER_COUNT] = { registerWritable_0, registerWritable_1, registerWritable_2, registerWritable_3, registerWritable_4, registerWritable_5, registerWritable_6, registerWritable_7, registerWritable_8, registerWritable_9, registerWritable_10, registerWritable_11 }; /* 全局变量 */ uint8_t modbusBuffer[MODBUS_BUFFER_SIZE]; uint8_t modbus_master_Buffer[MODBUS_BUFFER_SIZE]; uint8_t modbus_master_BufferIndex = 0; uint32_t last_master_ByteTime = 0; uint8_t modbusBufferIndex = 0; uint32_t lastByteTime = 0; bool messageComplete = false; uint8_t master_tx_buf[256]; uint8_t response[256]; uint8_t RS485_1_RX = 0; uint8_t RS485_1_Host_Existed = 0; char dmk_read_state=0; /* 函数声明 */ void Modbus_Init(void); void Modbus_Process(void); void Modbus_SendResponse(uint8_t *data, uint8_t length); void Modbus_HandleFunction03(uint16_t startAddress, uint16_t registerCount); void Modbus_HandleFunction06(uint16_t registerAddress, uint16_t value); void Modbus_HandleFunction10(uint16_t startAddress, uint16_t registerCount, uint8_t *data); void Modbus_SendExceptionResponse(uint8_t exceptionCode); uint16_t CalculateCRC(uint8_t *data, uint8_t length); /* 初始化函数 */ void Modbus_Init(void) { /* 初始化UART */ /* 配置RS485方向控制引脚 */ HAL_UART_Receive_IT(&huart1, (uint8_t*) &modbusBuffer[modbusBufferIndex], 1); HAL_UART_Receive_IT(&huart2, (uint8_t*) &modbus_master_Buffer[modbus_master_BufferIndex], 1); } /* Modbus处理函数 - 应在主循环中调用 */ void Modbus_Process(void) { uint16_t startAddress = 0; uint16_t registerCount = 0; if (modbusBufferIndex > 0&& (HAL_GetTick() - lastByteTime) > MODBUS_TIMEOUT_MS) { /* 超时,标记消息完成 */ messageComplete = true; } if (messageComplete) { uint16_t crcReceived = (modbusBuffer[modbusBufferIndex - 1] << 8) | modbusBuffer[modbusBufferIndex - 2]; uint16_t crcCalculated = CalculateCRC(modbusBuffer, modbusBufferIndex - 2); if (MODBUS_CRC_OFF || crcReceived == crcCalculated) { RS485_1_Host_Existed = 1; if (modbusBuffer[0] == MODBUS_SLAVE_ADDRESS) { RS485_1_RX = 1; switch (modbusBuffer[1]) { case MODBUS_FUNCTION_CODE_03: startAddress = (modbusBuffer[2] << 8) | modbusBuffer[3]; registerCount = (modbusBuffer[4] << 8) | modbusBuffer[5]; Modbus_HandleFunction03(startAddress, registerCount); break; case MODBUS_FUNCTION_CODE_06: startAddress = (modbusBuffer[2] << 8) | modbusBuffer[3]; uint16_t value = (modbusBuffer[4] << 8) | modbusBuffer[5]; Modbus_HandleFunction06(startAddress, value); break; case MODBUS_FUNCTION_CODE_10: startAddress = (modbusBuffer[2] << 8) | modbusBuffer[3]; registerCount = (modbusBuffer[4] << 8) | modbusBuffer[5]; uint8_t byteCount = modbusBuffer[6]; // 检查数据长度是否正确 if (byteCount == registerCount * 2 && modbusBufferIndex - 2 >= 7 + byteCount) { // 7是功能码10的固定头部长度 Modbus_HandleFunction10(startAddress, registerCount, &modbusBuffer[7]); } else { Modbus_SendExceptionResponse(0x03); // 数据长度错误 } break; default: Modbus_SendExceptionResponse(0x01); // 不支持的功能码 break; } } } /* 重置缓冲区 */ modbusBufferIndex = 0; messageComplete = false; } } /* 处理功能码03 */ void Modbus_HandleFunction03(uint16_t startAddress, uint16_t registerCount) { /* 检查地址和数量是否合法 */ if (startAddress < REGISTER_START_ADDRESS || startAddress + registerCount > REGISTER_START_ADDRESS + REGISTER_COUNT || registerCount > 0x7D) { Modbus_SendExceptionResponse(0x02); // 地址错误 return; } uint8_t byteCount = registerCount * 2; uint8_t index = 0; response[index++] = MODBUS_SLAVE_ADDRESS; response[index++] = MODBUS_FUNCTION_CODE_03; response[index++] = byteCount; for (uint16_t i = 0; i < registerCount; i++) { uint16_t regValue = holdingRegisters[(startAddress - REGISTER_START_ADDRESS) + i]; response[index++] = (regValue >> 8) & 0xFF; response[index++] = regValue & 0xFF; } uint16_t crc = CalculateCRC(response, index); response[index++] = crc & 0xFF; response[index++] = (crc >> 8) & 0xFF; Modbus_SendResponse(response, index); } /* 处理功能码06 */ void Modbus_HandleFunction06(uint16_t registerAddress, uint16_t value) { /* 检查地址是否合法 */ if (registerAddress < REGISTER_START_ADDRESS || registerAddress >= REGISTER_START_ADDRESS + REGISTER_COUNT) { Modbus_SendExceptionResponse(0x02); // 地址错误 return; } /* 写入寄存器值 */ holdingRegisters[registerAddress - REGISTER_START_ADDRESS] = value; /* 准备响应帧 - 功能码06的响应是原请求帧的原样返回 */ uint8_t index = 0; response[index++] = MODBUS_SLAVE_ADDRESS; response[index++] = MODBUS_FUNCTION_CODE_06; response[index++] = (registerAddress >> 8) & 0xFF; // 寄存器地址高8位 response[index++] = registerAddress & 0xFF; // 寄存器地址低8位 response[index++] = (value >> 8) & 0xFF; // 写入值高8位 response[index++] = value & 0xFF; // 写入值低8位 /* 计算CRC并添加到响应帧 */ uint16_t crc = CalculateCRC(response, index); response[index++] = crc & 0xFF; response[index++] = (crc >> 8) & 0xFF; /* 发送响应 */ Modbus_SendResponse(response, index); } // 添加功能码0x10处理函数 void Modbus_HandleFunction10(uint16_t startAddress, uint16_t registerCount, uint8_t *data) { // 检查地址和数量是否合法 if (startAddress < REGISTER_START_ADDRESS || startAddress + registerCount > REGISTER_START_ADDRESS + REGISTER_COUNT || registerCount == 0 || registerCount > 0x7B) { Modbus_SendExceptionResponse(0x02); // 地址错误 return; } // 处理每个寄存器 for (uint16_t i = 0; i < registerCount; i++) { uint16_t regIndex = (startAddress - REGISTER_START_ADDRESS) + i; uint16_t value = (data[i * 2] << 8) | data[i * 2 + 1]; // 只有可写寄存器才更新值 if (registerWritable[regIndex]) { holdingRegisters[regIndex] = value; } // 只读寄存器保持原有值,不做处理 } // 准备响应帧 - 功能码0x10的响应包含起始地址和写入数量 uint8_t index = 0; response[index++] = MODBUS_SLAVE_ADDRESS; response[index++] = MODBUS_FUNCTION_CODE_10; response[index++] = (startAddress >> 8) & 0xFF; // 起始地址高8位 response[index++] = startAddress & 0xFF; // 起始地址低8位 response[index++] = (registerCount >> 8) & 0xFF; // 写入数量高8位 response[index++] = registerCount & 0xFF; // 写入数量低8位 // 计算CRC并添加到响应帧 uint16_t crc = CalculateCRC(response, index); response[index++] = crc & 0xFF; response[index++] = (crc >> 8) & 0xFF; // 发送响应 Modbus_SendResponse(response, index); } /* 发送异常响应 */ void Modbus_SendExceptionResponse(uint8_t exceptionCode) { response[0] = MODBUS_SLAVE_ADDRESS; response[1] = modbusBuffer[1] | 0x80; // 异常功能码 response[2] = exceptionCode; uint16_t crc = CalculateCRC(response, 3); response[3] = crc & 0xFF; response[4] = (crc >> 8) & 0xFF; Modbus_SendResponse(response, 5); } /* 发送响应 */ void Modbus_SendResponse(uint8_t *data, uint8_t length) { /* 使能RS485发送 */ /* 发送数据 */ HAL_UART_Transmit_DMA(&huart1, data, length); /* 切换到接收模式 */ } /* 发送响应 */ void Modbus_Master_Send(uint8_t *data, uint8_t length) { /* 使能RS485发送 */ /* 发送数据 */ HAL_UART_Transmit_DMA(&huart2, data, length); /* 切换到接收模式 */ } /* CRC计算 */ uint16_t CalculateCRC(uint8_t *data, uint8_t length) { uint16_t crc = 0xFFFF; for (uint8_t i = 0; i < length; i++) { crc ^= (uint16_t) data[i]; for (uint8_t j = 0; j < 8; j++) { if ((crc & 0x0001) != 0) { crc >>= 1; crc ^= 0xA001; } else { crc >>= 1; } } } return crc; } /* UART接收中断回调函数 */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart == &huart1) { if (modbusBufferIndex < MODBUS_BUFFER_SIZE) { modbusBuffer[modbusBufferIndex++] = huart->Instance->RDR; } else { modbusBufferIndex = 0; } lastByteTime = HAL_GetTick(); /* 重新启动接收中断 */ HAL_UART_Receive_IT(&huart1, (uint8_t*) &modbusBuffer[modbusBufferIndex], 1); } else if (huart == &huart2) { if (modbus_master_BufferIndex < MODBUS_BUFFER_SIZE) { modbus_master_Buffer[modbus_master_BufferIndex++] = huart->Instance->RDR; } else { modbus_master_BufferIndex = 0; } last_master_ByteTime = HAL_GetTick(); /* 重新启动接收中断 */ HAL_UART_Receive_IT(&huart2, (uint8_t*) &modbus_master_Buffer[modbus_master_BufferIndex], 1); } } void MB_WriteHoldingReg(uint8_t _addr, uint16_t _reg, uint16_t _data) { uint16_t TxCount = 0; uint16_t crc = 0; master_tx_buf[TxCount++] = _addr; /* 从站地址 */ master_tx_buf[TxCount++] = 0x06; /* 功能码 */ master_tx_buf[TxCount++] = _reg >> 8; /* 寄存器地址 高字节 */ master_tx_buf[TxCount++] = _reg; /* 寄存器地址 低字节 */ master_tx_buf[TxCount++] = _data >> 8; /* 寄存器(16bits)个数 高字节 */ master_tx_buf[TxCount++] = _data; /* 低字节 */ crc = CalculateCRC(master_tx_buf, TxCount); master_tx_buf[TxCount++] = crc & 0xFF; master_tx_buf[TxCount++] = (crc >> 8) & 0xFF; Modbus_Master_Send(master_tx_buf,TxCount); dmk_read_state=0; } void calculate_dmk() { if (modbus_master_BufferIndex > 0&& (HAL_GetTick() - last_master_ByteTime) > MODBUS_TIMEOUT_MS) { /* 接收标记消息完成 */ dmk_read_state=1;//返回成功 } }