#include "COH2.h" #include "usart.h" #include #include // printf #include //#include "tim.h" // 用于传感器超时100ms处理 #define RS485_TX_MODE HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET) // 使能RS485发送模式 #define RS485_RX_MODE HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET) // 使能RS485接收模式 extern uint8_t dataReceive2[]; //#define NUM_CO_SENSORS 4 // CO传感器数量 //#define NUM_H2_SENSORS 4 // H2传感器数量 //// CO传感器地址 //uint8_t CO_addresses[NUM_CO_SENSORS] = {0x0E, 0x0F, 0x10, 0x11}; //// H2传感器地址 //uint8_t H2_addresses[NUM_H2_SENSORS] = {0x0B, 0x0A, 0x0C, 0x0D}; #define NUM_CO_SENSORS 1 // CO传感器数量 #define NUM_H2_SENSORS 1 // H2传感器数量 // CO传感器地址 uint8_t CO_addresses[NUM_CO_SENSORS] = {0x0E}; // H2传感器地址 uint8_t H2_addresses[NUM_H2_SENSORS] = {0x0B}; uint16_t calculate_crc16(uint8_t *data, uint16_t length) { uint16_t crc = 0xFFFF; for (uint16_t i = 0; i < length; i++) { crc ^= (uint16_t)data[i]; for (uint8_t j = 0; j < 8; j++) { if (crc & 0x0001) { crc >>= 1; crc ^= 0xA001; } else { crc >>= 1; } } } return crc; } // 查找传感器地址在数组中的索引 int find_sensor_index(uint8_t address, uint8_t *address_array, int num_sensors) { for (int i = 0; i < num_sensors; i++) { if (address == address_array[i]) { return i; } } return -1; // 地址未找到 } // 发送MODBUS指令读取传感器数据 void send_modbus_command(uint8_t sensor_address) { uint8_t command[8]; command[0] = sensor_address; // 传感器地址 command[1] = 0x03; // 功能码:读取保持寄存器 command[2] = 0x00; // 起始地址高字节 command[3] = 0x00; // 起始地址低字节 command[4] = 0x00; // 读取寄存器数量高字节 command[5] = 0x02; // 读取寄存器数量低字节 uint16_t crc = calculate_crc16(command, 6); command[6] = crc & 0xFF; // CRC低字节 command[7] = (crc >> 8) & 0xFF; // CRC高字节 RS485_TX_MODE; // 切换到发送模式 HAL_UART_Transmit(&huart2, command, 8,1000);//不用阻塞函数,防止系统卡死 // 注意:在这里不要立即切换到接收模式,需要在发送完成回调中处理 } void send_H2_0x0B_command(void) { uint8_t command[8]; command[0] = 0x0B; // 传感器地址 command[1] = 0x03; // 功能码:读取保持寄存器 command[2] = 0x00; // 起始地址高字节 command[3] = 0x00; // 起始地址低字节 command[4] = 0x00; // 读取寄存器数量高字节 command[5] = 0x02; // 读取寄存器数量低字节 uint16_t crc = calculate_crc16(command, 6); command[6] = crc & 0xFF; // CRC低字节 command[7] = (crc >> 8) & 0xFF; // CRC高字节 RS485_TX_MODE; // 切换到发送模式 HAL_UART_Transmit(&huart2, command, 8,1000); // 注意:在这里不要立即切换到接收模式,需要在发送完成回调中处理 } void send_CO_0x0E_command(void) { uint8_t command[8]; command[0] = 0x0E; // 传感器地址 command[1] = 0x03; // 功能码:读取保持寄存器 command[2] = 0x00; // 起始地址高字节 command[3] = 0x00; // 起始地址低字节 command[4] = 0x00; // 读取寄存器数量高字节 command[5] = 0x02; // 读取寄存器数量低字节 uint16_t crc = calculate_crc16(command, 6); command[6] = crc & 0xFF; // CRC低字节 command[7] = (crc >> 8) & 0xFF; // CRC高字节 RS485_TX_MODE; // 切换到发送模式 HAL_UART_Transmit(&huart2, command, 8,1000); // 注意:在这里不要立即切换到接收模式,需要在发送完成回调中处理 } // 处理接收的数据并转换为浮点数 void receive_and_store_data(uint8_t sensor_address) { // uint8_t received_data[9]; // 接收缓冲区,接收9字节 // HAL_UART_Receive_DMA(&huart2, received_data, 9); HAL_Delay(50); uint16_t crc_received = (dataReceive2[8] << 8) | dataReceive2[7]; uint16_t crc_calculated = calculate_crc16(dataReceive2, 7); if (crc_received == crc_calculated) { // 提取有效数据部分并转换为浮点数 uint8_t data_part[4] = {dataReceive2[3], dataReceive2[4], dataReceive2[5], dataReceive2[6]}; float result = modbus_to_float(data_part); // 检查地址是否属于CO传感器 int index = find_sensor_index(sensor_address, CO_addresses, NUM_CO_SENSORS); if (index != -1) { CO_data[index] = result; // 存储到CO数据数组 } // 检查地址是否属于H2传感器 else if ((index = find_sensor_index(sensor_address, H2_addresses, NUM_H2_SENSORS)) != -1) { H2_data[index] = result; // 存储到H2数据数组 } // printf("sensor %02X: %.2f\n", sensor_address, result); } else { // printf("CRC fail:%02X\n", sensor_address); } } // 处理接收的数据并转换为浮点数 void receive_and_store_data_CO_0E(void) { uint16_t crc_received = (dataReceive2[8] << 8) | dataReceive2[7]; uint16_t crc_calculated = calculate_crc16(dataReceive2, 7); if (crc_received == crc_calculated) { // 提取有效数据部分并转换为浮点数 uint8_t data_part[4] = {dataReceive2[3], dataReceive2[4], dataReceive2[5], dataReceive2[6]}; float result = modbus_to_float(data_part); CO_data[0] = result; // 存储到CO数据数组 // printf("CO 0x0E: %.2f\n", result); } } // 处理接收的数据并转换为浮点数 void receive_and_store_data_H2_0B(void) { uint16_t crc_received = (dataReceive2[8] << 8) | dataReceive2[7]; uint16_t crc_calculated = calculate_crc16(dataReceive2, 7); if (crc_received == crc_calculated) { // 提取有效数据部分并转换为浮点数 uint8_t data_part[4] = {dataReceive2[3], dataReceive2[4], dataReceive2[5], dataReceive2[6]}; float result = modbus_to_float(data_part); H2_data[0] = result; // 存储到CO数据数组 // printf("H2 0x0B: %.2f\n", result); } } // 将MODBUS数据转换为IEEE-754浮点数 float modbus_to_float(uint8_t *data) { uint8_t reordered_data[4]; reordered_data[0] = data[2]; // 高字节1 reordered_data[1] = data[3]; // 高字节2 reordered_data[2] = data[0]; // 低字节1 reordered_data[3] = data[1]; // 低字节2 float result; memcpy(&result, reordered_data, sizeof(float)); return result; } void read_gas_sensors_485data(void) { // for (int i = 0; i < NUM_CO_SENSORS; i++) { // send_modbus_command(CO_addresses[i]); // receive_and_store_data(CO_addresses[i]); // } // for (int i = 0; i < NUM_H2_SENSORS; i++) { // send_modbus_command(H2_addresses[i]); // receive_and_store_data(H2_addresses[i]); // } send_H2_0x0B_command(); receive_and_store_data(CO_addresses[0]); send_CO_0x0E_command(); receive_and_store_data(H2_addresses[0]); }