当前位置: 首页 > news >正文

江科大睡眠,停止,待机模式hal库实现

修改主频我们直接在cubeMx上面修改就行了,很方便

睡眠,停止,待机模式是通过对电源的控制来进行的,相关代码在PWR文件里面

SEV(Send Event)

void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry)
void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry)
void HAL_PWR_EnterSTANDBYMode(void)

当调用HAL_PWR_EnableSleepOnExit()后,处理器在中断服务程序结束返回时,会自动进入睡眠模式,除非有其他中断发生或者手动禁止该功能。

参数Regulator为调节器,PWR_MAINREGULATOR_ON主调节器,PWR_LOWPOWERREGULATOR_ON低功耗调节器

进入睡眠模式后的程序下载

按住复位键不松手,点击下载然后松手

我们把进入睡眠模式的代码写入主循环中,能一直观察到running,也就是没有成功进入睡眠模式,这是因为hal库的底层代码,systick会每隔一段时间刷新并触发一次中断,这个中断会使我们退出睡眠模式。

所以我们得在进入睡眠模式前面关闭tick时钟,在从睡眠模式恢复的时候再开启tick时钟

hal库睡眠模式串口收发

uint8_t RxData;
uint8_t Serial_RxFlag;
uint8_t Serial_GetRxFlag(void)
{if (Serial_RxFlag == 1)			//如果标志位为1{Serial_RxFlag = 0;return 1;					//则返回1,并自动清零标志位}return 0;						//如果标志位为0,则返回0
}int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_USART1_UART_Init();OLED_Init();OLED_ShowString(1, 1, "RxData:");HAL_UART_Receive_IT(&huart1,&RxData,1);while (1){if (Serial_GetRxFlag() == 1)			//检查串口接收数据的标志位{Serial_SendByte(RxData);			//串口将收到的数据回传回去,用于测试,hal库我们使用的是中断接收,所以就不需要和江科大一样把变量先读取再发送,直接发送就行了OLED_ShowHexNum(1, 8, RxData, 2);	//显示串口接收的数据}OLED_ShowString(2, 1, "Running");		//OLED闪烁Running,指示当前主循环正在运行HAL_Delay(100);OLED_ShowString(2, 1, "       ");HAL_Delay(100);HAL_SuspendTick();HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON,PWR_SLEEPENTRY_WFI);HAL_ResumeTick();  }
}void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){if(huart == &huart1){Serial_RxFlag = 1;HAL_UART_Receive_IT(&huart1,&RxData,1);}
}

hal库停止模式红外对射接收器计次

while (1){/* USER CODE END WHILE */OLED_ShowNum(1, 7, CountSensor_Get(), 5);			//OLED不断刷新显示CountSensor_Get的返回值OLED_ShowString(2, 1, "Running");					//OLED闪烁Running,指示当前主循环正在运行HAL_Delay(100);OLED_ShowString(2, 1, "       ");HAL_Delay(100);/* USER CODE BEGIN 3 */HAL_SuspendTick();HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON,PWR_STOPENTRY_WFI);HAL_ResumeTick();SystemClock_Config();}

停止模式结束后得重新对系统的时钟进行配置,所以我们在停止模式的后面加上cubeMx给我们生成的时钟配置函数即可。

hal库待机模式实时时钟

RTC_ReadTimeCounter()是hal库的获取时间戳的函数,这个函数在rtc文件里面是静态的,要获取时间戳的话得把他的前缀static删掉,并在.h文件里面进行声明。

标准库的闹钟设置是直接通过时间戳来设置的,而hal库的需要定义一个时间结构体作为闹钟结构体的成员,再初始化闹钟,对于相差10s的闹钟这类应用很差,不如标准库,但是对于定时时钟的闹钟效果比标准库的更直白。

闹钟配置函数

HAL_StatusTypeDef RTC_SetAlarmTenSecondsLater(RTC_HandleTypeDef *hrtc)
{RTC_TimeTypeDef sTime = {0};RTC_AlarmTypeDef sAlarm = {0};HAL_StatusTypeDef status = HAL_ERROR;/* 检查参数 */if (hrtc == NULL){return HAL_ERROR;}/* 获取当前时间 */if (HAL_RTC_GetTime(hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK){return HAL_ERROR;}/* 计算十秒后的时间 */sTime.Seconds += 10;/* 处理秒数进位 */if (sTime.Seconds >= 60){sTime.Seconds -= 60;sTime.Minutes++;if (sTime.Minutes >= 60){sTime.Minutes -= 60;sTime.Hours++;if (sTime.Hours >= 24){sTime.Hours -= 24;/* 注意:这里没有处理日期进位,因为RTC_DateTypeDef未获取 */}}}/* 配置闹钟结构体 */sAlarm.AlarmTime = sTime;sAlarm.Alarm = 0x00;//闹钟成员编号,单个闹钟无用/* 设置闹钟 */status = HAL_RTC_SetAlarm_IT(hrtc, &sAlarm, RTC_FORMAT_BIN);/* 配置闹钟中断 (可选,如需要中断处理) */if (status == HAL_OK){HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 0, 0);HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);}return status;
}

相比于标准库的直接写入时间戳,hal库的这类闹钟配置比较复杂

  RTC_DateTypeDef GetData;  //获取日期结构体RTC_TimeTypeDef GetTime;   //获取时间结构体HAL_StatusTypeDef RTC_SetAlarmTenSecondsLater(RTC_HandleTypeDef *hrtc);
uint32_t Alarm;
int main(void)
{HAL_Init();SystemClock_Config();OLED_Init();MX_GPIO_Init();MX_RTC_Init();/*显示静态字符串*/OLED_ShowString(1, 1, "CNT :");OLED_ShowString(2, 1, "ALR :");OLED_ShowString(3, 1, "ALRF:");HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);//wake up标志位得手动清除,不然会一直存在导致程序一直处于唤醒Alarm = RTC_ReadTimeCounter(&hrtc) + 10;			//闹钟为唤醒后当前时间的后10sOLED_ShowNum(2, 6, Alarm, 10);					//显示闹钟值RTC_SetAlarmTenSecondsLater(&hrtc);while (1){OLED_ShowNum(1, 6, RTC_ReadTimeCounter(&hrtc), 10);	//显示32位的秒计数器OLED_ShowNum(3, 6, __HAL_RTC_ALARM_EXTI_GET_FLAG(), 1);		//显示闹钟标志位OLED_ShowString(4, 1, "Running");			//OLED闪烁Running,指示当前主循环正在运行HAL_Delay(100);OLED_ShowString(4, 1, "       ");HAL_Delay(100);OLED_ShowString(4, 9, "STANDBY");			//OLED闪烁STANDBY,指示即将进入待机模式HAL_Delay(1000);OLED_ShowString(4, 9, "       ");HAL_Delay(100);OLED_Clear();								//OLED清屏,模拟关闭外部所有的耗电设备,以达到极度省电HAL_SuspendTick();HAL_PWR_EnterSTANDBYMode();     //STM32进入停止模式,并等待指定的唤醒事件(WKUP上升沿或RTC闹钟)HAL_ResumeTick();}
}

相关文章:

  • 长参考帧LTR
  • [Java 基础]面向对象-多态
  • C语言到底使用什么编码
  • git删除本地分支和远程分支
  • 【力扣】3403. 从盒子中找出字典序最大的字符串 I
  • 2025年6月4日收获
  • 佳易王钟表手表维修养护管理系统:高效便捷的维修管理解决方案
  • NX948NX951美光固态芯片NX956NX960
  • 《江西棒垒球》败方mvp叫什么·棒球1号位
  • Python数据可视化科技图表绘制系列教程(二)
  • 高防IP可以防护什么攻击类型?企业网络安全的第一道防线
  • zookeeper 学习
  • 尝试使用gocryptfs实现大模型加密部署
  • 如何利用乐维网管进行IP管理
  • Python中的`with`语句用法
  • 如何选择合适的分库分表策略
  • MQTT协议:物联网时代的通信基石
  • 《manacher》题集
  • LLM之RAG实战(五十四)| 复杂文档处理RAG框架:Ragflow
  • 列出浏览器所有的启动参数,并解释说明每个参数的含义
  • 电子商务网站建设需要什么/广告公司推广平台
  • 九江网站推广/企业网站推广的形式有
  • 建wap网站/百度收录提交申请网站
  • 做模式网站/重庆seo海洋qq
  • 哪些平台可以建立网站/网站友链查询源码
  • 2017设计工作室做网站/湖南网站营销seo方案