Callback.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /* USER CODE BEGIN Header */
  2. /**
  3. ******************************************************************************
  4. * @file : UARTCallback.c
  5. * @brief : Header for remote.c file.
  6. * This file contains the common defines of the application.
  7. ******************************************************************************
  8. * @attention
  9. *
  10. * Copyright (c) 2024 STMicroelectronics.
  11. * All rights reserved.
  12. *
  13. * This software is licensed under terms that can be found in the LICENSE file
  14. * in the root directory of this software component.
  15. * If no LICENSE file comes with this software, it is provided AS-IS.
  16. *
  17. ******************************************************************************
  18. */
  19. /* USER CODE END Header */
  20. /* Private includes ----------------------------------------------------------*/
  21. /* USER CODE BEGIN Includes */
  22. #include "FreeRTOS.h"
  23. #include "cmsis_os.h"
  24. #include "task.h"
  25. #include "queue.h"
  26. #include "main.h"
  27. #include "Callback.h"
  28. #include "Modbussimple.h"
  29. #include "FLASH.h"
  30. #include "DRV8837D.h"
  31. /* USER CODE END Includes */
  32. /* Exported types ------------------------------------------------------------*/
  33. /* USER CODE BEGIN ET */
  34. BootParams params;
  35. int32_t freq; // 定时器1频率
  36. extern uint8_t dataReceive485[BUFFER_SIZE485]; // 485
  37. extern osMessageQueueId_t uart485rxqueueHandle;
  38. extern uint16_t uartIRQ_rx_len; // 485串口接收数据长度
  39. uint16_t pwmdata = 0;
  40. extern float Motor_spe; // 电机转速
  41. /*
  42. * @ 电控API阀参数信息
  43. */
  44. //uint32_t Firmware_Version[4] = {1, 0, 0, 20250610}; // 固件版本号 [主版本][子版本][定制版本][打包日期]
  45. //uint16_t Hardware_Version = 0x0100; // 硬件版本号 [主版本][次版本]
  46. //uint32_t Device_SN = 0x19060A01; // 设备编号 [年份][月份][日期][序号]
  47. //uint16_t Device_type = 0x0101; // 设备类型 [主型号][子型号]
  48. //uint16_t SlaveDevice_addr = 0x0022; // 从机设备地址
  49. //uint16_t Serial_baud_rate = 0x0006; // 串口波特率01 - 08对应4800 - 256000bps
  50. uint16_t Running_time = 0; // 运行时长
  51. uint16_t Valve_status = 0; // 阀状态0000关0001开
  52. uint16_t Motor_status = 0; // 电机状态0000缩回0001伸出 0002停止
  53. uint32_t Motor_current = 0; // 电机电流
  54. uint32_t Motor_speed = 0; // 电机转速
  55. uint32_t Magnetic_angle = 0; // 磁角度
  56. uint32_t hall_data[4] = {0,0,0,0}; // 霍尔1到4的数据
  57. /* USER CODE END ET */
  58. /* Exported functions prototypes ---------------------------------------------*/
  59. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) // UART 接收完成回调
  60. {
  61. Uart485Rx_msg uart485_msg;
  62. if (huart->Instance == USART1)
  63. {
  64. BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  65. memcpy(uart485_msg.data, dataReceive485, MAX_FRAME_SIZE);
  66. if (xQueueSendToBackFromISR(uart485rxqueueHandle, &uart485_msg, &xHigherPriorityTaskWoken) != pdPASS)
  67. {
  68. uint8_t discard_buffer[MAX_FRAME_SIZE];
  69. xQueueReceiveFromISR(uart485rxqueueHandle, &discard_buffer, &xHigherPriorityTaskWoken);
  70. xQueueSendToBackFromISR(uart485rxqueueHandle, &uart485_msg, &xHigherPriorityTaskWoken);
  71. }
  72. }
  73. }
  74. void Process_Uart485callback(void)
  75. {
  76. uint8_t rxBuffer[MAX_FRAME_SIZE];
  77. memset(rxBuffer, 0, MAX_FRAME_SIZE);
  78. if (xQueueReceive(uart485rxqueueHandle, rxBuffer, (TickType_t)0) == pdPASS) // portMAX_DELAY (TickType_t)0
  79. {
  80. // DEBUG_PRINTF("485rxBuffer: ");
  81. // for (int i = 0; i < uartIRQ_rx_len; i++) {
  82. // DEBUG_PRINTF("%02X ", rxBuffer[i]);
  83. // }
  84. // DEBUG_PRINTF("\n");
  85. if (is_modbus_03_response(rxBuffer)) { // 处理03读指令
  86. process_modbus_03(rxBuffer);
  87. return;
  88. }
  89. if (is_modbus_06_response(rxBuffer)) { // 处理06写单指令
  90. process_modbus_06(rxBuffer);
  91. return;
  92. }
  93. if (is_modbus_42_response(rxBuffer)) { // 处理42升级指令
  94. process_modbus_42(rxBuffer);
  95. return;
  96. }
  97. }
  98. }
  99. bool is_modbus_03_response(uint8_t *data)
  100. {
  101. // 检查前三个字节是否符合要求
  102. if (!((data[0] == (g_deviceParams.SlaveDevice_addr & 0xFF) || data[0] == 0xFF) &&
  103. data[1] == 0x03 &&
  104. (data[2] == 0x40 || data[2] == 0x00)))
  105. return false; // 不匹配,直接返回 false
  106. uint16_t crc_received = (data[7] << 8) | data[6];
  107. uint16_t crc_calculated = modbus_crc16(data, 6);
  108. return memcmp(&crc_received, &crc_calculated, sizeof(crc_calculated)) == 0;
  109. }
  110. void process_modbus_03(uint8_t *data)
  111. {
  112. memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer)); // 清零缓存,防止旧数据影响
  113. uint8_t *tx_buf = (uint8_t *)g_modbusbuffer; // 强制转成字节指针
  114. // uint8_t dev_addr = data[0]; // 从机地址
  115. uint8_t func_code = data[1]; // 功能码
  116. uint16_t reg_addr = (data[2] <<8) | data[3]; // 寄存器地址
  117. uint8_t reg_count = data[5]; // 寄存器数量
  118. // 最多读取125个寄存器(Modbus限制)
  119. if (reg_count == 0 || reg_count > 125) return;
  120. // 填充应答头部
  121. tx_buf[0] = g_deviceParams.SlaveDevice_addr & 0xFF;
  122. tx_buf[1] = func_code;
  123. tx_buf[2] = reg_count * 2;
  124. uint16_t data_len = 0;
  125. bool found = read_modbus_registers(reg_addr, reg_count, &tx_buf[3], &data_len);
  126. if (!found) return; // 地址非法
  127. // 计算CRC
  128. uint16_t crc = modbus_crc16(tx_buf, 3 + data_len);
  129. tx_buf[3 + data_len] = crc & 0xFF;
  130. tx_buf[4 + data_len] = (crc >> 8) & 0xFF;
  131. // 发送帧长度
  132. uint16_t total_len = 5 + data_len;
  133. HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET); // 开启发送模式(RS485)
  134. HAL_UART_Transmit_DMA(&huart1, tx_buf, total_len);
  135. }
  136. bool is_modbus_06_response(uint8_t *data)
  137. {
  138. // 检查前三个字节是否符合要求
  139. if (!((data[0] == (g_deviceParams.SlaveDevice_addr & 0xFF) || data[0] == 0xFF)&&
  140. data[1] == 0x06 && (data[2] == 0x40 || data[2] == 0x00)))
  141. return false; // 不匹配,直接返回 false
  142. uint16_t crc_received = (data[7] << 8) | data[6];
  143. uint16_t crc_calculated = modbus_crc16(data, 6);
  144. return memcmp(&crc_received, &crc_calculated, sizeof(crc_calculated)) == 0;
  145. }
  146. void process_modbus_06(uint8_t *data)
  147. {
  148. memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer)); // 清零缓存,防止旧数据影响
  149. uint8_t *tx_buf = (uint8_t *)g_modbusbuffer; // 强制转成字节指针
  150. // uint8_t dev_addr = data[0]; // 从机地址
  151. uint8_t func_code = data[1]; // 功能码
  152. uint16_t reg_addr = (data[2] <<8) | data[3]; // 寄存器地址
  153. uint16_t reg_data = (data[4] <<8) |data[5]; // 写入数据
  154. switch(reg_addr)
  155. {
  156. case 0x4010: // 设置从机地址
  157. g_deviceParams.SlaveDevice_addr = reg_data;
  158. save_params_to_flash(); // 存入内部flash
  159. break;
  160. case 0x4011: // 设置波特率
  161. if (reg_data >= 0x0001 && reg_data <= 0x0008)
  162. {
  163. g_deviceParams.Serial_baud_rate = reg_data;
  164. save_params_to_flash(); // 存入内部flash
  165. uint16_t data_len = 0;
  166. // 填充应答头部
  167. tx_buf[data_len++] = g_deviceParams.SlaveDevice_addr & 0xFF;
  168. tx_buf[data_len++] = func_code;
  169. tx_buf[data_len++] = (reg_addr << 8) & 0xFF;
  170. tx_buf[data_len++] = reg_addr & 0xFF;
  171. tx_buf[data_len++] = (reg_data << 8) & 0xFF;
  172. tx_buf[data_len++] = reg_data & 0xFF;
  173. // 计算CRC
  174. uint16_t crc = modbus_crc16(tx_buf, data_len );
  175. tx_buf[data_len++] = crc & 0xFF;
  176. tx_buf[data_len++] = (crc >> 8) & 0xFF;
  177. HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET); // 开启发送模式(RS485)
  178. HAL_UART_Transmit_DMA(&huart1, tx_buf, data_len);
  179. osDelay (10);
  180. Set_485_Baudrate(g_deviceParams.Serial_baud_rate); // 修改485串口1波特率
  181. const char* msg = "New baudrate applied\r\n";
  182. HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), 100);
  183. uart_enable();
  184. return;
  185. }
  186. // 电机角度 cur_angle_deg(0到360度)
  187. // 电机转速 Motor_spe
  188. // 电机电流 Motor_cur (正常是0.0几,堵转最高是到0.3)
  189. // 目标速度 target_speed
  190. case 0x0002: // 控制电机
  191. Motor_status = reg_data;
  192. if(Motor_status == 0x0000)
  193. {
  194. use_pid_control = 0;
  195. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
  196. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
  197. Motormode = MOTOR_FORWARD; // 电机处于正转模式
  198. // Motor_Forward(pwmdata); // 2号电机最低350才能动
  199. use_pid_control = 1;
  200. }else if(Motor_status == 0x0001)
  201. {
  202. use_pid_control = 0;
  203. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
  204. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
  205. Motormode = MOTOR_REVERSE; // 电机处于反转模式
  206. // Motor_Reverse(pwmdata);
  207. use_pid_control = 1;
  208. }else if(Motor_status == 0x0002)
  209. {
  210. Motormode = MOTOR_STOPPED; // 电机处于停止模式
  211. use_pid_control = 0;
  212. Motor_spe = 0;
  213. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
  214. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
  215. }
  216. break;
  217. case 0x0011: // 控制电机目标转速
  218. // pwmdata = reg_data;
  219. pidMotor1Speed.target_speed = reg_data; // 目标转速
  220. break;
  221. case 0x4040: // 重启程序
  222. if(reg_data == 0x5599)
  223. {
  224. uint16_t data_len = 0;
  225. // 填充应答头部
  226. tx_buf[data_len++] = g_deviceParams.SlaveDevice_addr & 0xFF;
  227. tx_buf[data_len++] = func_code;
  228. tx_buf[data_len++] = (reg_addr << 8) & 0xFF;
  229. tx_buf[data_len++] = reg_addr & 0xFF;
  230. tx_buf[data_len++] = (reg_data << 8) & 0xFF;
  231. tx_buf[data_len++] = reg_data & 0xFF;
  232. // 计算CRC
  233. uint16_t crc = modbus_crc16(tx_buf, data_len );
  234. tx_buf[data_len++] = crc & 0xFF;
  235. tx_buf[data_len++] = (crc >> 8) & 0xFF;
  236. HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET); // 开启发送模式(RS485)
  237. HAL_UART_Transmit_DMA(&huart1, tx_buf, data_len);
  238. osDelay (50);
  239. NVIC_SystemReset(); // 系统软件复位
  240. }
  241. if(reg_data == 0x55AA)
  242. {
  243. g_deviceParams.SlaveDevice_addr = 0x00FF; // 恢复出厂设置
  244. g_deviceParams.Serial_baud_rate = 0x0002;
  245. Motor_status = 0x0000;
  246. // 版本回退指令
  247. // 电机缩回
  248. Set_485_Baudrate(g_deviceParams.Serial_baud_rate); // 重设波特率
  249. Restart_UART1_DMA();
  250. }
  251. break;
  252. case 0xAABB: // IAP-M42
  253. break;
  254. default:
  255. break;
  256. }
  257. uint16_t data_len = 0;
  258. // 填充应答头部
  259. tx_buf[data_len++] = g_deviceParams.SlaveDevice_addr & 0xFF;
  260. tx_buf[data_len++] = func_code;
  261. tx_buf[data_len++] = (reg_addr << 8) & 0xFF;
  262. tx_buf[data_len++] = reg_addr & 0xFF;
  263. tx_buf[data_len++] = (reg_data << 8) & 0xFF;
  264. tx_buf[data_len++] = reg_data & 0xFF;
  265. // 计算CRC
  266. uint16_t crc = modbus_crc16(tx_buf, data_len );
  267. tx_buf[data_len++] = crc & 0xFF;
  268. tx_buf[data_len++] = (crc >> 8) & 0xFF;
  269. HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET); // 开启发送模式(RS485)
  270. HAL_UART_Transmit_DMA(&huart1, tx_buf, data_len);
  271. }
  272. bool is_modbus_42_response(uint8_t *data)
  273. {
  274. // 检查前三个字节是否符合要求
  275. if (!((data[0] == (g_deviceParams.SlaveDevice_addr & 0xFF) && data[0] == 0xFF)&&
  276. data[1] == 0x42 && data[2] == 0xAA && data[3] == 0xBB))
  277. return false; // 不匹配,直接返回 false
  278. uint16_t crc_received = (data[uartIRQ_rx_len] << 8) | data[uartIRQ_rx_len - 1];
  279. uint16_t crc_calculated = modbus_crc16(data, uartIRQ_rx_len - 1);
  280. if (crc_received != crc_calculated)
  281. {
  282. // CRC 错误,返回错误应答
  283. send_upgrade_response(0x42, 0xAABB, 0x05, 0x0000); // 0x05:CRC错误
  284. return false; // 返回false,不执行后续处理
  285. }
  286. return true; // CRC正确
  287. }
  288. void process_modbus_42(uint8_t *data)
  289. {
  290. memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer)); // 清零缓存,防止旧数据影响
  291. uint16_t iapDataCommandCode = (data[4] <<8) |data[5]; // IAP数据的命令码
  292. switch(iapDataCommandCode)
  293. {
  294. case 0x4000: // 升级程序起始帧
  295. handle_upgrade_start_frame(data);
  296. break;
  297. case 0x4001: // 升级程序数据帧
  298. handle_upgrade_data_frame(data);
  299. break;
  300. case 0x4002: // 升级程序结束帧
  301. handle_upgrade_end_frame();
  302. break;
  303. default:
  304. send_upgrade_response(0x42, 0xAABB, 0x07, 0x0000); // 命令码错误
  305. break;
  306. }
  307. }
  308. bool is_modbus_errorfunc_response(uint8_t *data)
  309. {
  310. // 检查从机地址是否符合要求(等于 g_deviceParams.SlaveDevice_addr 或 0xFF)
  311. bool is_valid_addr = (data[0] == (g_deviceParams.SlaveDevice_addr & 0xFF)) || (data[0] == 0xFF);
  312. // 检查功能码是否不在允许的范围内(0x03, 0x06, 0x10, 0x42)
  313. bool is_invalid_func = (data[1] != 0x03) &&
  314. (data[1] != 0x06) &&
  315. (data[1] != 0x10) &&
  316. (data[1] != 0x42);
  317. if (is_valid_addr && is_invalid_func)
  318. {
  319. uint16_t crc_received = (data[7] << 8) | data[6];
  320. uint16_t crc_calculated = modbus_crc16(data, 6);
  321. return (memcmp(&crc_received, &crc_calculated, sizeof(crc_received)) == 0);
  322. }
  323. return false; // 不匹配,直接返回 false
  324. }
  325. void process_modbus_errorfunc(uint8_t *data)
  326. {
  327. memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer)); // 清零缓存,防止旧数据影响
  328. uint8_t *tx_buf = (uint8_t *)g_modbusbuffer; // 强制转成字节指针
  329. uint8_t func_code = data[1]; // 功能码
  330. uint8_t total_len = 0;
  331. total_len = modbus_error_response(g_deviceParams.SlaveDevice_addr & 0xFF, func_code, 0x01, tx_buf); // 功能码错误
  332. HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET); // 开启发送模式(RS485)
  333. HAL_UART_Transmit_DMA(&huart1, tx_buf, total_len);
  334. }
  335. bool is_modbus_error_regaddr_response(uint8_t *data)
  336. {
  337. // 检查从机地址是否符合要求(等于 g_deviceParams.SlaveDevice_addr 或 0xFF)
  338. bool is_valid_addr = (data[0] == (g_deviceParams.SlaveDevice_addr & 0xFF)) || (data[0] == 0xFF);
  339. // 检查功能码是否不在允许的范围内(0x03, 0x06, 0x10, 0x42)
  340. bool is_valid_func = (data[1] == 0x03) ||
  341. (data[1] == 0x06) ||
  342. (data[1] == 0x10) ||
  343. (data[1] == 0x42);
  344. uint16_t reg_addr = (data[2] <<8) | data[3]; // 寄存器地址
  345. // 检查寄存器地址是否不在允许的范围内(0x0000 到 0x001D 之间,0xAABB)
  346. bool is_invalid_regaddr = (reg_addr > 0x0021) && (reg_addr != 0xAABB);
  347. if (is_valid_addr && is_valid_func && is_invalid_regaddr)
  348. {
  349. uint16_t crc_received = (data[7] << 8) | data[6];
  350. uint16_t crc_calculated = modbus_crc16(data, 6);
  351. return (memcmp(&crc_received, &crc_calculated, sizeof(crc_received)) == 0);
  352. }
  353. return false; // 不匹配,直接返回 false
  354. }
  355. void process_modbus_error_regaddr(uint8_t *data)
  356. {
  357. memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer)); // 清零缓存,防止旧数据影响
  358. uint8_t *tx_buf = (uint8_t *)g_modbusbuffer; // 强制转成字节指针
  359. uint8_t func_code = data[1]; // 功能码
  360. uint8_t total_len = 0;
  361. total_len = modbus_error_response(g_deviceParams.SlaveDevice_addr & 0xFF, func_code, 0x02, tx_buf); // 功能码错误
  362. HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET); // 开启发送模式(RS485)
  363. HAL_UART_Transmit_DMA(&huart1, tx_buf, total_len);
  364. }
  365. void process_modbus_error_data(uint8_t *data)
  366. {
  367. memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer)); // 清零缓存,防止旧数据影响
  368. uint8_t *tx_buf = (uint8_t *)g_modbusbuffer; // 强制转成字节指针
  369. uint8_t func_code = data[1]; // 功能码
  370. uint8_t total_len = modbus_error_response(g_deviceParams.SlaveDevice_addr & 0xFF, func_code, 0x03, tx_buf); // 功能码错误
  371. HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET); // 开启发送模式(RS485)
  372. HAL_UART_Transmit_DMA(&huart1, tx_buf, total_len);
  373. }
  374. void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
  375. {
  376. if (huart->Instance == USART1)
  377. HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_RESET); // 发送完成后切回接收模式
  378. }
  379. /* USER CODE BEGIN EFP */