123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721 |
- /* USER CODE BEGIN Header */
- /**
- ******************************************************************************
- * File Name : freertos.c
- * Description : Code for freertos applications
- ******************************************************************************
- * @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 */
- /* Includes ------------------------------------------------------------------*/
- #include "FreeRTOS.h"
- #include "task.h"
- #include "main.h"
- #include "cmsis_os.h"
- /* Private includes ----------------------------------------------------------*/
- /* USER CODE BEGIN Includes */
- #include "semphr.h"
- #include "can.h"
- #include "iwdg.h"
- #include "rtc.h"
- #include "usart.h"
- /* USER CODE END Includes */
- /* Private typedef -----------------------------------------------------------*/
- typedef StaticQueue_t osStaticMessageQDef_t;
- /* USER CODE BEGIN PTD */
- /* USER CODE END PTD */
- /* Private define ------------------------------------------------------------*/
- /* USER CODE BEGIN PD */
- uint8_t data_P01[8] = {0};
- uint8_t data_P02[8] = {0};
- /**
- * @breaf 内部flash参数定义
- */
- #define FLASH_LAST_PAGE_ADDR 0x0801FC00 // STM32L431CCT6 内部Flash第127页起始地址
- #define FLASH_SECOND_LAST_PAGE_ADDR 0x08018800 // STM32L431CCT6 内部Flash第126页起始地址
- uint16_t NODE_ID;//压力传感器 ID 从 2开始 ,0x02 代表 1 号小板
- //typedef struct {
- // uint8_t second_threshold; // 二级警报阈值
- // uint8_t delay_receivedValue; // 初始上报频率
- // uint8_t reserve1;
- // uint8_t reserve2;
- //} FlashData;
- FlashData flash_data = {
- .second_threshold = 100, // 二级警报阈值
- .delay_receivedValue = 1, // 初始上报频率 1s
- .reserve1 = 0,
- };
- /* USER CODE END PD */
- /* Private macro -------------------------------------------------------------*/
- /* USER CODE BEGIN PM */
- void CAN_ErrorCheck(void);
- /* USER CODE END PM */
- /* Private variables ---------------------------------------------------------*/
- /* USER CODE BEGIN Variables */
- void Read_NODE_ID_From_Flash(void);
- void Read_parameter_From_Flash(void) ;
- void Save_NODEID_To_Flash(uint8_t NODE_ID);
- void Save_parameter_To_Flash(uint16_t second_threshold, uint8_t delay_receivedValue);
- 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);
- 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) ;
- void Configure_GPIOs_For_LowPower(void);
- void Enter_LPStop2Mode(void);
- void Wakeup_LPStop2Mode(void);
- void Enable_RTC_Wakeup(uint16_t delay_time);
- void control_MLX90640_power(bool enable) ;
- /* USER CODE END Variables */
- /* Definitions for Readpressure */
- osThreadId_t ReadpressureHandle;
- const osThreadAttr_t Readpressure_attributes = {
- .name = "Readpressure",
- .stack_size = 128 * 4,
- .priority = (osPriority_t) osPriorityNormal,
- };
- /* Definitions for Senddata */
- osThreadId_t SenddataHandle;
- const osThreadAttr_t Senddata_attributes = {
- .name = "Senddata",
- .stack_size = 128 * 4,
- .priority = (osPriority_t) osPriorityNormal,
- };
- /* Definitions for Common */
- osThreadId_t CommonHandle;
- const osThreadAttr_t Common_attributes = {
- .name = "Common",
- .stack_size = 128 * 4,
- .priority = (osPriority_t) osPriorityAboveNormal,
- };
- /* Definitions for myQueue01 */
- osMessageQueueId_t myQueue01Handle;
- const osMessageQueueAttr_t myQueue01_attributes = {
- .name = "myQueue01"
- };
- /* Definitions for myQueue02 */
- osMessageQueueId_t myQueue02Handle;
- uint8_t myQueue02Buffer[ 16 * sizeof( uint16_t ) ];
- osStaticMessageQDef_t myQueue02ControlBlock;
- const osMessageQueueAttr_t myQueue02_attributes = {
- .name = "myQueue02",
- .cb_mem = &myQueue02ControlBlock,
- .cb_size = sizeof(myQueue02ControlBlock),
- .mq_mem = &myQueue02Buffer,
- .mq_size = sizeof(myQueue02Buffer)
- };
- /* Definitions for dataMutex */
- osMutexId_t dataMutexHandle;
- const osMutexAttr_t dataMutex_attributes = {
- .name = "dataMutex"
- };
- /* Definitions for dataReadySem */
- osSemaphoreId_t dataReadySemHandle;
- const osSemaphoreAttr_t dataReadySem_attributes = {
- .name = "dataReadySem"
- };
- /* Private function prototypes -----------------------------------------------*/
- /* USER CODE BEGIN FunctionPrototypes */
- /* USER CODE END FunctionPrototypes */
- void ReadpressureTask(void *argument);
- void SenddataTask(void *argument);
- void CommonTask(void *argument);
- void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
- /**
- * @brief FreeRTOS initialization
- * @param None
- * @retval None
- */
- void MX_FREERTOS_Init(void) {
- /* USER CODE BEGIN Init */
- // Read_NODE_ID_From_Flash();
- Read_parameter_From_Flash();
- NODE_ID = 04;
- /* USER CODE END Init */
- /* Create the mutex(es) */
- /* creation of dataMutex */
- dataMutexHandle = osMutexNew(&dataMutex_attributes);
- /* USER CODE BEGIN RTOS_MUTEX */
- /* add mutexes, ... */
- /* USER CODE END RTOS_MUTEX */
- /* Create the semaphores(s) */
- /* creation of dataReadySem */
- dataReadySemHandle = osSemaphoreNew(1, 1, &dataReadySem_attributes);
- /* USER CODE BEGIN RTOS_SEMAPHORES */
- /* add semaphores, ... */
- /* USER CODE END RTOS_SEMAPHORES */
- /* USER CODE BEGIN RTOS_TIMERS */
- /* start timers, add new ones, ... */
- /* USER CODE END RTOS_TIMERS */
- /* Create the queue(s) */
- /* creation of myQueue01 */
- myQueue01Handle = osMessageQueueNew (16, sizeof(uint16_t), &myQueue01_attributes);
- /* creation of myQueue02 */
- myQueue02Handle = osMessageQueueNew (16, sizeof(uint16_t), &myQueue02_attributes);
- /* USER CODE BEGIN RTOS_QUEUES */
- /* add queues, ... */
- /* USER CODE END RTOS_QUEUES */
- /* Create the thread(s) */
- /* creation of Readpressure */
- ReadpressureHandle = osThreadNew(ReadpressureTask, NULL, &Readpressure_attributes);
- /* creation of Senddata */
- SenddataHandle = osThreadNew(SenddataTask, NULL, &Senddata_attributes);
- /* creation of Common */
- CommonHandle = osThreadNew(CommonTask, NULL, &Common_attributes);
- /* USER CODE BEGIN RTOS_THREADS */
- /* add threads, ... */
- /* USER CODE END RTOS_THREADS */
- /* USER CODE BEGIN RTOS_EVENTS */
- /* add events, ... */
- /* USER CODE END RTOS_EVENTS */
- }
- /* USER CODE BEGIN Header_ReadpressureTask */
- /**
- * @brief Function implementing the Readpressure thread.
- * @param argument: Not used
- * @retval None
- */
- /* USER CODE END Header_ReadpressureTask */
- void ReadpressureTask(void *argument)
- {
- /* USER CODE BEGIN ReadpressureTask */
- /* Infinite loop */
- uint8_t sequence =0;
- uint8_t slice_num = 1;
-
- for(;;)
- {
-
- Read_PressureData();
- memcpy(data_P02, data_P01, 3);
- printf("data_P02: ");
- for (int i = 0; i < 8; i++) {
- printf("%02X ", data_P02[i]);
- }
- printf("\n");
- // control_MLX90640_power(false);
- CAN_Send_Msg(data_P02, 8, NODE_ID, sequence, slice_num, 0);
- sequence++;
- // printf("1\n");
- Enter_LPStop2Mode();
- osDelay(500);
- // if (osMutexAcquire(dataMutexHandle, pdMS_TO_TICKS(600)) == osOK)// 获取互斥量
- // {
- // memcpy(data_P02, data_P01, 3);
- // osMutexRelease(dataMutexHandle);// 释放互斥量
- // }
- }
- /* USER CODE END ReadpressureTask */
- }
- /* USER CODE BEGIN Header_SenddataTask */
- /**
- * @brief Function implementing the Senddata thread.
- * @param argument: Not used
- * @retval None
- */
- /* USER CODE END Header_SenddataTask */
- void SenddataTask(void *argument)
- {
- /* USER CODE BEGIN SenddataTask */
- /* Infinite loop */
- // TickType_t pxPreviousWakeTime = xTaskGetTickCount();
- // uint8_t sequence =0;
- // uint8_t slice_num = 1;
- // uint32_t send_interval = 0;
-
- // Bus-Off 错误处理标志
- // static uint32_t last_busoff_time = 0;
- // static uint8_t bus_off_flag = 0;
-
- for(;;)
- {
- // // 1. CAN 错误状态检测部分
- // uint32_t can_esr = hcan1.Instance->ESR; // 读取 CAN 错误状态寄存器
- // uint8_t lec = (can_esr >> 4) & 0x07; // 最近一次错误类型
- // uint8_t tec = (can_esr >> 16) & 0xFF; // 发送错误计数
- // uint8_t rec = (can_esr >> 24) & 0xFF; // 接收错误计数
- //
- // // Bus-Off 状态检测与恢复
- // if (can_esr & CAN_ESR_BOFF)
- // {
- // if (bus_off_flag == 0)
- // {
- // printf("[CAN ERROR] Bus-Off detected! TEC=%d REC=%d\n", tec, rec);
- // bus_off_flag = 1;
- // last_busoff_time = HAL_GetTick();
- // }
- // // 延时恢复:等待 1 秒再尝试复位 CAN
- // if (HAL_GetTick() - last_busoff_time > 1000)
- // {
- // printf("[CAN] Try to recover CAN...\n");
- // HAL_CAN_Stop(&hcan1);
- // HAL_CAN_Start(&hcan1);
- // HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_BUSOFF);
- // // 观察是否成功恢复,若未恢复再走 DeInit/Init
- // if (hcan1.Instance->ESR & CAN_ESR_BOFF)
- // {
- // printf("[CAN] Quick recovery failed. Doing full re-init...\n");
- // HAL_CAN_DeInit(&hcan1);
- // MX_CAN1_Init();
- // HAL_CAN_Start(&hcan1);
- // HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_BUSOFF);
- // }
- // printf("[CAN] CAN restarted successfully after Bus-Off!\n");
- // bus_off_flag = 0;
- // }
- // // 跳过本次发送,等待 CAN 恢复
- // vTaskDelayUntil(&pxPreviousWakeTime, pdMS_TO_TICKS(10));
- // send_interval++;
- // continue;
- // }
- // // Error Passive 警告
- // if (tec >= 128 || rec >= 128)
- // {
- // printf("[CAN WARNING] Error Passive! TEC=%d REC=%d\n", tec, rec);
- // }
- // // LEC(Last Error Code)
- // if (lec != 0)
- // {
- // switch (lec)
- // {
- // case 0x01: printf("[CAN LEC] Stuff Error\n"); break;
- // case 0x02: printf("[CAN LEC] Form Error\n"); break;
- // case 0x03: printf("[CAN LEC] Acknowledgment Error\n"); break;
- // case 0x04: printf("[CAN LEC] Bit recessive Error\n"); break;
- // case 0x05: printf("[CAN LEC] Bit dominant Error\n"); break;
- // case 0x06: printf("[CAN LEC] CRC Error\n"); break;
- // default: break;
- // }
- // }
- // // 2. 正常发送部分
- // if ((send_interval >= 100 * flash_data.delay_receivedValue))
- // {
- // if (osMutexAcquire(dataMutexHandle, pdMS_TO_TICKS(200)) == osOK)// 获取互斥量
- // {
- // CAN_Send_Msg(data_P02, 8, NODE_ID, sequence, slice_num, 0);
- // sequence++;
- // osMutexRelease(dataMutexHandle);// 释放互斥量
- // Enter_LPStop2Mode();
- // }
- // send_interval=0;
- // }
-
- // 等待下一次发送
- // vTaskDelayUntil(&pxPreviousWakeTime, pdMS_TO_TICKS(10));
- osDelay (10);
- // send_interval++;
- }
- /* USER CODE END SenddataTask */
- }
- /* USER CODE BEGIN Header_CommonTask */
- /**
- * @brief Function implementing the Common thread.
- * @param argument: Not used
- * @retval None
- */
- /* USER CODE END Header_CommonTask */
- void CommonTask(void *argument)
- {
- /* USER CODE BEGIN CommonTask */
- /* Infinite loop */
- // uint16_t counter = 0; // 闪灯计数器
- for(;;)
- {
- osDelay(10);
- // counter++;
- // if (counter >= 500)
- // {
- // HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_4); // 切换 LED 状态
- // counter = 0; // 重置计数器
- //// HAL_IWDG_Refresh(&hiwdg);
- // }
- }
- /* USER CODE END CommonTask */
- }
- /* Private application code --------------------------------------------------*/
- /* USER CODE BEGIN Application */
- /**
- * @breaf CAN相关函数
- */
- //主板ID 0x00100000
- HAL_StatusTypeDef CAN_FilterInit(void)// 初始化CAN过滤器
- {
- CAN_FilterTypeDef CAN_FilterInitStructure;
- // 选择要初始化的过滤器
- CAN_FilterInitStructure.FilterBank = 0; // 选择过滤器的过滤库,CAN总线支持多个过滤器
- CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK; // 设置过滤模式为ID掩码模式,即根据ID和掩码进行过滤
- CAN_FilterInitStructure.FilterScale = CAN_FILTERSCALE_32BIT; // 选择32位的过滤器(过滤器ID + 掩码总共32位)
- CAN_FilterInitStructure.FilterFIFOAssignment = CAN_FILTER_FIFO0; // 指定过滤器分配给FIFO0,用于接收来自CAN总线的消息
- // 配置第一个过滤器接收 0x00100000
- CAN_FilterInitStructure.FilterIdHigh = (0x00100000 >> 13) & 0xFFFF; // 高 16 位
- CAN_FilterInitStructure.FilterIdLow = ((0x00100000 << 3) & 0xFFFF) | (1 << 2); // 低 16 位 + IDE 位
- CAN_FilterInitStructure.FilterMaskIdHigh = 0xFFFF; // 掩码的高16位设置为全1,表示不对该部分进行匹配过滤
- CAN_FilterInitStructure.FilterMaskIdLow = 0xFFFF;
- CAN_FilterInitStructure.FilterActivation = CAN_FILTER_ENABLE; // 启用该过滤器,只有符合条件的消息才会通过
- if (HAL_CAN_ConfigFilter(&hcan1, &CAN_FilterInitStructure) != HAL_OK)
- {
- Error_Handler();
- return HAL_ERROR;
- }
- // 配置第二个过滤器接收 0x00110000
- CAN_FilterInitStructure.FilterBank = 1; // 使用下一个过滤器
- CAN_FilterInitStructure.FilterIdHigh = (0x00110000 >> 13) & 0xFFFF;
- CAN_FilterInitStructure.FilterIdLow = ((0x00110000 << 3) & 0xFFFF) | (1 << 2);
- if (HAL_CAN_ConfigFilter(&hcan1, &CAN_FilterInitStructure) != HAL_OK)
- {
- Error_Handler();
- return HAL_ERROR;
- }
-
- if (HAL_CAN_Init(&hcan1) != HAL_OK)// 初始化CAN外设
- {
- // 如果CAN初始化失败,打印错误信息并进入错误处理
- uint32_t can_error = HAL_CAN_GetError(&hcan1);
- printf("CAN Initialization Error: %ld\n", can_error);
- Error_Handler();
- return HAL_ERROR;
- }
- return HAL_OK;
- }
- void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
- {
- CAN_RxHeaderTypeDef RX_Header;
- uint8_t rxData[8];
- if (HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RX_Header, rxData) == HAL_OK)
- {
- // 检查是否是目标扩展帧
- if (RX_Header.ExtId == 0x00100000 && RX_Header.IDE == CAN_ID_EXT)
- {
- printf("CANID received: 0x%08X\n", RX_Header.ExtId);
- if (rxData[1] == 0x00)
- {
- CAN_Send_Parameter(NODE_ID, 0, &flash_data, 0xFF, 0xFF, 0xFF);
- return;
- }
- // 更新 NODE_ID
- if (rxData[0] == 0xFF || rxData[0] == (uint8_t)(NODE_ID & 0xFF))
- {
- NODE_ID = rxData[1];
- // 保存到 Flash
- Save_NODEID_To_Flash(NODE_ID);
- // 应答
- CAN_Send_extId(&NODE_ID, 1, NODE_ID, 0xFF, 0xFF, 0xFF);
- }
- else if (rxData[0] != (uint8_t)(NODE_ID & 0xFF))
- {
- // 如果第一个字节和当前 NODE_ID 不一致,则不执行
- return;
- }
- }
- else if(RX_Header.ExtId == 0x00110000 && RX_Header.IDE == CAN_ID_EXT)
- {
- printf("CANID received: 0x%08X\n", RX_Header.ExtId);
- if ((rxData[4] == 0 && rxData[5] == 0) || rxData[6] == 0)
- {
- CAN_Send_Parameter(NODE_ID, 0, &flash_data, 0xFF, 0xFF, 0xFF);
- return;
- }
- flash_data.second_threshold = (rxData[4] << 8) | rxData[5];
- flash_data.delay_receivedValue = rxData[6];
- // 保存到 Flash
- Save_parameter_To_Flash(flash_data.second_threshold, flash_data.delay_receivedValue);
- // 应答
- CAN_Send_Parameter(NODE_ID, 3, &flash_data, 0xFF, 0xFF, 0xFF);
- }
- else
- {
- printf("CANID mismatched!\n");
- }
- }
- else
- {
- printf("CAN receive failed!Error code: 0x%08lX\n", HAL_CAN_GetError(&hcan1));
- }
- }
- 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)
- {
- CAN_TxHeaderTypeDef Tx_Header;
- uint32_t TxMailBox;
- uint32_t ret_status = 0;
-
- // Tx_Header.StdId = id;
- Tx_Header.ExtId = (1<<28)|(node_id << 20)|(sequence << 12)|(slice_num << 8)|(slice_id << 4);
- Tx_Header.IDE = CAN_ID_EXT;
- Tx_Header.RTR = CAN_RTR_DATA;
- Tx_Header.DLC = len;
- ret_status = HAL_CAN_AddTxMessage(&hcan1,&Tx_Header,msg,&TxMailBox);
-
- if(0 != ret_status){
- printf("HAL_CAN_AddTxMessage failed , ret_status:0x%x \r\n", ret_status);
- printf("hcan->ErrorCode: 0x%x \r\n", hcan1.ErrorCode);
- }
- }
- 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)
- {
- // 配置 CAN 发送消息结构体
- CAN_TxHeaderTypeDef Tx_Header;
- uint32_t txMailbox;
- Tx_Header.ExtId = (0U << 28) // 指令标志位 0
- | ((node_id & 0xFF) << 20) // 节点 ID,占 8 位
- | ((sequence & 0xFF) << 12) // 序列号,占 8 位
- | ((slice_num & 0xF) << 8) // 分片总数,占 4 位
- | ((slice_id & 0xF) << 4); // 当前分片 ID,占 4 位
- Tx_Header.IDE = CAN_ID_EXT; // 扩展帧
- Tx_Header.RTR = CAN_RTR_DATA; // 数据帧
- Tx_Header.DLC = len; // 数据长度
- if (HAL_CAN_AddTxMessage(&hcan1, &Tx_Header, (uint8_t *)data, &txMailbox) != HAL_OK) {
- printf("CAN message send failed\n");
- } else {
- // 将数据转换为十六进制字符串形式
- char dataStr[len * 3]; // 每字节 3 个字符 (2个字符 + 空格)
- for (uint8_t i = 0; i < len; i++) {
- sprintf(&dataStr[i * 3], "%02X ", data[i]);
- }
- printf("CAN message sent: ID=0x%08X, Data=%s\n", Tx_Header.ExtId, dataStr);
- }
- }
- 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)
- {
- CAN_TxHeaderTypeDef Tx_Header;
- uint32_t TxMailBox;
- uint32_t ret_status = 0;
- uint8_t msg[8] = {0};
- msg[0] = (flash_data->second_threshold >> 8) & 0xFF;
- msg[1] = flash_data->second_threshold & 0xFF;
- msg[2] = flash_data->delay_receivedValue;
- msg[3] = 0;
- msg[4] = 0;
- msg[5] = 0;
- msg[6] = 0;
- msg[7] = 0;
-
- Tx_Header.ExtId = (0U << 28) // 指令标志位 0
- | ((node_id & 0xFF) << 20) // 节点 ID,占 8 位
- | ((sequence & 0xFF) << 12) // 序列号,占 8 位
- | ((slice_num & 0xF) << 8) // 分片总数,占 4 位
- | ((slice_id & 0xF) << 4); // 当前分片 ID,占 4 位
- Tx_Header.IDE = CAN_ID_EXT;
- Tx_Header.RTR = CAN_RTR_DATA;
- Tx_Header.DLC = len;
- ret_status = HAL_CAN_AddTxMessage(&hcan1,&Tx_Header,msg,&TxMailBox);
-
- if(0 != ret_status){
- printf("HAL_CAN_AddTxMessage failed , ret_status:0x%x \r\n", ret_status);
- printf("hcan->ErrorCode: 0x%x \r\n", hcan1.ErrorCode);
- }
- }
- /**
- * @breaf 内部flash相关函数
- */
- void Read_NODE_ID_From_Flash(void) // 从 Flash 读取 NODE_ID
- {
- NODE_ID = *((uint8_t *)FLASH_SECOND_LAST_PAGE_ADDR);
- if (NODE_ID == 0xFF)
- {
- NODE_ID = 02;
- }else{
- NODE_ID = NODE_ID;
- }
- printf("Loaded data: NODE_ID=%u\n",NODE_ID);
- }
- void Read_parameter_From_Flash(void) // 从 Flash 读取 parameter
- {
- uint8_t *flash_ptr = (uint8_t *)FLASH_LAST_PAGE_ADDR;
-
- if (flash_ptr[0] == 0xFF && flash_ptr[1] == 0xFF) {
- flash_data.second_threshold = 100;
- }else{
- flash_data.second_threshold = (uint16_t)(flash_ptr[0] << 8) | flash_ptr[1];
- }
- if (flash_ptr[2] == 0xFF) {
- flash_data.delay_receivedValue = 29;
- }else{
- flash_data.delay_receivedValue = flash_ptr[2];
- }
- printf("Loaded data: second_threshold=%u , delay_receivedValue=%u\n",
- flash_data.second_threshold, flash_data.delay_receivedValue);
- }
- void Save_NODEID_To_Flash(uint8_t NODE_ID) // 向 Flash 写入 NODE_ID
- {
- uint8_t nodeIDData[4] = { NODE_ID, 0, 0, 0 };
- uint8_t readnodeIDData[4];
- if (Flash_WriteRead(FLASH_SECOND_LAST_PAGE_ADDR, nodeIDData, sizeof(nodeIDData), readnodeIDData) != SUCCESS) {
- printf("Failed to save NODE_ID to flash\n");
- } else {
- printf("NODE_ID saved to flash: %u\n", nodeIDData[0]);
- }
- }
- void Save_parameter_To_Flash(uint16_t second_threshold, uint8_t delay_receivedValue) // 向 Flash 写入 parameter
- {
- uint8_t parameter[4] = {0};
- parameter[0]= (uint8_t)(second_threshold >> 8);
- parameter[1]= (uint8_t)(second_threshold & 0xFF);
- parameter[2]= delay_receivedValue;
- parameter[3]= 0;
- uint8_t readparameterData[4];
- if (Flash_WriteRead(FLASH_LAST_PAGE_ADDR, parameter, sizeof(parameter), readparameterData) != SUCCESS) {
- printf("Failed to save Parameter to flash\n");
- } else {
- printf("Parameter saved to flash: [%u] [%u] [%u] [%u] \n", parameter[0], parameter[1], parameter[2], parameter[3]);
- }
- }
- /**
- * @breaf 低功耗相关
- */
- void Configure_GPIOs_For_LowPower(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- // 启用承朿 GPIO 端口的时钿
- __HAL_RCC_GPIOA_CLK_ENABLE();
- __HAL_RCC_GPIOB_CLK_ENABLE();
-
- __HAL_RCC_RTC_ENABLE();
- __HAL_RCC_USART2_CLK_ENABLE();
-
- GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;// 配置为模拟模式,禁用上拉/下拉
- GPIO_InitStruct.Pull = GPIO_NOPULL;
-
- GPIO_InitStruct.Pin = GPIO_PIN_All;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);// 配置 GPIOA
-
- GPIO_InitStruct.Pin = GPIO_PIN_All& ~(GPIO_PIN_15);// 配置 GPIOB
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
- // 9 10 是IIC,11 12是CAN
- HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_15, GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);
-
- __HAL_RCC_GPIOA_CLK_DISABLE();
- __HAL_RCC_GPIOB_CLK_DISABLE();
-
- // 关闭外设时钟
- __HAL_RCC_USART2_CLK_DISABLE();
- __HAL_RCC_I2C1_CLK_DISABLE();
- __HAL_RCC_CAN1_CLK_DISABLE();
- }
- void Enter_LPStop2Mode(void)
- {
- printf("Entering Stop2\n");
- Configure_GPIOs_For_LowPower();
- Enable_RTC_Wakeup(flash_data.delay_receivedValue); // 使能 RTC 唤醒
- // HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2); // 配置调压器为低功耗模式
- HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);// 进入 STOP2 低功耗模式
- }
- void Wakeup_LPStop2Mode(void)
- {
- // 重新初始化系统时钟
- SystemClock_Config();
- NVIC_SystemReset(); // 直接执行软件复位
- }
- void Enable_RTC_Wakeup(uint16_t delay_time)
- {
- HAL_RTCEx_DeactivateWakeUpTimer(&hrtc); // 先关闭 RTC 唤醒,防止冲突
- // 计算唤醒时间
- uint32_t wakeup_counter = delay_time;
- // 设置 RTC 唤醒
- HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, wakeup_counter, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);
- printf("RTC Wakeup Timer set for %d s\n", wakeup_counter);
- }
- void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
- {
- printf("RTC callback\n");
- // control_MLX90640_power(false);
- HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); // 配置调压器为正常模式
- NVIC_SystemReset(); // RTC 唤醒后执行软件复位
- }
- void control_MLX90640_power(bool enable) // 三极管 徐
- {
- // 低电平 供电,高电平 断电。
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, enable ? GPIO_PIN_RESET : GPIO_PIN_SET);
- }
- /* USER CODE END Application */
|