历史上的今天
今天是:2024年10月17日(星期四)
2018年10月17日 | 50.待机唤醒实验
2018-10-17 来源:eefocus
一。STM32低功耗模式讲解

有些设备比如可穿戴设备对功耗的要求非常高,比如手表,我在看时间或者获取数据的时候就需要正常的执行,
但有的时候比如晚上或有时候不需要使用它,但我们并不需要关机,可以通过低功耗模式让它更加省电,就延长了它的使用时间。

1. 睡眠模式: 内核停止,但是它的外设比如中断管理NVIC,系统的时钟Systick仍在运行。
2. 停止模式:比睡眠模式更加低功耗,所有的时钟都停止,但是1.8V的内核电源还在工作,但是其他的时钟比如 PLL,HIS和HSE RC振荡器功能全部禁止了。
寄存器和SRAM的内容保留。
3. 待机模式:功耗更低,内核1.8V的电源关闭,只有备份寄存器和待机电路维持供电。
寄存器和SRAM内容全部丢失,实现最低功耗。
运行模式,有些场景我们还是需要系统能正常运行,我们要降低功耗的话可以采取以下方式:
1. 降低系统时钟
2. 关闭APB和AHB总线上未被使用的外设的时钟。
STM32的三种低功耗模式
要进入这三种低功耗模式或者从三种低功耗模式退出的方法:

1. 睡眠模式:进入的方法:(1)执行WFI指令或WFE指令,只需要调用一个函数就OK了。
唤醒的方法: 对于WFI进入:任一个中断
对于WFE进入:唤醒事件
2. 停机模式: 进入的方法:PDDS和LPDS位 + SLEEPDEEP位都需要设置,然后再用WFI或WFE指令。
唤醒的方法:任何一种外部中断都可以(在外部中断寄存器中设置)
3. 待机模式: 进入的方法: PDDS位+SLEEPDEEP位设置,清除WUF位,然后再用WFI或WFE指令进入
唤醒的方法:通过WKUP引脚的上升沿(PA0引脚),或者RTC闹钟事件,或者NRST引脚上的外 部复位,独立看门狗IWDG复位。常用的是闹钟事件或者外部WKUP引脚。
实验程序用WKUP引脚(PA0)唤醒。
实验采用待机模式:

待机模式下大部分引脚都处于高阻状态。
在待机模式下F1只需要2uA的电流,非常低。
二。寄存器和库函数配置
1. PWR_CR电源控制寄存器

位1: PDDS,在进入待机模式要置1
SLEEPDEEP在系统控制寄存器SCB中置1。
清除PWR_CSR寄存器中的WUF位。
2. PWR_CSR 电源控制/状态寄存器

退出待机模式有几种方法,如果要用WKUP引脚唤醒怎么配置?
PWR_CSR寄存器位8,EWUP使能WKUP引脚。
固件库中低功耗操作函数

调用 void PWR_EnterSTANDBYMode(void); //进入待机模式
这个函数中执行了四个操作:1. PDDS位置1
2. SLEEPDEEP位置1
3. 清除WUF位
4. 执行WFI()指令,当然也可以执行WFE()指令
待机唤醒的配置步骤
三。实验程序讲解
实验程序比较复杂,主要是为了在同一个WKUP引脚(PA0)长按3秒进入待机模式,在待机模式下,长按3秒待机唤醒。
程序的设计思路提醒:

1. 先写一个待机唤醒测试
按下某一个按键进入待机模式
(1)在FWLlib下面要添加PWR相关的固件库 .c 和 .h文件
(2)程序设计:程序复位后液晶屏被点亮,显示一些内容,然后按下KEY0之后进入待机模式,在待机模式下按下WKUP键退出待机模式,程序又相当于复位从头开始执行,液晶屏又重新显示内容。
int main(void)
{
u8 x=0;
u8 lcd_id[12]; //存放LCD ID字符串
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
LED_Init(); //LED端口初始化
LCD_Init();
KEY_Init();
POINT_COLOR=RED;
LCD_ShowString(30,40,210,24,24,"WarShip STM32 ^_^"); //液晶屏显示一些内容
LCD_ShowString(30,70,200,16,16,"TFTLCD TEST");
LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
while(1)
{
if(KEY_Scan(0) == KEY0_PRES)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE); //使能PWR时钟,在APB1总线上
PWR_WakeUpPinCmd(ENABLE); //使能WKUP唤醒引脚,使得在待机模式下按WKUP键能够退出待机模式
PWR_EnterSTANDBYMode(); //进入待机模式
}
delay_ms(10);
}
}
实验现象:程序开始运行,液晶屏显示三行文字,按下KEY0键时进入待机模式,液晶屏关闭,按下WKUP键,液晶屏重新显示内容。
2. 实验程序
在同一个WKUP引脚(PA0)长按3秒进入待机模式,在待机模式下,长按3秒待机唤醒。
wkup.c 文件
//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和复用功能时钟,因为后面要把PA0引脚配置成外部中断,所以要开启复用功能。
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引脚3秒,进入待机模式 ,只有开机 时连续按下WKUP键3秒程序才能正常执行。
}
//检测WKUP脚的信号
//返回值1:连续按下3s以上
// 0:错误的触发
u8 Check_WKUP(void) //检测WKUP引脚的电平,3秒钟内连续按下返回1,
{
u8 t=0; //记录按下的时间
LED0=0; //亮灯DS0
while(1)
{
if(WKUP_KD)
{
t++; //已经按下了
delay_ms(30);
if(t>=100) //按下超过3秒钟,每30毫秒 t+1, t计数到100,说明到3秒钟
{
LED0=0; //点亮DS0
return 1; //按下3s以上了,返回1
}
}else
{
LED0=1;
return 0; //按下不足3秒,返回0
}
}
}
void Sys_Standby(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //使能PWR外设时钟
PWR_WakeUpPinCmd(ENABLE); //使能唤醒管脚功能
PWR_EnterSTANDBYMode(); //进入待命(STANDBY)模式 ,进入待机模式
}
main.c文件
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,"Warship 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,"2014/1/14");
while(1)
{
LED0=!LED0;
delay_ms(250);
}
}
//外部中断,检测到PA0脚的一个上升沿.
//中断线0线上的中断检测
void EXTI0_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line0); // 清除LINE10上的中断标志位
if(Check_WKUP())//检测WKUP键是不是连续按下3秒钟,连续按下3秒进入待机模式
{
Sys_Enter_Standby(); //如果是连续按下3秒,就进入待机唤醒模式
}
}
//系统进入待机模式
void Sys_Enter_Standby(void)
{
RCC_APB2PeriphResetCmd(0X01FC,DISABLE); //复位所有IO口
Sys_Standby();
}
程序正常运行时显示几行文字,LED0交叉闪烁。
在WKUP_Init函数中如果没有连续按下3秒就进入待机模式
如果连续按下了WKUP键3秒,则正常执行,而在正常执行的情况下因为我们把WKUP设置了外部中断,进入外部中断函数
实验现象:
程序开始执行,判断WKUP是不是按下了,如果没有长按3秒就进入待机模式。
因为一开始没有按WKUP,所以进入待机模式,液晶屏不亮。
然后连续按WKUP3秒后就唤醒了,液晶屏显示几行文字,LED0也开始闪烁。
因为,一按WKUP的瞬间就被唤醒,同样开始执行主函数,执行到
if(Check_WKUP()==0) Sys_Standby(); //不是开机,进入待机模式
因为我们长按了3秒所以这个检测就不通过,就不会进入待机模式,程序就直接往下执行,液晶屏显示,LED0闪烁。
接下来再去长按WKUP3秒,又进入待机模式。因为程序正常运行情况下,我们把WKUP设置成了外部中断,所以一按PA0就会进入外部中断服务函数,在中断服务函数中去判断按下WKUP是不是超过3秒,超过3秒就进入到待机模式,如果按下的时间不到3秒钟,不会进入待机模式,液晶屏还是正常显示。
上一篇:51.内部温度传感器实验
下一篇:49. RTC实验讲解
史海拾趣
|
仅用鼠标就搞定的第一个C++程序 学习C++,不同IDE的控制台程序,新建、点击后产生的第一个C++程序,有的仅用鼠标就能搞定,“正常显示”,而有的则需要补充些语句才能通过编译到“正常显示”状态。 这里没有别的意思,只是想说 ...… 查看全部问答> |
|
国家统计局的数据则表明,未来五年,电磁炉在国内将有7000万至8000万台的市场潜力,市场容量将达到数百亿元。但是,当电磁炉大批走进千家万户之时,其电磁污染的病症也日益显现。 那么什么是磁泄漏呢?中国室内装饰协会室内环境监测委员会副主任赵 ...… 查看全部问答> |
|
#define DEFC(name, address) __no_init volatile unsigned char name @ address; 各位大虾 我在430的库文件里面看到这么一句 #define DEFC(name, address) __no_init volatile unsigned char name @ address; 是什么啊… 查看全部问答> |
|
今天和大家分享一个有关ESD电路保护设计的视频。 随着技术的发展,移动电子设备已成为我们生活和文化的重要组成部分。平板电脑和只能手机触摸技术的应用,让我们能够与这些设备进行更多的互动。同时,它也构成了一个完整的静电放电(ESD)危险环境 ...… 查看全部问答> |
|
本帖最后由 huayuliang 于 2014-11-8 18:38 编辑 算是正式开始了吧,不过俺只能想到(用到)哪里写到哪里,结果就如之前描述的——很乱。。。 其实所谓的技巧,只是基本命令的使用,不过是和实际应用相关的一些可能你没有想过的用法而已···· ...… 查看全部问答> |




