/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : UARTCallback.c * @brief : Header for remote.c file. * This file contains the common defines of the application. ****************************************************************************** * @attention * * Copyright (c) 2024 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 */ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "FreeRTOS.h" #include "cmsis_os.h" #include "task.h" #include "queue.h" #include "main.h" #include "Callback.h" #include "Modbussimple.h" #include "FLASH.h" #include "DRV8837D.h" /* USER CODE END Includes */ /* Exported types ------------------------------------------------------------*/ /* USER CODE BEGIN ET */ BootParams params; int32_t freq; // 定时器1频率 extern uint8_t dataReceive485[BUFFER_SIZE485]; // 485 extern osMessageQueueId_t uart485rxqueueHandle; extern uint16_t uartIRQ_rx_len; // 485串口接收数据长度 uint16_t pwmdata = 0; extern float Motor_spe; // 电机转速 /* * @ 电控API阀参数信息 */ //uint32_t Firmware_Version[4] = {1, 0, 0, 20250610}; // 固件版本号 [主版本][子版本][定制版本][打包日期] //uint16_t Hardware_Version = 0x0100; // 硬件版本号 [主版本][次版本] //uint32_t Device_SN = 0x19060A01; // 设备编号 [年份][月份][日期][序号] //uint16_t Device_type = 0x0101; // 设备类型 [主型号][子型号] //uint16_t SlaveDevice_addr = 0x0022; // 从机设备地址 //uint16_t Serial_baud_rate = 0x0006; // 串口波特率01 - 08对应4800 - 256000bps uint16_t Running_time = 0; // 运行时长 uint16_t Valve_status = 0; // 阀状态0000关0001开 uint16_t Motor_status = 0; // 电机状态0000缩回0001伸出 0002停止 uint32_t Motor_current = 0; // 电机电流 uint32_t Motor_speed = 0; // 电机转速 uint32_t Magnetic_angle = 0; // 磁角度 uint32_t hall_data[4] = {0,0,0,0}; // 霍尔1到4的数据 /* USER CODE END ET */ /* Exported functions prototypes ---------------------------------------------*/ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) // UART 接收完成回调 { Uart485Rx_msg uart485_msg; if (huart->Instance == USART1) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; memcpy(uart485_msg.data, dataReceive485, MAX_FRAME_SIZE); if (xQueueSendToBackFromISR(uart485rxqueueHandle, &uart485_msg, &xHigherPriorityTaskWoken) != pdPASS) { uint8_t discard_buffer[MAX_FRAME_SIZE]; xQueueReceiveFromISR(uart485rxqueueHandle, &discard_buffer, &xHigherPriorityTaskWoken); xQueueSendToBackFromISR(uart485rxqueueHandle, &uart485_msg, &xHigherPriorityTaskWoken); } } } void Process_Uart485callback(void) { uint8_t rxBuffer[MAX_FRAME_SIZE]; memset(rxBuffer, 0, MAX_FRAME_SIZE); if (xQueueReceive(uart485rxqueueHandle, rxBuffer, (TickType_t)0) == pdPASS) // portMAX_DELAY (TickType_t)0 { // DEBUG_PRINTF("485rxBuffer: "); // for (int i = 0; i < uartIRQ_rx_len; i++) { // DEBUG_PRINTF("%02X ", rxBuffer[i]); // } // DEBUG_PRINTF("\n"); if (is_modbus_03_response(rxBuffer)) { // 处理03读指令 process_modbus_03(rxBuffer); return; } if (is_modbus_06_response(rxBuffer)) { // 处理06写单指令 process_modbus_06(rxBuffer); return; } if (is_modbus_42_response(rxBuffer)) { // 处理42升级指令 process_modbus_42(rxBuffer); return; } } } bool is_modbus_03_response(uint8_t *data) { // 检查前三个字节是否符合要求 if (!((data[0] == (g_deviceParams.SlaveDevice_addr & 0xFF) || data[0] == 0xFF) && data[1] == 0x03 && (data[2] == 0x40 || data[2] == 0x00))) return false; // 不匹配,直接返回 false uint16_t crc_received = (data[7] << 8) | data[6]; uint16_t crc_calculated = modbus_crc16(data, 6); return memcmp(&crc_received, &crc_calculated, sizeof(crc_calculated)) == 0; } void process_modbus_03(uint8_t *data) { memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer)); // 清零缓存,防止旧数据影响 uint8_t *tx_buf = (uint8_t *)g_modbusbuffer; // 强制转成字节指针 // uint8_t dev_addr = data[0]; // 从机地址 uint8_t func_code = data[1]; // 功能码 uint16_t reg_addr = (data[2] <<8) | data[3]; // 寄存器地址 uint8_t reg_count = data[5]; // 寄存器数量 // 最多读取125个寄存器(Modbus限制) if (reg_count == 0 || reg_count > 125) return; // 填充应答头部 tx_buf[0] = g_deviceParams.SlaveDevice_addr & 0xFF; tx_buf[1] = func_code; tx_buf[2] = reg_count * 2; uint16_t data_len = 0; bool found = read_modbus_registers(reg_addr, reg_count, &tx_buf[3], &data_len); if (!found) return; // 地址非法 // 计算CRC uint16_t crc = modbus_crc16(tx_buf, 3 + data_len); tx_buf[3 + data_len] = crc & 0xFF; tx_buf[4 + data_len] = (crc >> 8) & 0xFF; // 发送帧长度 uint16_t total_len = 5 + data_len; HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET); // 开启发送模式(RS485) HAL_UART_Transmit_DMA(&huart1, tx_buf, total_len); } bool is_modbus_06_response(uint8_t *data) { // 检查前三个字节是否符合要求 if (!((data[0] == (g_deviceParams.SlaveDevice_addr & 0xFF) || data[0] == 0xFF)&& data[1] == 0x06 && (data[2] == 0x40 || data[2] == 0x00))) return false; // 不匹配,直接返回 false uint16_t crc_received = (data[7] << 8) | data[6]; uint16_t crc_calculated = modbus_crc16(data, 6); return memcmp(&crc_received, &crc_calculated, sizeof(crc_calculated)) == 0; } void process_modbus_06(uint8_t *data) { memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer)); // 清零缓存,防止旧数据影响 uint8_t *tx_buf = (uint8_t *)g_modbusbuffer; // 强制转成字节指针 // uint8_t dev_addr = data[0]; // 从机地址 uint8_t func_code = data[1]; // 功能码 uint16_t reg_addr = (data[2] <<8) | data[3]; // 寄存器地址 uint16_t reg_data = (data[4] <<8) |data[5]; // 写入数据 switch(reg_addr) { case 0x4010: // 设置从机地址 g_deviceParams.SlaveDevice_addr = reg_data; save_params_to_flash(); // 存入内部flash break; case 0x4011: // 设置波特率 if (reg_data >= 0x0001 && reg_data <= 0x0008) { g_deviceParams.Serial_baud_rate = reg_data; save_params_to_flash(); // 存入内部flash uint16_t data_len = 0; // 填充应答头部 tx_buf[data_len++] = g_deviceParams.SlaveDevice_addr & 0xFF; tx_buf[data_len++] = func_code; tx_buf[data_len++] = (reg_addr << 8) & 0xFF; tx_buf[data_len++] = reg_addr & 0xFF; tx_buf[data_len++] = (reg_data << 8) & 0xFF; tx_buf[data_len++] = reg_data & 0xFF; // 计算CRC uint16_t crc = modbus_crc16(tx_buf, data_len ); tx_buf[data_len++] = crc & 0xFF; tx_buf[data_len++] = (crc >> 8) & 0xFF; HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET); // 开启发送模式(RS485) HAL_UART_Transmit_DMA(&huart1, tx_buf, data_len); osDelay (10); Set_485_Baudrate(g_deviceParams.Serial_baud_rate); // 修改485串口1波特率 const char* msg = "New baudrate applied\r\n"; HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), 100); uart_enable(); return; } // 电机角度 cur_angle_deg(0到360度) // 电机转速 Motor_spe // 电机电流 Motor_cur (正常是0.0几,堵转最高是到0.3) // 目标速度 target_speed case 0x0002: // 控制电机 Motor_status = reg_data; if(Motor_status == 0x0000) { use_pid_control = 0; __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0); __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0); Motormode = MOTOR_FORWARD; // 电机处于正转模式 // Motor_Forward(pwmdata); // 2号电机最低350才能动 use_pid_control = 1; }else if(Motor_status == 0x0001) { use_pid_control = 0; __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0); __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0); Motormode = MOTOR_REVERSE; // 电机处于反转模式 // Motor_Reverse(pwmdata); use_pid_control = 1; }else if(Motor_status == 0x0002) { Motormode = MOTOR_STOPPED; // 电机处于停止模式 use_pid_control = 0; Motor_spe = 0; __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0); __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0); } break; case 0x0011: // 控制电机目标转速 // pwmdata = reg_data; pidMotor1Speed.target_speed = reg_data; // 目标转速 break; case 0x4040: // 重启程序 if(reg_data == 0x5599) { uint16_t data_len = 0; // 填充应答头部 tx_buf[data_len++] = g_deviceParams.SlaveDevice_addr & 0xFF; tx_buf[data_len++] = func_code; tx_buf[data_len++] = (reg_addr << 8) & 0xFF; tx_buf[data_len++] = reg_addr & 0xFF; tx_buf[data_len++] = (reg_data << 8) & 0xFF; tx_buf[data_len++] = reg_data & 0xFF; // 计算CRC uint16_t crc = modbus_crc16(tx_buf, data_len ); tx_buf[data_len++] = crc & 0xFF; tx_buf[data_len++] = (crc >> 8) & 0xFF; HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET); // 开启发送模式(RS485) HAL_UART_Transmit_DMA(&huart1, tx_buf, data_len); osDelay (50); NVIC_SystemReset(); // 系统软件复位 } if(reg_data == 0x55AA) { g_deviceParams.SlaveDevice_addr = 0x00FF; // 恢复出厂设置 g_deviceParams.Serial_baud_rate = 0x0002; Motor_status = 0x0000; // 版本回退指令 // 电机缩回 Set_485_Baudrate(g_deviceParams.Serial_baud_rate); // 重设波特率 Restart_UART1_DMA(); } break; case 0xAABB: // IAP-M42 break; default: break; } uint16_t data_len = 0; // 填充应答头部 tx_buf[data_len++] = g_deviceParams.SlaveDevice_addr & 0xFF; tx_buf[data_len++] = func_code; tx_buf[data_len++] = (reg_addr << 8) & 0xFF; tx_buf[data_len++] = reg_addr & 0xFF; tx_buf[data_len++] = (reg_data << 8) & 0xFF; tx_buf[data_len++] = reg_data & 0xFF; // 计算CRC uint16_t crc = modbus_crc16(tx_buf, data_len ); tx_buf[data_len++] = crc & 0xFF; tx_buf[data_len++] = (crc >> 8) & 0xFF; HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET); // 开启发送模式(RS485) HAL_UART_Transmit_DMA(&huart1, tx_buf, data_len); } bool is_modbus_42_response(uint8_t *data) { // 检查前三个字节是否符合要求 if (!((data[0] == (g_deviceParams.SlaveDevice_addr & 0xFF) && data[0] == 0xFF)&& data[1] == 0x42 && data[2] == 0xAA && data[3] == 0xBB)) return false; // 不匹配,直接返回 false uint16_t crc_received = (data[uartIRQ_rx_len] << 8) | data[uartIRQ_rx_len - 1]; uint16_t crc_calculated = modbus_crc16(data, uartIRQ_rx_len - 1); if (crc_received != crc_calculated) { // CRC 错误,返回错误应答 send_upgrade_response(0x42, 0xAABB, 0x05, 0x0000); // 0x05:CRC错误 return false; // 返回false,不执行后续处理 } return true; // CRC正确 } void process_modbus_42(uint8_t *data) { memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer)); // 清零缓存,防止旧数据影响 uint16_t iapDataCommandCode = (data[4] <<8) |data[5]; // IAP数据的命令码 switch(iapDataCommandCode) { case 0x4000: // 升级程序起始帧 handle_upgrade_start_frame(data); break; case 0x4001: // 升级程序数据帧 handle_upgrade_data_frame(data); break; case 0x4002: // 升级程序结束帧 handle_upgrade_end_frame(); break; default: send_upgrade_response(0x42, 0xAABB, 0x07, 0x0000); // 命令码错误 break; } } bool is_modbus_errorfunc_response(uint8_t *data) { // 检查从机地址是否符合要求(等于 g_deviceParams.SlaveDevice_addr 或 0xFF) bool is_valid_addr = (data[0] == (g_deviceParams.SlaveDevice_addr & 0xFF)) || (data[0] == 0xFF); // 检查功能码是否不在允许的范围内(0x03, 0x06, 0x10, 0x42) bool is_invalid_func = (data[1] != 0x03) && (data[1] != 0x06) && (data[1] != 0x10) && (data[1] != 0x42); if (is_valid_addr && is_invalid_func) { uint16_t crc_received = (data[7] << 8) | data[6]; uint16_t crc_calculated = modbus_crc16(data, 6); return (memcmp(&crc_received, &crc_calculated, sizeof(crc_received)) == 0); } return false; // 不匹配,直接返回 false } void process_modbus_errorfunc(uint8_t *data) { memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer)); // 清零缓存,防止旧数据影响 uint8_t *tx_buf = (uint8_t *)g_modbusbuffer; // 强制转成字节指针 uint8_t func_code = data[1]; // 功能码 uint8_t total_len = 0; total_len = modbus_error_response(g_deviceParams.SlaveDevice_addr & 0xFF, func_code, 0x01, tx_buf); // 功能码错误 HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET); // 开启发送模式(RS485) HAL_UART_Transmit_DMA(&huart1, tx_buf, total_len); } bool is_modbus_error_regaddr_response(uint8_t *data) { // 检查从机地址是否符合要求(等于 g_deviceParams.SlaveDevice_addr 或 0xFF) bool is_valid_addr = (data[0] == (g_deviceParams.SlaveDevice_addr & 0xFF)) || (data[0] == 0xFF); // 检查功能码是否不在允许的范围内(0x03, 0x06, 0x10, 0x42) bool is_valid_func = (data[1] == 0x03) || (data[1] == 0x06) || (data[1] == 0x10) || (data[1] == 0x42); uint16_t reg_addr = (data[2] <<8) | data[3]; // 寄存器地址 // 检查寄存器地址是否不在允许的范围内(0x0000 到 0x001D 之间,0xAABB) bool is_invalid_regaddr = (reg_addr > 0x0021) && (reg_addr != 0xAABB); if (is_valid_addr && is_valid_func && is_invalid_regaddr) { uint16_t crc_received = (data[7] << 8) | data[6]; uint16_t crc_calculated = modbus_crc16(data, 6); return (memcmp(&crc_received, &crc_calculated, sizeof(crc_received)) == 0); } return false; // 不匹配,直接返回 false } void process_modbus_error_regaddr(uint8_t *data) { memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer)); // 清零缓存,防止旧数据影响 uint8_t *tx_buf = (uint8_t *)g_modbusbuffer; // 强制转成字节指针 uint8_t func_code = data[1]; // 功能码 uint8_t total_len = 0; total_len = modbus_error_response(g_deviceParams.SlaveDevice_addr & 0xFF, func_code, 0x02, tx_buf); // 功能码错误 HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET); // 开启发送模式(RS485) HAL_UART_Transmit_DMA(&huart1, tx_buf, total_len); } void process_modbus_error_data(uint8_t *data) { memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer)); // 清零缓存,防止旧数据影响 uint8_t *tx_buf = (uint8_t *)g_modbusbuffer; // 强制转成字节指针 uint8_t func_code = data[1]; // 功能码 uint8_t total_len = modbus_error_response(g_deviceParams.SlaveDevice_addr & 0xFF, func_code, 0x03, tx_buf); // 功能码错误 HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET); // 开启发送模式(RS485) HAL_UART_Transmit_DMA(&huart1, tx_buf, total_len); } void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == USART1) HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_RESET); // 发送完成后切回接收模式 } /* USER CODE BEGIN EFP */