在本章节中,首先向大家介绍电源系统结构,接着简述三种低功耗模式,最后重点介绍CKS32F4xx系列如何进入STOP模式以及使用按键实现中断唤醒。
CKS32F4xx电源系统介绍
CKS32F4xx系列的电源系统框图
CKS32F4xx系列的器件工作电压(VDD)为1.8~3.6V。
①备份域电路:包含LSE振荡器、RTC、备份寄存器及备份SRAM。电源开关自动切换VDD和VBAT供电。
②调压器电路(1.2V域):为备份域及待机电路外的所有数字电路供电,其中包括内核、数字外设及RAM。
③ADC电路和参考电压:ADC工作电源使用VDDA引脚输入,使用VSSA作为独立的地连接,VREF引脚则为ADC提供测量使用的参考电压。
低功耗模式简介
CKS32F4xx系列按功耗由高到低排列,分别是运行、睡眠、停止(STOP)和待机(STANDBY)四种工作模式。上电复位后,CKS32F4xx系列会处于正常运行状态,当不需要继续运行内核时,就可以选择进入后面的三种低功耗模式降低功耗。这三种模式中,电源消耗不同、唤醒时间不同、唤醒源不同,用户需要根据应用需求,选择最佳的低功耗模式。其中,最低功耗的是待机模式,停机模式(STOP)是次低功耗的,最后是睡眠模式。低功耗相关寄存器主要有SCB_SCR、PWR_CR、PWR_CSR,进入各种低功耗需要调用的指令有WFI或WFE,以下做简要介绍。
1.SCB_SCR(系统控制寄存器)
若进入停止模式or待机模式,需将SLEEPDEEP置1。
2.PWR_CR(电源控制寄存器)
若进入停止模式,需将PDDS清0,LPDS选调节器模式;若进入待机模式,需将PDDS置1,清除唤醒位CWUF。
3.PWR_CSR(电源控制/状态寄存器)
若芯片处于待机模式下,需使用使用WKUP引脚唤醒并需要清除WUF标记位。
注:WKUP上升沿才能唤醒待机状态,清除WUF标记位实则需操作CWUF位。
4.WFI与WFE指令
实质上都是内核指令,在库文件core_cmInstr.h中把这些指令封装成了函数,调用它们都能进入低功耗模式。调用时,需要使用函数的格式“__WFI();”和“__WFE();”,这是因为__wfi及__wfe是编译器内置的函数,函数内部使用调用了相应的汇编指令。其中WFI指令决定了它需要用中断唤醒,而WFE则决定了它可用事件来唤醒。
以下表格是对三种低功耗模式的简要概述。
本章中,我们主要对CKS32F4xx系列的低功耗模式—停止模式(STOP)做详细介绍。该模式中,由于其1.2V区域的部分电源没有关闭,会保留内核的寄存器、内存的信息,所以从STOP模式唤醒,并重新开启时钟后,还可以从上次停止处继续执行代码。停止模式可以由任意一个外部中断(EXTI)唤醒。在停止模式中可以选择电压调节器为开模式或低功耗模式,可选择内部FLASH工作在正常模式或掉电模式。那我们如何进入STOP模式,可以按照下述表格中的步骤执行即可:
CKS32F4xx系列标准库把进入STOP模式这部分的操作封装到PWR_EnterSTOPMode函数中了,并且需要注意的是进入STOP模式后,CKS32F4xx系列的所有IO都保持在停止前的状态,且当它被唤醒时,CKS32F4xx系列使用HSI作为系统时钟运行,由于系统时钟会影响很多外设的工作状态,所以一般我们在唤醒后会重新开启HSE,把系统时钟设置为原来的状态。上面表格也提到在停止模式中,还可以控制FLASH的供电,使用库函数PWR_FlashPowerDownCmd配置进入掉电状态还是正常供电状态,本质上是封装了一个对FPDS寄存器位操作的语句,使用时需要再进入停止模式前被调用,可以进一步降低功耗。
采用EXTI唤醒STOP模式实验
程序设计主要要点如下:
① 初始化用于唤醒的中断按键;
② 配置不用的I/O端口;
③ 设置停滞状态是FLASH掉电以及选择电压调节器的工作模式并进入停止状态;
④ 使用按键中断唤醒芯片;
⑤ 重启HSE时钟,使系统完全恢复停止之前的状态。
1)初始化用于唤醒的中断按键
此处选择连接PB1引脚的按键用于将芯片从STOP模式唤醒,代码如下:
void CKS_EXTI_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); /* Configure PB1 as EXTI */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure); /* Configure PB1 to EXTI line 1 */ SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB,EXTI_PinSource1); /* EXTI configuration */ EXTI_InitStructure.EXTI_Line = EXTI_Line1; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); /* NVIC configuration */ NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }
在CKS_EXTI_Init函数中,首先使能GPIOB时钟,又因为用到外部中断,所以必须先使能SYSCFG时钟,接着对GPIOB初始化为上拉输入,并调用函数 SYSCFG_EXTILineConfig配置GPIOB.1连接到中断线1,最后初始化EXTI中断线以及NVIC中断优先级。
void EXTI1_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line1) != RESET) { EXTI_ClearITPendingBit(EXTI_Line1); } }
在中断服务函数EXTI1_IRQHandler内,主要是清除LINE1上的中断标志位。
2)配置未使用的I/O口
进入STOP模式之前,需要对I/O进行处理,若不处理很多配置为输入浮空的I/O口在受到外界干扰的时候,状态不定,消耗大量的电流,代码如下:
void CKS_Stop_Mode_IO_Set(void) { /* set pins not used to AIN */ GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOI, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_Init(GPIOF, &GPIO_InitStructure); GPIO_Init(GPIOG, &GPIO_InitStructure); GPIO_Init(GPIOH, &GPIO_InitStructure); GPIO_Init(GPIOI, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = (~GPIO_Pin_1); GPIO_Init(GPIOB, &GPIO_InitStructure); }
由上述代码可知,我们将没用到的I/O全部设置为模拟输入,保留PB1作为按键,产生外部中断来将芯片从STOP模式唤醒。
3)芯片进入STOP模式
该部分代码一般是程序执行一段时间再调用,我们先使用PWR_FlashPowerDownCmd配置停止模式下FLASH使用掉电模式,随后调用PWR_EnterSTOPMode把调压器设置在低功耗模式,最后使用WFI指令进入停止状态。由上文可知,WFI进入停止模式可由任意的EXTI的中断唤醒,所以此处使用按键中断唤醒是可行的,代码如下:
void CKS_Set_Stop_Mode(void) { PWR_FlashPowerDownCmd (ENABLE); PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI); }
4)主函数配置
本例程中主函数主要对上文所述函数调用,程序编译下载至开发板,先进行相关外设初始化后,直接进入STOP模式,此时按下按键,芯片可立即被唤醒,随即又进入STOP模式,循环往复,主函数代码如下:
int main(void) { GPIO_Configuration(); CKS_EXTI_Init(); CKS_Stop_Mode_IO_Set(); while (1) { CKS_Stop_Mode_IO_Set(); CKS_Set_Stop_Mode(); SystemInit(); Delay(0xffffff); } }
来源:中科芯MCU
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。