freertos.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. /* USER CODE BEGIN Header */
  2. /**
  3. ******************************************************************************
  4. * File Name : freertos.c
  5. * Description : Code for freertos applications
  6. ******************************************************************************
  7. * @attention
  8. *
  9. * Copyright (c) 2024 STMicroelectronics.
  10. * All rights reserved.
  11. *
  12. * This software is licensed under terms that can be found in the LICENSE file
  13. * in the root directory of this software component.
  14. * If no LICENSE file comes with this software, it is provided AS-IS.
  15. *
  16. ******************************************************************************
  17. */
  18. /* USER CODE END Header */
  19. /* Includes ------------------------------------------------------------------*/
  20. #include "FreeRTOS.h"
  21. #include "task.h"
  22. #include "main.h"
  23. #include "cmsis_os.h"
  24. /* Private includes ----------------------------------------------------------*/
  25. /* USER CODE BEGIN Includes */
  26. #include "semphr.h"
  27. #include "can.h"
  28. #include "iwdg.h"
  29. #include "rtc.h"
  30. #include "usart.h"
  31. /* USER CODE END Includes */
  32. /* Private typedef -----------------------------------------------------------*/
  33. typedef StaticQueue_t osStaticMessageQDef_t;
  34. /* USER CODE BEGIN PTD */
  35. /* USER CODE END PTD */
  36. /* Private define ------------------------------------------------------------*/
  37. /* USER CODE BEGIN PD */
  38. uint8_t data_P01[8] = {0};
  39. uint8_t data_P02[8] = {0};
  40. /**
  41. * @breaf 内部flash参数定义
  42. */
  43. #define FLASH_LAST_PAGE_ADDR 0x0801FC00 // STM32L431CCT6 内部Flash第127页起始地址
  44. #define FLASH_SECOND_LAST_PAGE_ADDR 0x08018800 // STM32L431CCT6 内部Flash第126页起始地址
  45. uint16_t NODE_ID;//压力传感器 ID 从 2开始 ,0x02 代表 1 号小板
  46. //typedef struct {
  47. // uint8_t second_threshold; // 二级警报阈值
  48. // uint8_t delay_receivedValue; // 初始上报频率
  49. // uint8_t reserve1;
  50. // uint8_t reserve2;
  51. //} FlashData;
  52. FlashData flash_data = {
  53. .second_threshold = 100, // 二级警报阈值
  54. .delay_receivedValue = 1, // 初始上报频率 1s
  55. .reserve1 = 0,
  56. };
  57. /* USER CODE END PD */
  58. /* Private macro -------------------------------------------------------------*/
  59. /* USER CODE BEGIN PM */
  60. void CAN_ErrorCheck(void);
  61. /* USER CODE END PM */
  62. /* Private variables ---------------------------------------------------------*/
  63. /* USER CODE BEGIN Variables */
  64. void Read_NODE_ID_From_Flash(void);
  65. void Read_parameter_From_Flash(void) ;
  66. void Save_NODEID_To_Flash(uint8_t NODE_ID);
  67. void Save_parameter_To_Flash(uint16_t second_threshold, uint8_t delay_receivedValue);
  68. void CAN_Send_extId(uint16_t *data, uint8_t len, uint32_t node_id, uint8_t sequence, uint8_t slice_num, uint8_t slice_id);
  69. void CAN_Send_Parameter(uint32_t node_id, uint8_t len, FlashData *flash_data, uint8_t sequence, uint8_t slice_num, uint8_t slice_id) ;
  70. void Configure_GPIOs_For_LowPower(void);
  71. void Enter_LPStop2Mode(void);
  72. void Wakeup_LPStop2Mode(void);
  73. void Enable_RTC_Wakeup(uint16_t delay_time);
  74. void control_MLX90640_power(bool enable) ;
  75. /* USER CODE END Variables */
  76. /* Definitions for Readpressure */
  77. osThreadId_t ReadpressureHandle;
  78. const osThreadAttr_t Readpressure_attributes = {
  79. .name = "Readpressure",
  80. .stack_size = 128 * 4,
  81. .priority = (osPriority_t) osPriorityNormal,
  82. };
  83. /* Definitions for Senddata */
  84. osThreadId_t SenddataHandle;
  85. const osThreadAttr_t Senddata_attributes = {
  86. .name = "Senddata",
  87. .stack_size = 128 * 4,
  88. .priority = (osPriority_t) osPriorityNormal,
  89. };
  90. /* Definitions for Common */
  91. osThreadId_t CommonHandle;
  92. const osThreadAttr_t Common_attributes = {
  93. .name = "Common",
  94. .stack_size = 128 * 4,
  95. .priority = (osPriority_t) osPriorityAboveNormal,
  96. };
  97. /* Definitions for myQueue01 */
  98. osMessageQueueId_t myQueue01Handle;
  99. const osMessageQueueAttr_t myQueue01_attributes = {
  100. .name = "myQueue01"
  101. };
  102. /* Definitions for myQueue02 */
  103. osMessageQueueId_t myQueue02Handle;
  104. uint8_t myQueue02Buffer[ 16 * sizeof( uint16_t ) ];
  105. osStaticMessageQDef_t myQueue02ControlBlock;
  106. const osMessageQueueAttr_t myQueue02_attributes = {
  107. .name = "myQueue02",
  108. .cb_mem = &myQueue02ControlBlock,
  109. .cb_size = sizeof(myQueue02ControlBlock),
  110. .mq_mem = &myQueue02Buffer,
  111. .mq_size = sizeof(myQueue02Buffer)
  112. };
  113. /* Definitions for dataMutex */
  114. osMutexId_t dataMutexHandle;
  115. const osMutexAttr_t dataMutex_attributes = {
  116. .name = "dataMutex"
  117. };
  118. /* Definitions for dataReadySem */
  119. osSemaphoreId_t dataReadySemHandle;
  120. const osSemaphoreAttr_t dataReadySem_attributes = {
  121. .name = "dataReadySem"
  122. };
  123. /* Private function prototypes -----------------------------------------------*/
  124. /* USER CODE BEGIN FunctionPrototypes */
  125. /* USER CODE END FunctionPrototypes */
  126. void ReadpressureTask(void *argument);
  127. void SenddataTask(void *argument);
  128. void CommonTask(void *argument);
  129. void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
  130. /**
  131. * @brief FreeRTOS initialization
  132. * @param None
  133. * @retval None
  134. */
  135. void MX_FREERTOS_Init(void) {
  136. /* USER CODE BEGIN Init */
  137. // Read_NODE_ID_From_Flash();
  138. Read_parameter_From_Flash();
  139. NODE_ID = 04;
  140. /* USER CODE END Init */
  141. /* Create the mutex(es) */
  142. /* creation of dataMutex */
  143. dataMutexHandle = osMutexNew(&dataMutex_attributes);
  144. /* USER CODE BEGIN RTOS_MUTEX */
  145. /* add mutexes, ... */
  146. /* USER CODE END RTOS_MUTEX */
  147. /* Create the semaphores(s) */
  148. /* creation of dataReadySem */
  149. dataReadySemHandle = osSemaphoreNew(1, 1, &dataReadySem_attributes);
  150. /* USER CODE BEGIN RTOS_SEMAPHORES */
  151. /* add semaphores, ... */
  152. /* USER CODE END RTOS_SEMAPHORES */
  153. /* USER CODE BEGIN RTOS_TIMERS */
  154. /* start timers, add new ones, ... */
  155. /* USER CODE END RTOS_TIMERS */
  156. /* Create the queue(s) */
  157. /* creation of myQueue01 */
  158. myQueue01Handle = osMessageQueueNew (16, sizeof(uint16_t), &myQueue01_attributes);
  159. /* creation of myQueue02 */
  160. myQueue02Handle = osMessageQueueNew (16, sizeof(uint16_t), &myQueue02_attributes);
  161. /* USER CODE BEGIN RTOS_QUEUES */
  162. /* add queues, ... */
  163. /* USER CODE END RTOS_QUEUES */
  164. /* Create the thread(s) */
  165. /* creation of Readpressure */
  166. ReadpressureHandle = osThreadNew(ReadpressureTask, NULL, &Readpressure_attributes);
  167. /* creation of Senddata */
  168. SenddataHandle = osThreadNew(SenddataTask, NULL, &Senddata_attributes);
  169. /* creation of Common */
  170. CommonHandle = osThreadNew(CommonTask, NULL, &Common_attributes);
  171. /* USER CODE BEGIN RTOS_THREADS */
  172. /* add threads, ... */
  173. /* USER CODE END RTOS_THREADS */
  174. /* USER CODE BEGIN RTOS_EVENTS */
  175. /* add events, ... */
  176. /* USER CODE END RTOS_EVENTS */
  177. }
  178. /* USER CODE BEGIN Header_ReadpressureTask */
  179. /**
  180. * @brief Function implementing the Readpressure thread.
  181. * @param argument: Not used
  182. * @retval None
  183. */
  184. /* USER CODE END Header_ReadpressureTask */
  185. void ReadpressureTask(void *argument)
  186. {
  187. /* USER CODE BEGIN ReadpressureTask */
  188. /* Infinite loop */
  189. uint8_t sequence =0;
  190. uint8_t slice_num = 1;
  191. for(;;)
  192. {
  193. Read_PressureData();
  194. memcpy(data_P02, data_P01, 3);
  195. printf("data_P02: ");
  196. for (int i = 0; i < 8; i++) {
  197. printf("%02X ", data_P02[i]);
  198. }
  199. printf("\n");
  200. // control_MLX90640_power(false);
  201. CAN_Send_Msg(data_P02, 8, NODE_ID, sequence, slice_num, 0);
  202. sequence++;
  203. // printf("1\n");
  204. Enter_LPStop2Mode();
  205. osDelay(500);
  206. // if (osMutexAcquire(dataMutexHandle, pdMS_TO_TICKS(600)) == osOK)// 获取互斥量
  207. // {
  208. // memcpy(data_P02, data_P01, 3);
  209. // osMutexRelease(dataMutexHandle);// 释放互斥量
  210. // }
  211. }
  212. /* USER CODE END ReadpressureTask */
  213. }
  214. /* USER CODE BEGIN Header_SenddataTask */
  215. /**
  216. * @brief Function implementing the Senddata thread.
  217. * @param argument: Not used
  218. * @retval None
  219. */
  220. /* USER CODE END Header_SenddataTask */
  221. void SenddataTask(void *argument)
  222. {
  223. /* USER CODE BEGIN SenddataTask */
  224. /* Infinite loop */
  225. // TickType_t pxPreviousWakeTime = xTaskGetTickCount();
  226. // uint8_t sequence =0;
  227. // uint8_t slice_num = 1;
  228. // uint32_t send_interval = 0;
  229. // Bus-Off 错误处理标志
  230. // static uint32_t last_busoff_time = 0;
  231. // static uint8_t bus_off_flag = 0;
  232. for(;;)
  233. {
  234. // // 1. CAN 错误状态检测部分
  235. // uint32_t can_esr = hcan1.Instance->ESR; // 读取 CAN 错误状态寄存器
  236. // uint8_t lec = (can_esr >> 4) & 0x07; // 最近一次错误类型
  237. // uint8_t tec = (can_esr >> 16) & 0xFF; // 发送错误计数
  238. // uint8_t rec = (can_esr >> 24) & 0xFF; // 接收错误计数
  239. //
  240. // // Bus-Off 状态检测与恢复
  241. // if (can_esr & CAN_ESR_BOFF)
  242. // {
  243. // if (bus_off_flag == 0)
  244. // {
  245. // printf("[CAN ERROR] Bus-Off detected! TEC=%d REC=%d\n", tec, rec);
  246. // bus_off_flag = 1;
  247. // last_busoff_time = HAL_GetTick();
  248. // }
  249. // // 延时恢复:等待 1 秒再尝试复位 CAN
  250. // if (HAL_GetTick() - last_busoff_time > 1000)
  251. // {
  252. // printf("[CAN] Try to recover CAN...\n");
  253. // HAL_CAN_Stop(&hcan1);
  254. // HAL_CAN_Start(&hcan1);
  255. // HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_BUSOFF);
  256. // // 观察是否成功恢复,若未恢复再走 DeInit/Init
  257. // if (hcan1.Instance->ESR & CAN_ESR_BOFF)
  258. // {
  259. // printf("[CAN] Quick recovery failed. Doing full re-init...\n");
  260. // HAL_CAN_DeInit(&hcan1);
  261. // MX_CAN1_Init();
  262. // HAL_CAN_Start(&hcan1);
  263. // HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_BUSOFF);
  264. // }
  265. // printf("[CAN] CAN restarted successfully after Bus-Off!\n");
  266. // bus_off_flag = 0;
  267. // }
  268. // // 跳过本次发送,等待 CAN 恢复
  269. // vTaskDelayUntil(&pxPreviousWakeTime, pdMS_TO_TICKS(10));
  270. // send_interval++;
  271. // continue;
  272. // }
  273. // // Error Passive 警告
  274. // if (tec >= 128 || rec >= 128)
  275. // {
  276. // printf("[CAN WARNING] Error Passive! TEC=%d REC=%d\n", tec, rec);
  277. // }
  278. // // LEC(Last Error Code)
  279. // if (lec != 0)
  280. // {
  281. // switch (lec)
  282. // {
  283. // case 0x01: printf("[CAN LEC] Stuff Error\n"); break;
  284. // case 0x02: printf("[CAN LEC] Form Error\n"); break;
  285. // case 0x03: printf("[CAN LEC] Acknowledgment Error\n"); break;
  286. // case 0x04: printf("[CAN LEC] Bit recessive Error\n"); break;
  287. // case 0x05: printf("[CAN LEC] Bit dominant Error\n"); break;
  288. // case 0x06: printf("[CAN LEC] CRC Error\n"); break;
  289. // default: break;
  290. // }
  291. // }
  292. // // 2. 正常发送部分
  293. // if ((send_interval >= 100 * flash_data.delay_receivedValue))
  294. // {
  295. // if (osMutexAcquire(dataMutexHandle, pdMS_TO_TICKS(200)) == osOK)// 获取互斥量
  296. // {
  297. // CAN_Send_Msg(data_P02, 8, NODE_ID, sequence, slice_num, 0);
  298. // sequence++;
  299. // osMutexRelease(dataMutexHandle);// 释放互斥量
  300. // Enter_LPStop2Mode();
  301. // }
  302. // send_interval=0;
  303. // }
  304. // 等待下一次发送
  305. // vTaskDelayUntil(&pxPreviousWakeTime, pdMS_TO_TICKS(10));
  306. osDelay (10);
  307. // send_interval++;
  308. }
  309. /* USER CODE END SenddataTask */
  310. }
  311. /* USER CODE BEGIN Header_CommonTask */
  312. /**
  313. * @brief Function implementing the Common thread.
  314. * @param argument: Not used
  315. * @retval None
  316. */
  317. /* USER CODE END Header_CommonTask */
  318. void CommonTask(void *argument)
  319. {
  320. /* USER CODE BEGIN CommonTask */
  321. /* Infinite loop */
  322. // uint16_t counter = 0; // 闪灯计数器
  323. for(;;)
  324. {
  325. osDelay(10);
  326. // counter++;
  327. // if (counter >= 500)
  328. // {
  329. // HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_4); // 切换 LED 状态
  330. // counter = 0; // 重置计数器
  331. //// HAL_IWDG_Refresh(&hiwdg);
  332. // }
  333. }
  334. /* USER CODE END CommonTask */
  335. }
  336. /* Private application code --------------------------------------------------*/
  337. /* USER CODE BEGIN Application */
  338. /**
  339. * @breaf CAN相关函数
  340. */
  341. //主板ID 0x00100000
  342. HAL_StatusTypeDef CAN_FilterInit(void)// 初始化CAN过滤器
  343. {
  344. CAN_FilterTypeDef CAN_FilterInitStructure;
  345. // 选择要初始化的过滤器
  346. CAN_FilterInitStructure.FilterBank = 0; // 选择过滤器的过滤库,CAN总线支持多个过滤器
  347. CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK; // 设置过滤模式为ID掩码模式,即根据ID和掩码进行过滤
  348. CAN_FilterInitStructure.FilterScale = CAN_FILTERSCALE_32BIT; // 选择32位的过滤器(过滤器ID + 掩码总共32位)
  349. CAN_FilterInitStructure.FilterFIFOAssignment = CAN_FILTER_FIFO0; // 指定过滤器分配给FIFO0,用于接收来自CAN总线的消息
  350. // 配置第一个过滤器接收 0x00100000
  351. CAN_FilterInitStructure.FilterIdHigh = (0x00100000 >> 13) & 0xFFFF; // 高 16 位
  352. CAN_FilterInitStructure.FilterIdLow = ((0x00100000 << 3) & 0xFFFF) | (1 << 2); // 低 16 位 + IDE 位
  353. CAN_FilterInitStructure.FilterMaskIdHigh = 0xFFFF; // 掩码的高16位设置为全1,表示不对该部分进行匹配过滤
  354. CAN_FilterInitStructure.FilterMaskIdLow = 0xFFFF;
  355. CAN_FilterInitStructure.FilterActivation = CAN_FILTER_ENABLE; // 启用该过滤器,只有符合条件的消息才会通过
  356. if (HAL_CAN_ConfigFilter(&hcan1, &CAN_FilterInitStructure) != HAL_OK)
  357. {
  358. Error_Handler();
  359. return HAL_ERROR;
  360. }
  361. // 配置第二个过滤器接收 0x00110000
  362. CAN_FilterInitStructure.FilterBank = 1; // 使用下一个过滤器
  363. CAN_FilterInitStructure.FilterIdHigh = (0x00110000 >> 13) & 0xFFFF;
  364. CAN_FilterInitStructure.FilterIdLow = ((0x00110000 << 3) & 0xFFFF) | (1 << 2);
  365. if (HAL_CAN_ConfigFilter(&hcan1, &CAN_FilterInitStructure) != HAL_OK)
  366. {
  367. Error_Handler();
  368. return HAL_ERROR;
  369. }
  370. if (HAL_CAN_Init(&hcan1) != HAL_OK)// 初始化CAN外设
  371. {
  372. // 如果CAN初始化失败,打印错误信息并进入错误处理
  373. uint32_t can_error = HAL_CAN_GetError(&hcan1);
  374. printf("CAN Initialization Error: %ld\n", can_error);
  375. Error_Handler();
  376. return HAL_ERROR;
  377. }
  378. return HAL_OK;
  379. }
  380. void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
  381. {
  382. CAN_RxHeaderTypeDef RX_Header;
  383. uint8_t rxData[8];
  384. if (HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RX_Header, rxData) == HAL_OK)
  385. {
  386. // 检查是否是目标扩展帧
  387. if (RX_Header.ExtId == 0x00100000 && RX_Header.IDE == CAN_ID_EXT)
  388. {
  389. printf("CANID received: 0x%08X\n", RX_Header.ExtId);
  390. if (rxData[1] == 0x00)
  391. {
  392. CAN_Send_Parameter(NODE_ID, 0, &flash_data, 0xFF, 0xFF, 0xFF);
  393. return;
  394. }
  395. // 更新 NODE_ID
  396. if (rxData[0] == 0xFF || rxData[0] == (uint8_t)(NODE_ID & 0xFF))
  397. {
  398. NODE_ID = rxData[1];
  399. // 保存到 Flash
  400. Save_NODEID_To_Flash(NODE_ID);
  401. // 应答
  402. CAN_Send_extId(&NODE_ID, 1, NODE_ID, 0xFF, 0xFF, 0xFF);
  403. }
  404. else if (rxData[0] != (uint8_t)(NODE_ID & 0xFF))
  405. {
  406. // 如果第一个字节和当前 NODE_ID 不一致,则不执行
  407. return;
  408. }
  409. }
  410. else if(RX_Header.ExtId == 0x00110000 && RX_Header.IDE == CAN_ID_EXT)
  411. {
  412. printf("CANID received: 0x%08X\n", RX_Header.ExtId);
  413. if ((rxData[4] == 0 && rxData[5] == 0) || rxData[6] == 0)
  414. {
  415. CAN_Send_Parameter(NODE_ID, 0, &flash_data, 0xFF, 0xFF, 0xFF);
  416. return;
  417. }
  418. flash_data.second_threshold = (rxData[4] << 8) | rxData[5];
  419. flash_data.delay_receivedValue = rxData[6];
  420. // 保存到 Flash
  421. Save_parameter_To_Flash(flash_data.second_threshold, flash_data.delay_receivedValue);
  422. // 应答
  423. CAN_Send_Parameter(NODE_ID, 3, &flash_data, 0xFF, 0xFF, 0xFF);
  424. }
  425. else
  426. {
  427. printf("CANID mismatched!\n");
  428. }
  429. }
  430. else
  431. {
  432. printf("CAN receive failed!Error code: 0x%08lX\n", HAL_CAN_GetError(&hcan1));
  433. }
  434. }
  435. void CAN_Send_Msg(uint8_t *msg,uint8_t len,uint32_t node_id, uint8_t sequence, uint8_t slice_num, uint8_t slice_id)
  436. {
  437. CAN_TxHeaderTypeDef Tx_Header;
  438. uint32_t TxMailBox;
  439. uint32_t ret_status = 0;
  440. // Tx_Header.StdId = id;
  441. Tx_Header.ExtId = (1<<28)|(node_id << 20)|(sequence << 12)|(slice_num << 8)|(slice_id << 4);
  442. Tx_Header.IDE = CAN_ID_EXT;
  443. Tx_Header.RTR = CAN_RTR_DATA;
  444. Tx_Header.DLC = len;
  445. ret_status = HAL_CAN_AddTxMessage(&hcan1,&Tx_Header,msg,&TxMailBox);
  446. if(0 != ret_status){
  447. printf("HAL_CAN_AddTxMessage failed , ret_status:0x%x \r\n", ret_status);
  448. printf("hcan->ErrorCode: 0x%x \r\n", hcan1.ErrorCode);
  449. }
  450. }
  451. void CAN_Send_extId(uint16_t *data, uint8_t len, uint32_t node_id, uint8_t sequence, uint8_t slice_num, uint8_t slice_id)
  452. {
  453. // 配置 CAN 发送消息结构体
  454. CAN_TxHeaderTypeDef Tx_Header;
  455. uint32_t txMailbox;
  456. Tx_Header.ExtId = (0U << 28) // 指令标志位 0
  457. | ((node_id & 0xFF) << 20) // 节点 ID,占 8 位  
  458. | ((sequence & 0xFF) << 12) // 序列号,占 8 位  
  459. | ((slice_num & 0xF) << 8) // 分片总数,占 4 位  
  460. | ((slice_id & 0xF) << 4); // 当前分片 ID,占 4 位
  461. Tx_Header.IDE = CAN_ID_EXT; // 扩展帧
  462. Tx_Header.RTR = CAN_RTR_DATA; // 数据帧
  463. Tx_Header.DLC = len; // 数据长度
  464. if (HAL_CAN_AddTxMessage(&hcan1, &Tx_Header, (uint8_t *)data, &txMailbox) != HAL_OK) {
  465. printf("CAN message send failed\n");
  466. } else {
  467. // 将数据转换为十六进制字符串形式
  468. char dataStr[len * 3]; // 每字节 3 个字符 (2个字符 + 空格)
  469. for (uint8_t i = 0; i < len; i++) {
  470. sprintf(&dataStr[i * 3], "%02X ", data[i]);
  471. }
  472. printf("CAN message sent: ID=0x%08X, Data=%s\n", Tx_Header.ExtId, dataStr);
  473. }
  474. }
  475. void CAN_Send_Parameter(uint32_t node_id, uint8_t len, FlashData *flash_data, uint8_t sequence, uint8_t slice_num, uint8_t slice_id)
  476. {
  477. CAN_TxHeaderTypeDef Tx_Header;
  478. uint32_t TxMailBox;
  479. uint32_t ret_status = 0;
  480. uint8_t msg[8] = {0};
  481. msg[0] = (flash_data->second_threshold >> 8) & 0xFF;
  482. msg[1] = flash_data->second_threshold & 0xFF;
  483. msg[2] = flash_data->delay_receivedValue;
  484. msg[3] = 0;
  485. msg[4] = 0;
  486. msg[5] = 0;
  487. msg[6] = 0;
  488. msg[7] = 0;
  489. Tx_Header.ExtId = (0U << 28) // 指令标志位 0
  490. | ((node_id & 0xFF) << 20) // 节点 ID,占 8 位  
  491. | ((sequence & 0xFF) << 12) // 序列号,占 8 位  
  492. | ((slice_num & 0xF) << 8) // 分片总数,占 4 位  
  493. | ((slice_id & 0xF) << 4); // 当前分片 ID,占 4 位
  494. Tx_Header.IDE = CAN_ID_EXT;
  495. Tx_Header.RTR = CAN_RTR_DATA;
  496. Tx_Header.DLC = len;
  497. ret_status = HAL_CAN_AddTxMessage(&hcan1,&Tx_Header,msg,&TxMailBox);
  498. if(0 != ret_status){
  499. printf("HAL_CAN_AddTxMessage failed , ret_status:0x%x \r\n", ret_status);
  500. printf("hcan->ErrorCode: 0x%x \r\n", hcan1.ErrorCode);
  501. }
  502. }
  503. /**
  504. * @breaf 内部flash相关函数
  505. */
  506. void Read_NODE_ID_From_Flash(void) // 从 Flash 读取 NODE_ID
  507. {
  508. NODE_ID = *((uint8_t *)FLASH_SECOND_LAST_PAGE_ADDR);
  509. if (NODE_ID == 0xFF)
  510. {
  511. NODE_ID = 02;
  512. }else{
  513. NODE_ID = NODE_ID;
  514. }
  515. printf("Loaded data: NODE_ID=%u\n",NODE_ID);
  516. }
  517. void Read_parameter_From_Flash(void) // 从 Flash 读取 parameter
  518. {
  519. uint8_t *flash_ptr = (uint8_t *)FLASH_LAST_PAGE_ADDR;
  520. if (flash_ptr[0] == 0xFF && flash_ptr[1] == 0xFF) {
  521. flash_data.second_threshold = 100;
  522. }else{
  523. flash_data.second_threshold = (uint16_t)(flash_ptr[0] << 8) | flash_ptr[1];
  524. }
  525. if (flash_ptr[2] == 0xFF) {
  526. flash_data.delay_receivedValue = 29;
  527. }else{
  528. flash_data.delay_receivedValue = flash_ptr[2];
  529. }
  530. printf("Loaded data: second_threshold=%u , delay_receivedValue=%u\n",
  531. flash_data.second_threshold, flash_data.delay_receivedValue);
  532. }
  533. void Save_NODEID_To_Flash(uint8_t NODE_ID) // 向 Flash 写入 NODE_ID
  534. {
  535. uint8_t nodeIDData[4] = { NODE_ID, 0, 0, 0 };
  536. uint8_t readnodeIDData[4];
  537. if (Flash_WriteRead(FLASH_SECOND_LAST_PAGE_ADDR, nodeIDData, sizeof(nodeIDData), readnodeIDData) != SUCCESS) {
  538. printf("Failed to save NODE_ID to flash\n");
  539. } else {
  540. printf("NODE_ID saved to flash: %u\n", nodeIDData[0]);
  541. }
  542. }
  543. void Save_parameter_To_Flash(uint16_t second_threshold, uint8_t delay_receivedValue) // 向 Flash 写入 parameter
  544. {
  545. uint8_t parameter[4] = {0};
  546. parameter[0]= (uint8_t)(second_threshold >> 8);
  547. parameter[1]= (uint8_t)(second_threshold & 0xFF);
  548. parameter[2]= delay_receivedValue;
  549. parameter[3]= 0;
  550. uint8_t readparameterData[4];
  551. if (Flash_WriteRead(FLASH_LAST_PAGE_ADDR, parameter, sizeof(parameter), readparameterData) != SUCCESS) {
  552. printf("Failed to save Parameter to flash\n");
  553. } else {
  554. printf("Parameter saved to flash: [%u] [%u] [%u] [%u] \n", parameter[0], parameter[1], parameter[2], parameter[3]);
  555. }
  556. }
  557. /**
  558. * @breaf 低功耗相关
  559. */
  560. void Configure_GPIOs_For_LowPower(void)
  561. {
  562. GPIO_InitTypeDef GPIO_InitStruct = {0};
  563. // 启用承朿 GPIO 端口的时钿
  564. __HAL_RCC_GPIOA_CLK_ENABLE();
  565. __HAL_RCC_GPIOB_CLK_ENABLE();
  566. __HAL_RCC_RTC_ENABLE();
  567. __HAL_RCC_USART2_CLK_ENABLE();
  568. GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;// 配置为模拟模式,禁用上拉/下拉
  569. GPIO_InitStruct.Pull = GPIO_NOPULL;
  570. GPIO_InitStruct.Pin = GPIO_PIN_All;
  571. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);// 配置 GPIOA
  572. GPIO_InitStruct.Pin = GPIO_PIN_All& ~(GPIO_PIN_15);// 配置 GPIOB
  573. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  574. // 9 10 是IIC,11 12是CAN
  575. HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_SET);
  576. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_15, GPIO_PIN_SET);
  577. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);
  578. __HAL_RCC_GPIOA_CLK_DISABLE();
  579. __HAL_RCC_GPIOB_CLK_DISABLE();
  580. // 关闭外设时钟
  581. __HAL_RCC_USART2_CLK_DISABLE();
  582. __HAL_RCC_I2C1_CLK_DISABLE();
  583. __HAL_RCC_CAN1_CLK_DISABLE();
  584. }
  585. void Enter_LPStop2Mode(void)
  586. {
  587. printf("Entering Stop2\n");
  588. Configure_GPIOs_For_LowPower();
  589. Enable_RTC_Wakeup(flash_data.delay_receivedValue); // 使能 RTC 唤醒
  590. // HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2); // 配置调压器为低功耗模式
  591. HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);// 进入 STOP2 低功耗模式
  592. }
  593. void Wakeup_LPStop2Mode(void)
  594. {
  595. // 重新初始化系统时钟
  596. SystemClock_Config();
  597. NVIC_SystemReset(); // 直接执行软件复位
  598. }
  599. void Enable_RTC_Wakeup(uint16_t delay_time)
  600. {
  601. HAL_RTCEx_DeactivateWakeUpTimer(&hrtc); // 先关闭 RTC 唤醒,防止冲突
  602. // 计算唤醒时间
  603. uint32_t wakeup_counter = delay_time;
  604. // 设置 RTC 唤醒
  605. HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, wakeup_counter, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);
  606. printf("RTC Wakeup Timer set for %d s\n", wakeup_counter);
  607. }
  608. void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
  609. {
  610. printf("RTC callback\n");
  611. // control_MLX90640_power(false);
  612. HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); // 配置调压器为正常模式
  613. NVIC_SystemReset(); // RTC 唤醒后执行软件复位
  614. }
  615. void control_MLX90640_power(bool enable) // 三极管 徐
  616. {
  617. // 低电平 供电,高电平 断电。
  618. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, enable ? GPIO_PIN_RESET : GPIO_PIN_SET);
  619. }
  620. /* USER CODE END Application */