关于Stm32的低功耗模式的具体内容及相关代码

最新更新时间:2022-04-23来源: eefocus关键字:stm32  低功耗模式  唤醒 手机看文章 扫描二维码
随时随地手机看文章

Stm32的低功耗模式

3种低功耗模式:

**1.睡眠模式:**内核停止,外设如NVIC,系统时钟Systick仍运行。

**2.停止模式:**所有时钟都已停止。1.8V内核电源工作。

PLL,HIS和HSE RC振荡器功能禁止。

寄存器和SRAM内容保留。

3.待机模式:1.8V内核电源关闭。

只有备份寄存器和待机电路维持供电。

寄存器和SRAM内容全部丢失。实现最低功耗。

在运行模式下,可以通过下面方式降低功耗:

① 降低系统时钟。

② 关闭APB和AHB总线上未被使用的外设时钟。


低功耗模式的进入与唤醒:

在这里插入图片描述

注意:每种模式的唤醒中断有所差别,待机模式理想状态下,只需要2uA电流。停机模式下典型电流为20uA。


待机模式:

在这里插入图片描述

待机模式初始化代码:


//初始化待机模式

void Standy_Init(void)

{

  SCB->SCR|=1<<2;//使能SLEEPDEEP位 (SYS->CTRL)

  RCC->APB1ENR|=1<<28;     //使能电源接口时钟

  PWR->CR|=1<<1;       //CPU进入待机模式使能

  PWR->CR|=1<<2;      //清除WKUP唤醒标志位,防止在使能时产生唤醒事件

  PWR->CSR|=1<<8;     //设置PA0唤醒

  WFI_SET(); //执行WFI指令


其中WFI_SET()代码:

//THUMB指令不支持汇编内联 //采用如下方法实现执行汇编指令WFI void WFI_SET(void) { __ASM volatile("wfi"); }


上面的SCB->SCR寄存器stm32中文参考手册没有,在编程手册上有提到:

在这里插入图片描述

这个是系统寄存器中的一个不需要了解太多,设置SLEEPDEEP位就行。其他寄存器在中文参考手册中有详细解释。

注意:初始化待机模式时也要开启电源端口时钟 RCC->APB1ENR|=1<<28; //使能电源接口时钟


下面为待机唤醒实现的代码:


#include "wkup.h"

#include "delay.h"

#include "led.h"


//初始化待机模式

void Standy_Init(void)

{

  RCC->APB2RSTR|=0X01FC;//复位所有IO口

  SCB->SCR|=1<<2;//使能SLEEPDEEP位 (SYS->CTRL)

  RCC->APB1ENR|=1<<28;     //使能电源接口时钟

  PWR->CR|=1<<1;       //CPU进入待机模式使能

  PWR->CR|=1<<2;      //清除WKUP唤醒标志位,防止在使能时产生唤醒事件

  PWR->CSR|=1<<8;     //设置PA0唤醒

  WFI_SET(); //执行WFI指令

}


void WKUP_Init(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

  RCC->APB2ENR|=1<<2;       //使能时钟

  GPIOA->CRL&=0xfffffff0;     //清除配置位

  GPIOA->CRL|=0x00000008;   //下拉输入

  GPIOA->IDR&=0xfffffffe;   //设置为下拉

  

  RCC->APB2ENR|=1<<0;      //打开复用功能时钟

  AFIO->EXTICR[0]&=0xfffffff0;     //清零配置,并配置中断线连接到PA0

  EXTI->RTSR|=0x01;        //上升沿中断

  EXTI->IMR|=0x01;         //开启中断线

  

  //开启中断

  NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;

  NVIC_Init(&NVIC_InitStructure);  

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  

  if(Check_Key()==0)Standy_Init();    //进入待机模式

}


u8 Check_Key(void)

{

  u8 t;

LED0=0; //亮灯DS0 

  while(1)

{

if(WK_UP)

{

  t++;

  delay_ms(30);

  if(t>=100)

LED0=0;

             return 1;

}

}

else{

   LED0=1;

return 0;

}

}

}


void EXTI0_IRQHandler()

{

   EXTI->PR=1<<0;  //清除LINE10上的中断标志位   

if(Check_Key())//关机?

{   

Standy_Init();  

}

}


#include "delay.h"

#include "led.h"

#include "key.h"

#include "usart.h"

#include "wkup.h"

#include "sys.h"

#include "lcd.h"


int main()

{

  LED_Init();

  KEY_Init();

  delay_init();

  uart_init(115200); //串口初始化为115200

   WKUP_Init();

  LCD_Init();

  POINT_COLOR=RED;

  LCD_ShowString(30,70,200,16,16,"WKUP TEST");

  while(1)

{

  LED0=!LED0;

  delay_ms(500);

}

  

}


功能:初始化时进入待机模式,LCD屏幕关闭,当PA0口的WK_UP按键按下3秒时屏幕唤醒。

实现过程:开始进入待机模式,其中Check_Key()==0的判断是为下次唤醒时不初始化进入待机模式准备的,因为待机唤醒后CPU重头执行程序。按下WK_UP 3秒后屏幕跳出按键的while(1)的循环继续执行任务,其实WK_UP 一按下去检测到上升沿信号立马就唤醒了,只是按键while(1)延时3秒后才执行下面的初始化以及后面的任务。再一次按下Wk_UP按键进入外部中断,在按键的Check_Key()函数延时下3秒后才进入待机模式。唤醒时之所以没有进入外部中断是因为CPU没有启动


低功耗----停止模式

在这里插入图片描述

测试代码:


停止模式初始化

void Stop_Mode()

{

SCB->SCR|=1<<2;//使能SLEEPDEEP位 (SYS->CTRL)

PWR->CR|=0<<1;       //清除待机模式使能位

PWR->CR|=1<<0;       //使能停机模式

WFI_SET(); //执行WFI指令

}


打开PA0中断作为唤醒停止模式

void WKUP_Init(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

  RCC->APB2ENR|=1<<2;       //使能时钟

  GPIOA->CRL&=0xfffffff0;     //清除配置位

  GPIOA->CRL|=0x00000008;   //下拉输入

  GPIOA->IDR&=0xfffffffe;   //设置为下拉

  

  RCC->APB2ENR|=1<<0;      //打开复用功能时钟

  AFIO->EXTICR[0]&=0xfffffff0;     //清零配置,并配置中断线连接到PA0

  EXTI->RTSR|=0x01;        //上升沿中断

  EXTI->IMR|=0x01;         //开启中断线

  

  //开启中断

  NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;

  NVIC_Init(&NVIC_InitStructure);  

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  

// if(Check_Key()==0)Stop_Mode();    //进入待机模式

}


在中断中加入Systemlnit()是初始化系统时钟为72MHz启用外部时钟,停止模式所有的时钟都停止,且CPU1.8v区全部不工作,所以停止退出后使用的是内部RC时钟。


   void EXTI0_IRQHandler()

    {

         SystemInit();

        EXTI->PR=1<<0;  //清除LINE10上的中断标志位

       

    }


我用的是PA0外部中断唤醒停止模式,通过按键进入停止模式;下面的 t 变量是测试停止模式中SRAM不断电而写的

int main()

{

  u16 p;

  LED_Init();

  KEY_Init();

  delay_init();

  uart_init(115200); //串口初始化为115200

   WKUP_Init();

  LCD_Init();

  POINT_COLOR=RED;

  LCD_ShowString(30,70,200,16,16,"STOP TEST:");

  while(1)

{

  LED0=!LED0;

  delay_ms(500);

  p++;

  LCD_ShowNum(110,70,p,3,16);

  if(KEY1==0)

{

   //EXTI->PR=0XFFFFF;

delay_ms(10);

if(KEY1==0)

{

    Stop_Mode();

          LED1=0;}

}

}

  

}


对比待机模式,停止模式应该注意的细节:

停止模式的SRAM以及寄存器的值在进入停止模式时保持不变,也就是说在退出停止模式后程序在之前执行到哪一步的接着往下执行,这是因为CPU的程序指针保留为进入停止模式时的值,恢复后继续下一步;而待机模式由于寄存器断电不工作,所以程序指针在退出时从头开始执行程序。


睡眠模式:

在这里插入图片描述

初始化代码:


//THUMB指令不支持汇编内联

//采用如下方法实现执行汇编指令WFI  

void WFI_SET(void)

    __ASM volatile("wfi");   

}


只需要这一句命令就可以初始化为睡眠模式。

注意:睡眠模式只有CPU停止了工作,只是不运行程序,停止了而已。

关键字:stm32  低功耗模式  唤醒 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic564814.html

上一篇:Stm32的Flash模拟EEPROM与BOOT基本了解
下一篇:Stm32的ADC功能介绍及相关代码

推荐阅读

STM32笔记——GPIO
GPIO简介GPIO是通用输出输入端口的简称,简单来说就是STM32可控制的引脚,STM32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集功能。GPIO的基本结构1、保护二极管与上下拉电阻当外部输入电压高于VDD的电压时,上方的保护二极管导通,当外部输入电压底于Vss的电压时,上方的保护二极管导通,防止不正常电压引入芯片导致芯片烧毁。2、P-MOS管和N-MOS管在输出模式部分,线路经过一个由"P-MOS"和"N-MOS"组成的结构,这个结构使其拥有"推挽输出"和"开漏输出"的功能。3、TTL肖特基触发器4、IO耐压STM32
发表于 2022-07-01
<font color='red'>STM32</font>笔记——GPIO
STM32笔记——外部中断的配置
一、选择对应芯片常规操作,这里我们选择F407ZGT6二、配置sys选择Serial Wire三、配置RCC选择高速外部时钟晶振,系统自动配置相应引脚。四、配置外部中断引脚通过查看开发板原理图,找出按键对应引脚五、设置外部中断引脚1、上升沿触发(外部中断触发引脚上的电平从低电平跳转到高电平)2、下降沿触发(外部中断触发引脚上的电平从高电平跳转到低电平)3、上下边沿均触发 (外部中断触发引脚上有电平变化)六、开启外部中断七、配置中断优先级八、配置时钟九、生成工程HAL库GPIO函数库讲解1、外部中断服务函数void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin);功能:用于清除中断标志位实例:H
发表于 2022-07-01
<font color='red'>STM32</font>笔记——外部中断的配置
STM32笔记——外部中断
基本概念一、中断和异常1、中断——当需要出现时,CPU暂时停止当前程序的执行,转而执行处理新情况的程序和执行过程。2、异常——处理器要复位,不可屏蔽中断,存储故障,这些由内核产生的就叫做异常,也就是硬件异常。二、EXIT和NVICEXIT外部中断/事件控制器 外部中断/事件控制器包含多达 23 个用于产生事件/中断请求的边沿检测器。每根输入线都可单独进行配置,以选择类型(中断或事件)和相应的触发事件(上升沿触发、下降沿触发或边沿触发)。每根输入线还可单独屏蔽。挂起寄存器用于保持中断请求的状态线。外部中断框图:触发机制上升沿:数字电路中,数字电平从低电平(数字“0”)变为高电平(数字“1”)的那一瞬间(时刻)叫作上升沿。下降沿:
发表于 2022-07-01
<font color='red'>STM32</font>笔记——外部中断
STM32学习第一课:STM32 编程的C语言基础
刚开始看STM32的库函数,会有很多疑惑,例如指针怎么用,结构体跟指针怎么配合,例如函数的参数有什么要求,如何实时更新IO口的数据等。如果重新进行C语言的学习,那么要学很久才能够系统地认识。这里将比较容易想不起来的知识点进行简单的整理。1、#ifdef 和 #ifndef#ifdef 标识符A// 如果标识符A定义了,就编译程序段1,否则编译程序段2程序段1#else程序段2#endif#ifndef 的功能则与 #ifdef相反,是没有定义标识符A的时候编译程序段1。2、全局define在软件的选项中,有如此一栏,在上面填写的变量则表示在所有的文件中,上述的标识均被定义过。#ifdef STM32F10X_HD大容量芯片需要的一些
发表于 2022-07-01
STM32学习第二课:STM32c语言基础2
1.Typedeftypedef用于为现有类型创建一个新的名字,或称为类型别名,用来简化变量的定义。typedef在MDK用得最多的就是定义结构体的类型别名和枚举类型了。如:typedef struct{ u16 seq_num; u16 len; u8 dev_id[GPRS_PRO_DEVICE_ID]; u16 command_id; u8 *pro_data;}gprs_pro_cmd_t;然后我们就可以直接使用gprs_pro_cmd_t定义一个结构体变量。2.结构体① 一般形式:Struct 结构体名 { 成员列表; }变量名列表;② 这样是声明后直接定义,也可以先声明,后定义;如:Struct 结构体名字 { 成员列表
发表于 2022-07-01
STM32学习第三课:STM32 c语言学习基础3(内存操作、指针、结构指针)
1.内存操作在对内存操作头疼的时候我发现了这篇神奇的文章,拜读之后豁然开朗心生崇拜数据指针在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力。在嵌入式系统的实际调试中,多借助C语言指针所具有的对绝对地址单元内容的读写能力。以指针直接操作内存多发生在如下几种情况:(1) 某I/O芯片被定位在CPU的存储空间而非I/O空间,而且寄存器对应于某特定地址;(2) 两个CPU之间以双端口RAM通信,CPU需要在双端口RAM的特定单元(称为mail box)书写内容以在对方CPU产生中断;(3) 读取在ROM或FLASH的特定单元所烧录的汉字和英文字模。
发表于 2022-07-01
<font color='red'>STM32</font>学习第三课:<font color='red'>STM32</font> c语言学习基础3(内存操作、指针、结构指针)

推荐帖子

CAN总线的问题
这几天一直都在忙,而且忙到很烦, 产品出了点问题,在家里怎么都不能再现,很多天过去了, 今天发现了一点,可能正是问题所在, 我用同一个CAN接口,不同的两个buffer发送了两组数据, 甚至调用的发送子函数都是一样的,出人意料,今天竟然出现只发出了其中一组数据的情况 接收数据,是用第三方的工具,应该是正确的结果, 求大虾指点,为什么 有经验的速来,谢谢:(CAN总线的问题
HOHO 单片机
新塘M030G开发板的ISP_UART升级操作说明
新唐的MCU都提供的ISP功能,且提供提供了相关的工具和程序,很多时候因为资料比较杂,且项目紧急,没办法慢慢的来研究其ISP升级机制,刚好笔者手上有个M030G的评估版,用来指导说明ISP通过串口升级的操作方法;可方便用户快速熟悉并使用; 新塘M030G开发板的ISP_UART升级操作说明
火辣西米秀 国产芯片交流
能否用open打开打开usb节点?
本信息来自合作QQ群:armlinuxfpga嵌入0群49900581(超级群)群主在坛子里ID:wangkj 我问一下各位大虾, 我把U盘插入linux系统的电脑时有一个设备U盘节点/dev/sdb1 当我用open函数打开时打不开 open("/dev/sdb1",O_RDWR); 返回一个小于零的数 难道不能用open打开打开usb节点?能否用open打开打开usb节点?
ic_李余荣 嵌入式系统
函数信号发生器的问题
要做一个函数信号发生器用凌阳061a和max038max038的fadj口调节频率-2.4v到2.4v可调用061的dac口输出的是0-3mA电流怎样转换成2.4v到2.4v可调电压谢谢啦并诚交电路设计能人异士为好友如果可能诚心拜师非诚勿扰联系邮箱lian.sun.hai@163.com函数信号发生器的问题
younha 嵌入式系统
电子测量仪器原理与使用
内容简介:本书系统地阐述了各种电子测量仪器的工作原理与使用。内容包括:基础知识、测量用信号发生器、电子电压表、电子示波器、电子计数器、元件参数测试仪、晶体管特性图示仪、数字集成电路测试仪、频谱分析仪、频率特性测试仪(扫频仪)、网络分析仪、逻辑分析仪、虚拟仪器等.电子测量仪器原理与使用
心仪 测试/测量
【phyBOARD-i.MX 8M Plus 开发板】三:Demo例程编译下载及运行
phyBOARD-i.MX8MPlus开发板的编译环境在虚拟机中已经搭建好了,然后由于是Linux的系统,Demo例程需要交叉编译后下载至开发板后才能执行。 1、虚拟机环境设置 由于是德国版本的乌班图,需要设置语音和键盘,否则会出现上次评测中无法输入/的情况 点击右侧上方的下三角,出现界面后,点击配置按钮 在配置界面中选择语音,需要把字体和键盘都改成us 如下图,中间可能需要重启 语音和键盘更改后,就可以正常使用了,不过,没有中文支持。 2
kit7828 开发板测评专版
小广播
实战 培训 开发板 精华推荐

何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved