如何做网站与网页,网站模板怎么打开,集约化网站建设的函,正规的锦州网站建设电源管理 STM32 HAL库对电源管理提供了完善的函数和命令。 工作模式#xff08;高功耗-低功耗#xff09;#xff1a;运行、睡眠、停止、待机。 若备份域电源正常供电#xff0c;备份域内的RTC都可以正常运行#xff0c;备份域内的寄存器的数据会被保存#xff0c;不… 电源管理 STM32 HAL库对电源管理提供了完善的函数和命令。 工作模式高功耗-低功耗运行、睡眠、停止、待机。 若备份域电源正常供电备份域内的RTC都可以正常运行备份域内的寄存器的数据会被保存不受功耗模式影响。 上电复位POR和掉电复位PDR 当检测到VDD的电压低于阈值VPOR及VPDR时无需外部电路辅助STM32芯片会自动保持在复位状态防止因电压不足强行工作而带来严重的后果。 在刚开始电压低于VPOR时约1.92VSTM32保持在上电复位状态PORPower On Reset。当VDD电压持续上升至大于VPOR时芯片开始正常运行。 而在芯片开始正常运行的时候当检测到VDD电压下降至低于VPDR阈值约1.88V会进入掉电复位状态PDRPower Down Reset。 配置PVD监控功能 PVD可监控VDD的电压当它低于阈值时可产生PVD中断以让系统进行紧急处理这个阈值可以直接使用库函数PWR_PVDLevelConfig配置成某一个的阈值等级。 WFI和WFE命令 进入各种低功耗模式时都需要调用WFI或WFE命令实质上都是内核指令在库文件 core_cm3.h 或 cmsis_armcc.h 中把这些指令封装成了函数。 /* 等待中断。是一种暂停执行指令暂停至任意中断产生后被唤醒 */
#define __WFI __wfi/* 等待事件。是一种暂停执行指令暂停至任意事件产生后被唤醒 */
#define __WFE __wfe 这两个指令调用后都能进入低功耗模式需要使用__WFI();和__WFE();来调用因为__wfi和__wfe是编译器内置的函数函数内部调用了相对应的汇编指令。 具体可查《cortex-CM3/CM4权威指南》。 进入停止模式 直接调用WFI和WFE指令可以进入睡眠模式而进入停止模式这还需要在调用指令前设置一些寄存器位STM32 HAL库把这部分的操作封装到HAL_PWR_EnterSTOPMode()。 /*** brief 进入停止模式* note 在停止模式下所有I/O都会保持在停止前的状态.* note 当使用中断或唤醒事件退出停止模式时HSI RC振荡器被选择为系统时钟。* note 当稳压器在低功率模式下工作时从停止模式唤醒时会产生额外的启动延迟。* 通过在停止模式中保持内部稳压器打开虽然启动时间减少但消耗更高。* param Regulator: 在停止模式下指定稳压器状态。* arg PWR_MAINREGULATOR_ON: 稳压器正常运行* arg PWR_LOWPOWERREGULATOR_ON: 稳压器低功耗运行* param STOPEntry: 指定是否使用WFI或WFE指令进入停止模式。* arg PWR_STOPENTRY_WFI: 使用WFI指令进入停止模式* arg PWR_STOPENTRY_WFE: 使用WFE指令进入停止模式* retval None*/
void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry)
{/* 检查参数 */assert_param(IS_PWR_REGULATOR(Regulator));assert_param(IS_PWR_STOP_ENTRY(STOPEntry));/* 清除PWR寄存器中的PDDS位以指定当CPU进入深度睡眠时进入停止模式 */CLEAR_BIT(PWR-CR, PWR_CR_PDDS);/* 根据稳压参数值通过在PWR寄存器中设置LPDS位来选择稳压模式 */MODIFY_REG(PWR-CR, PWR_CR_LPDS, Regulator);/* 设置内核系统控制寄存器的SLEEPDEEP位 */SET_BIT(SCB-SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));/* 选择停止模式进入 */if (STOPEntry PWR_STOPENTRY_WFI){/* 请求等待中断 */__WFI();}else{/* 请求等待事件 */__SEV();PWR_OverloadWfe(); /* 本地重新定义WFE */PWR_OverloadWfe(); /* 本地重新定义WFE */}/* 以下的程序是当重新唤醒时才执行的清除内核系统控制寄存器的SLEEPDEEP位 */CLEAR_BIT(SCB-SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
} 进入停止模式后STM32的所有I/O都保持在停止前的状态而当它被唤醒时STM32使用HSI作为系统时钟8MHz运行由于系统是在会影响很多外设的工作状态所以一般我们在唤醒后会重新开始HSE把系统时钟设置成原来的状态。 进入待机模式
STM32 HAL库把这部分的操作封装到HAL_PWR_EnterSTANDBYMode()。
/*** brief 进入待机模式* note 待机模式下除以下情况外所有I/O引脚均为高阻抗::* - 复位引脚仍然有效* - TAMPER pin if configured for tamper or calibration out.* - WKUP pin (PA0) 如果使能WKUP唤醒功能.* retval None*/
void HAL_PWR_EnterSTANDBYMode(void)
{/* 选择待机模式 */SET_BIT(PWR-CR, PWR_CR_PDDS);/* 设置内核系统控制寄存器的SLEEPDEEP位*/SET_BIT(SCB-SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));/* 存储操作完毕时才能进入待机模式使用以下语句确保存储操作执行完毕 */
#if defined ( __CC_ARM)__force_stores();
#endif/* 请求等待中断 */__WFI();
} 待机模式也可以使用WFE指令进入的如果有需要可以自行修改。 在进入待机模式后除了被使能用于唤醒的I/O其余I/O都进入高阻态而从待机模式唤醒后想防御复位STM32芯片程序重新从头开始执行。 实验环节1PWR_PVD监控
实验操作 使用外部可调电源调节成5V输出连接到开发板5V和GND排针给板子进行供电 复位开发板电压正常时LED为绿色 向下调节可调电源的电压大约降到4V时LED为红色。程序中控制PVD监控电压约为2.8V当5V降到4V时连接STM32的VDD电源会降于2.8V产生PVD事件在中断中控制亮红灯。 注意其他电源线都拔掉包括下载器、USB线。不能远高于5V而导致烧坏开发板。 PVD配置
void PVD_Config(void)
{PWR_PVDTypeDef sConfigPVD;/*使能 PWR 时钟 */__HAL_RCC_PWR_CLK_ENABLE();/* 配置 PVD 中断 */HAL_NVIC_SetPriority(PVD_IRQn, 0 ,0);HAL_NVIC_EnableIRQ(PVD_IRQn); /* 配置PVD级别6 (PVD检测电压的阈值为2.8VVDD电压低于2.8V时产生PVD中断具体数据可查询数据手册获知) 具体级别根据自己的实际应用要求配置*/sConfigPVD.PVDLevel PWR_PVDLEVEL_6;sConfigPVD.Mode PWR_PVD_MODE_IT_RISING_FALLING;HAL_PWR_ConfigPVD(sConfigPVD);/* 使能PVD输出 */HAL_PWR_EnablePVD();
} 测试环节
void PVD_IRQHandler(void)
{HAL_PWR_PVD_IRQHandler();
}void HAL_PWR_PVDCallback(void)
{LED红灯
}void test(void)
{初始化LED绿灯// 配置PVD当电压过低时会进入中断服务函数亮红灯PVD_Config();while(1){}
} 实验环节2PWR睡眠模式
实验操作 LED绿灯正常运行红灯睡眠状态蓝灯刚被唤醒。 KEYkey1和key2配置成IO中断模式。 运行一段时间后自动进入睡眠时间通过按键key1或key2唤醒。 睡眠状态下DAP下载器无法给STM32下载程序可唤醒后再下载或按复位键使芯片处于复位状态下下载后松开复位键。 测试环节
int main(void)
{初始化while (1){LED绿灯HAL_Delay(2000);LED红灯HAL_SuspendTick(); //暂停滴答时钟防止通过滴答时钟中断唤醒//进入睡眠模式HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);//等待中断唤醒 K1或K2按键中断LED蓝灯HAL_ResumeTick(); //被唤醒后恢复滴答时钟HAL_Delay(2000);//继续执行while循环}
} 实验环节3PWR待机模式
实验操作 LED绿灯表示本次复位是上电或引脚复位红灯待机状态蓝灯刚被唤醒。 KEYkey2配置成输入模式。 长按KEY2按键会进入待机模式待机模式下KEY1按键可唤醒唤醒后系统会复位。可通过检测PWR_CSRWUF标志确定复位来源。 待机模式下DAP下载器无法给STM32下载程序可唤醒后再下载。 注意由于WKUP引脚PA0必须使用上升沿才能唤醒待机状态的系统所以硬件设计PA0引脚连接到KEY1且按下KEY1时会在PA0引脚产生上升沿从而可实现唤醒的功能。 测试环节
/*** brief 用于检测按键是否被长时间按下* param 无* retval 1 按键被长时间按下 0 按键没有被长时间按下*/
static uint8_t KEY2_LongPress(void)
{uint8_t downCnt 0; //记录按下的次数uint8_t upCnt 0; //记录松开的次数while (1) //死循环由return结束{ HAL_Delay(20); //延迟一段时间再检测if (HAL_GPIO_ReadPin(KEY2_GPIO_PORT, KEY2_PIN) SET) //检测到按下按键{downCnt; //记录按下次数upCnt 0; //清除按键释放记录if (downCnt 100) //按下时间足够{return 1; //检测到按键被时间长按下}}else{upCnt; //记录释放次数if (upCnt 5) //连续检测到释放超过5次{return 0; //按下时间太短不是按键长按操作}}}
}int main(void)
{初始化/* 使能电源管理单元的时钟,必须要使能时钟才能进入待机模式 */__HAL_RCC_PWR_CLK_ENABLE();//检测复位来源if (__HAL_PWR_GET_FLAG(PWR_FLAG_WU) SET){ // 复位前为待机模式__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);LED蓝灯}else{// 复位前为正常运行LED绿灯}while (1){// K2 按键长按进入待机模式if (KEY2_LongPress()){LED红灯HAL_Delay(1000);/*清除WU状态位*/__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);/* 使能WKUP引脚的唤醒功能使能PA0*/HAL_PWR_EnableWakeUpPin(0x00000100U);//暂停滴答时钟防止通过滴答时钟中断唤醒HAL_SuspendTick();/* 进入待机模式 */HAL_PWR_EnterSTANDBYMode();}}
} 实验现象 开机正常运行绿灯。长按KEY2按键显红灯过1s后进入待机模式LED灭。按下KEY1按键退出待机模式自动复位显蓝灯。按下复位键重新运行绿灯。 实验环节4PWR停止模式
实验操作 LED绿灯正常运行红灯停止状态蓝灯刚被唤醒。 KEYkey1和key2配置成IO中断模式。 运行一段时间后自动进入停止时间通过按键key1或key2唤醒。 待机模式下DAP下载器无法给STM32下载程序可唤醒后再下载。 注意由于WKUP引脚PA0必须使用上升沿才能唤醒待机状态的系统所以硬件设计PA0引脚连接到KEY1且按下KEY1时会在PA0引脚产生上升沿从而可实现唤醒的功能。 测试环节
/*** brief 从停止模式唤醒后配置系统时钟:启用HSE、PLL并选择PLL作为系统时钟源。* param 无* retval 无*/
static void SYSCLKConfig_STOP(void)
{RCC_ClkInitTypeDef RCC_ClkInitStruct {0};RCC_OscInitTypeDef RCC_OscInitStruct {0};uint32_t pFLatency 0;/* 启用电源控制时钟 */__HAL_RCC_PWR_CLK_ENABLE();/* 根据内部RCC寄存器获取振荡器配置 */HAL_RCC_GetOscConfig(RCC_OscInitStruct);/* 从停止模式唤醒后重新配置系统时钟: 启用HSE和PLL */RCC_OscInitStruct.OscillatorType RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState RCC_PLL_ON;if (HAL_RCC_OscConfig(RCC_OscInitStruct) ! HAL_OK){while(1) { ; }}/* 根据内部RCC寄存器获取时钟配置 */HAL_RCC_GetClockConfig(RCC_ClkInitStruct, pFLatency);/* 选择 PLL 作为系统时钟源, 并配置 HCLK、PCLK1 和 PCLK2时钟分频系数 */RCC_ClkInitStruct.ClockType RCC_CLOCKTYPE_SYSCLK;RCC_ClkInitStruct.SYSCLKSource RCC_SYSCLKSOURCE_PLLCLK;if (HAL_RCC_ClockConfig(RCC_ClkInitStruct, pFLatency) ! HAL_OK){while(1) { ; }}
}int main(void)
{uint32_t SYSCLK_Frequency 0; uint32_t HCLK_Frequency 0;uint32_t PCLK1_Frequency 0;uint32_t PCLK2_Frequency 0;uint32_t SYSCLK_Source 0;初始化while(1){ LED绿灯HAL_Delay(2000); // 进入停止模式亮红灯,按KEY1或KEY2按键可唤醒LED_RED;HAL_SuspendTick(); //暂停滴答时钟防止通过滴答时钟中断唤醒/* 进入停止模式设置电压调节器为低功耗模式等待中断唤醒 */HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);// 等待中断唤醒 K1或K2按键中断 // 被唤醒亮蓝灯指示LED蓝灯SystemCoreClockUpdate(); //根据时钟寄存器的值更新SystemCoreClock变量//获取唤醒后的时钟状态 SYSCLK_Frequency HAL_RCC_GetSysClockFreq(); HCLK_Frequency HAL_RCC_GetHCLKFreq();PCLK1_Frequency HAL_RCC_GetPCLK1Freq();PCLK2_Frequency HAL_RCC_GetPCLK2Freq();SYSCLK_Source __HAL_RCC_GET_SYSCLK_SOURCE();/* 从停止模式唤醒后配置系统时钟:启用HSE、PLL*//* 选择PLL作为系统时钟源(HSE和PLL在停止模式下被禁用)*/SYSCLKConfig_STOP();HAL_ResumeTick(); //被唤醒后恢复滴答时钟//获取重新配置后的时钟状态SYSCLK_Frequency HAL_RCC_GetSysClockFreq(); HCLK_Frequency HAL_RCC_GetHCLKFreq();PCLK1_Frequency HAL_RCC_GetPCLK1Freq();PCLK2_Frequency HAL_RCC_GetPCLK2Freq();SYSCLK_Source __HAL_RCC_GET_SYSCLK_SOURCE();HAL_Delay(2000); //继续执行while循环}
}