123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474 |
- /* 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 */
|