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

江科大睡眠,停止,待机模式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();}
}

http://www.xdnf.cn/news/11782.html

相关文章:

  • MySQL范式和反范式
  • Windows安装docker desktop
  • 【使用JAVA调用deepseek】实现自能回复
  • Devops自动化运维---py基础篇一
  • Appium如何支持ios真机测试
  • CppCon 2014 学习:Mixins for C++
  • 基于行为分析的下一代安全防御指南
  • webPack基本使用步骤
  • Cocos creator游戏开发面试题
  • Windows+Linux安装redis教程
  • Qt 中,设置事件过滤器(Event Filter)的方式
  • Java面试专项一-准备篇
  • 【2025】使用docker compose一键部署项目到服务器(4)
  • 【Web应用】若依框架:基础篇14 源码阅读-后端代码分析-课程管理模块前后端代码分析
  • WINDOWS11安装ipython3
  • sql入门语句-案例
  • ‘pnpm‘ 不是内部或外部命令,也不是可运行的程序
  • DrissionPage调试工具:网页自动化与数据采集的革新利器
  • Kafka消息队列
  • 洛谷 P1758 [NOI2009] 管道取珠(DP)
  • 小型民用AUV用途与研究
  • Linux RPC 和 NFS 教程
  • postman自动化测试
  • 玄机-日志分析-IIS日志分析
  • 网络各类型(BMA,NBMA,P2P)
  • Apache POI操作Excel详解
  • 微信小程序实现运动能耗计算
  • 区域徘徊检测算法AI智能分析网关V4助力公共场所/工厂等多场景安全升级
  • 时序数据库IoTDB与EdgeX Foundry集成适配服务介绍
  • RabbitMQ 开机启动配置教程