一、低功耗模式的第二种---停止模式,相比于第一种睡眠模式,这种在上种的基础之上关闭了所有1.8V供电的部分以及HSI和HSE外部高速和内部高速时钟。功耗更低
二、进入到该模式的方法
?官方手册中提供了,意思就是要控制寄存器来进入到这个模式,但是我们选择更方便的用库函数
1.想到电源控制,就一定要先开启电源控制的时钟,这里的电源控制时钟被RCC的APB1总线控制
所以第一步:使能它
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
2.选择电源控制的库函数进行设置
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
第一个参数:进入停止模式后电压比较器是否开启,意思你都进入停止模式了,一般的肯定更希望低功耗,所以我先选择关闭,也可以选择打开,就是功耗相对高一点
第二个参数:进入到停止模式后是选择用什么方式进行唤醒。也是和睡眠模式一样又两种方式
WFI(wait for interrupt)和WFE( wait for event);通过事件和中断的方式来唤醒? 这里我还是选用外部中断的方式来唤醒。
注意!这里如果只是唤醒了但是没重新初始化时钟的话,会使得停止模式前后的其他位置工作时钟不一样,导致很多问题(比如通过ststick写的小延时这种就会变慢,需要重新初始化时钟
?这个初始化函数里面就包含了初始化时钟的函数(但是因为里面是系统初始化的? 最好还是不要修改 而且系统函数里面写了static静态的 直接用用不了)
所以建议直接复制一份 在中断唤醒的时候调用就行了;
void SetSysClock_to_72MHz(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL9);
#else
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
#endif /* STM32F10X_CL */
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
void EXTI0_IRQHandler(void) //这个名字是从启动文件中找到的 你进入了什么中断就去找对应的名字
{
LED_TOGGLE;
EXTI_ClearFlag(EXTI_Line0);
EXTI_ClearITPendingBit(EXTI_Line0);
SetSysClock_to_72MHz(); //这里就是重新把时钟变回72Mhz 具体就是上面的 实现内容不用管 照抄就完事
}
这样就能重新初始化时钟? 就能恢复正常了
|