技术交流QQ群【JAVA,C++,Python,.NET,BigData,AI】:170933152
因为工作需要这里,跳过了LCD的实验,后面会补上
.
待机模式的功耗最低.
进入3种低功耗模式的方法
这里着重说待机模式:
这里这个WKUP引脚,就是PA0这个IO口.
进入到待机模式主要使用到了两个寄存器一个是:
PWR_CR寄存器,这里设置PDDS为可以进入深度睡眠进入待机模式
配置这个位,可以参考文档.
还需要再配置一个:
PWR_CSR寄存器,的这个WUF这个位.
然后还有,SLEEPDEEP这个位.这个位实际上是在SYSTEM CONTROL B..这个寄存器中来配置的
等一会在代码中看是如何配置的
总结一下就是要配置上面看到的标红的这几个位,才能进入待机模式.
然后再看看退出.
这里咱们一般用WKUP引脚的上升沿,来控制唤醒,或者是RTC闹钟事件的上升沿来配置唤醒,
这两个经常用,其他的不怎么用.
然后打开待机唤醒实验来看看:
然后来看一下,待机唤醒的函数.
看到这里有个:
这个待机唤醒的函数
void PWR_WakeUpPinCmd(FunctionalState NewState);
这个就是使能WKUP这个引脚,也就是待机唤醒的引脚.
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry);//进入停止模式的函数
void PWR_EnterSTANDBYMode(void);//进入待机模式的函数.
先看一下这个进入待机模式的函数
下面是进入待机模式的三步走:
从下到上.
可以看到这个函数
/**
* @brief Enters STANDBY mode.
* @param None
* @retval None
*/
void PWR_EnterSTANDBYMode(void)
{
/* Clear Wake-up flag */
PWR->CR |= PWR_CR_CWUF; //1.先设置WUF
/* Select STANDBY mode */
PWR->CR |= PWR_CR_PDDS;//2.再设置PDDS
/* Set SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR |= SCB_SCR_SLEEPDEEP;//3.再设置SLEEPDEEP
/* This option is used to ensure that store operations are completed */
#if defined ( __CC_ARM )
__force_stores();
#endif
/* Request Wait For Interrupt */
__WFI();
}
然后再看看那个进入这个停止模式
可以看到,这里进入停机模式,实际上是多了一个
LPDS
/**
* @brief Enters STOP mode.
* @param PWR_Regulator: specifies the regulator state in STOP mode.
* This parameter can be one of the following values:
* @arg PWR_Regulator_ON: STOP mode with regulator ON
* @arg PWR_Regulator_LowPower: STOP mode with regulator in low power mode
* @param PWR_STOPEntry: specifies if STOP mode in entered with WFI or WFE instruction.
* This parameter can be one of the following values:
* @arg PWR_STOPEntry_WFI: enter STOP mode with WFI instruction
* @arg PWR_STOPEntry_WFE: enter STOP mode with WFE instruction
* @retval None
*/
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_PWR_REGULATOR(PWR_Regulator));
assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));
/* Select the regulator state in STOP mode ---------------------------------*/
tmpreg = PWR->CR;
/* Clear PDDS and LPDS bits */ //1.可以看到进入停止模式,这里多了一个LPDS的设置.
tmpreg &= CR_DS_MASK;
/* Set LPDS bit according to PWR_Regulator value */
tmpreg |= PWR_Regulator;
/* Store the new value */
PWR->CR = tmpreg;
/* Set SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR |= SCB_SCR_SLEEPDEEP;
/* Select STOP mode entry --------------------------------------------------*/
if(PWR_STOPEntry == PWR_STOPEntry_WFI)
{
/* Request Wait For Interrupt */
__WFI();
}
else
{
/* Request Wait For Event */
__WFE();
}
/* Reset SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
}
然后再看看待机唤醒的步骤
然后再看看待机唤醒实验
这里我们把LCD的实验拿出来,来写一个手把手的,待机唤醒的实验
这里首先把STM32F10X_PWR.C这个文件添加进来.
然后把mian.c中的循环都删除掉,只留下对应的初始化函数.
这里我们要做的实验是这样,我们要,按下KEY0然后,进入待机模式,然后
按下WKUP按键,使能EWUP位,以后等待上升沿到来,唤醒系统.
可以看到首先,要去
初始化KEY_INIT()
然后写个循环,然后在循环中可以扫描KEY0按下的话就
去做对应的进入睡眠的动作:
按照下面的这三个步骤来做.
然后这类使能电源时钟,代码再rcc中.
用下面这个函数来使能电源时钟.
可以看看这个代码:
很简单:
可以看到首先,使能电源时钟,
然后执行PWR_WakeUpPinCmd()使能WKUP引脚,等待上升沿唤醒
然后进入待机模式
PWR_EnterSTANDBYMode()
然后,接下来为了测试,咱们把LCD显示的一部分字,加进来,系统启动的时候
先去显示一些文字.
然后再去下载到开发版,看效果.
代码下载之前:
代码下载以后:
可以看到显示了咱们LCD要显示的文字.
然后按下KEY0可以看到,系统进入待机模式了
然后,再按下WKUP按键以后,可以看到系统就变亮了0,唤醒了.
然后咱们再来看一下,待机唤醒的实验.
首先看一下,系统启动以后首先执行
WKUP_INIT()这个函数.
先去初始化
初始化的话,这里可以看到,先去使能GPIOA口的时钟,还有AFIO时钟,因为用到了
优先级中断,所以这里要使能AFIO这个时钟.
然后设置了PA0引脚的模式,这里上拉输入什么的
然后设置对应的中断.
然后设置中断优先级.
然后还有一个调用这里的Check_WKUP()这个函数,调用这个函数的时候会
这个函数会去检测是不是到了3秒了,按下3秒以上了返回1,否则返回0
int main(void)
{
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
LED_Init(); //LED端口初始化
WKUP_Init(); //待机唤醒初始化
LCD_Init(); //LCD初始化
POINT_COLOR=RED;
LCD_ShowString(30,50,200,16,16,"Elite STM32");
LCD_ShowString(30,70,200,16,16,"WKUP TEST");
LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,110,200,16,16,"2015/1/14");
while(1)
{
LED0=!LED0;
delay_ms(250);
}
}
//PA0 WKUP唤醒初始化
void WKUP_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);//使能GPIOA和复用功能时钟
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0; //PA.0
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPD;//上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO
//使用外部中断方式
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); //中断线0连接GPIOA.0
EXTI_InitStructure.EXTI_Line = EXTI_Line0; //设置按键所有的外部线路
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //设外外部中断模式:EXTI线路为中断请求
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); // 初始化外部中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级2级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //从优先级2级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
if(Check_WKUP()==0) Sys_Standby(); //不是开机,进入待机模式
}
//检测WKUP脚的信号
//返回值1:连续按下3s以上
// 0:错误的触发
u8 Check_WKUP(void)
{
u8 t=0; //记录按下的时间
LED0=0; //亮灯DS0
while(1)
{
if(WKUP_KD)
{
t++; //已经按下了
delay_ms(30);
if(t>=100) //按下超过3秒钟
{
LED0=0; //点亮DS0
return 1; //按下3s以上了
}
}else
{
LED0=1;
return 0; //按下不足3秒
}
}
}
//中断,检测到PA0脚的一个上升沿.
//中断线0线上的中断检测
可以看到这里30毫秒就去检测一次,检测到100次的时候,也就是超过3秒了就返回1.
然后下面是进入待机模式的,和前面咱们写的代码是一样的
这个时候,画面启动的时候是这样,也就说,
系统启动的时候,会检测有没有按下wkup按键,按下了多久,显然刚启动的时候,咱们没有按下
wkup按键,这个时候,check_wkup就会返回0,返回0的时候,那么系统就会自动进入
待机模式.黑屏的,然后当咱们按下wkup按键的时候,系统会再去从main函数开始执行,这个时候
再去执行check_up函数的时候,这个时候检测到wkup按键被按下了3秒,那么就返回1,也就是不会
进入待机模式,不会进入待机模式,那么就会接着执行下面的函数,也就是LCD显示的内容,那么系统就亮了.
注意这里的屏幕亮了是因为程序从新从main函数开始执行导致的.
可以看到这个WKUP_INIT()这个函数,下面还是有LCD显示的函数的,只要是返回了1,那么,系统没有进入待机模式,那么
代码就会往下执行.就会执行LCD显示文字的代码.LCD屏幕就亮了.
下载到开发版看看效果,可以看到
首先下载到开发版以后,屏幕是暗的:
连续按下3秒以后可以看到,程序会亮了
然后这个时候如果我们再按下3秒,就会又进入待机模式了
这个是怎没做的呢?
因为咱们前面设置了中断.
PA0的中断,那么在系统的LCD屏亮着的情况下,也就是没有进入待机模式的情况下,
中断是起作用的,而在待机模式下,中断是不起作用的,那么在正常运行的情况,下如果我们按下了,3秒,那么
会检测到上升沿,就会触发PA0的中断,那么就会进入中断函数,可以看到中断函数中判断了如果按下的时间超过3秒
返回1,也就是,系统会又进入待机模式了.
那么再按下wkup按键的,时候因为待机模式下,代码会从main函数从头开始执行,这里代码执行到
WKUP_INIT()的时候,如果没有按下超过3秒,就自动进入待机模式,如果超过3秒了,屏幕又会亮了,
这样就显示了按3秒,关机,再按3秒启动的效果.