预研目标

六轴静止时,终端进入低功耗模式;六轴震动时,终端正常工作模式,从而极大减少非工作时的电流消耗。

解决方案

机器静止时,依据六轴算法,CPU进入休眠(停止)模式;机器工作时,触发六轴中断唤醒CPU,再配合系统空闲时进入CPU睡眠模式,从而极大降低机器非工作时的电流消耗和降低工作时底电流消耗。

关键技术

STM32功耗模式

按功耗由高到低排列,STM32具有运行、睡眠、停止和待机四种工作模式。上电复位后STM32处于运行状态时,当内核不需要继续运行,就可以选择进入后面的三种低功耗模式降低功耗,这三种模式中,电源消耗不同、唤醒时间不同、唤醒源不同,用户需要根据应用需求,选择最佳的低功耗模式。三种低功耗的模式说明见表1。

表 1  STM32的低功耗模式说明

模式

说明

进入方式

唤醒方式

对1.2V区域时钟的影响

对VDD区域时钟的影响

调压器

睡眠

内核停止,所有外设包括M4核心的外设,如NVIC、系统时钟(SysTick)等仍在运行

调用WFI命令

任一中断

内核时钟关,对其他时钟和ADC时钟无影响

调用WFE命令

唤醒事件

停止

所有的时钟都已停止

配置PWR_CR寄存器的PDDS +LPDS 位+SLEEPDEEP位

+WFI或WFE命令

任一外部中断( 在外部中断寄存器中设置)

关闭所有1.2V区域的时钟

HSI和HSE的振荡器关闭

开启或处于低功耗模式( 依据电源控制寄存器的设定)

待机

1.2V 电源关闭

配置PWR_CR寄存器的PDDS +SLEEPDEEP位

+WFI或WFE命令

WKUP 引脚的上升沿、RTC闹钟事件、NRST 引脚上的外部复位、IWDG 复位

从表中可以看到,这三种低功耗模式层层递进,运行的时钟或芯片功能越来越少,因而功耗越来越低。

睡眠模式

在睡眠模式中,仅关闭了内核时钟,内核停止运行,但其片上外设,CM4核心的外设全都还照常运行。有两种方式进入睡眠模式,它的进入方式决定了从睡眠唤醒的方式,分别是WFI(wait for interrupt)和WFE(wait for event),即由等待"中断"唤醒和由"事件"唤醒。睡眠模式的各种特性见表 2。

表 2  睡眠模式的各种特性

特性

说明

立即睡眠

在执行WFI 或WFE 指令时立即进入睡眠模式。

退出时睡眠

在退出优先级最低的中断服务程序后才进入睡眠模式。

进入方式

内核寄存器的SLEEPDEEP = 0 ,然后调用WFI或WFE指令即可进入睡眠模式;

另外若内核寄存器的SLEEPONEXIT=0时,进入"立即睡眠"模式,SLEEPONEXIT=1时,进入"退出时睡眠"模式。

唤醒方式

如果是使用WFI指令睡眠的,则可使用任意中断唤醒;

如果是使用WFE指令睡眠的,则由事件唤醒。

睡眠时

关闭内核时钟,内核停止,而外设正常运行,在软件上表现为不再执行新的代码。这个状态会保留睡眠前的内核寄存器、内存的数据。

唤醒延迟

无延迟。

唤醒后

若由中断唤醒,先进入中断,退出中断服务程序后,接着执行WFI指令后的程序;若由事件唤醒,直接接着执行WFE后的程序。

停止模式

在停止模式中,进一步关闭了其它所有的时钟,于是所有的外设都停止了工作,但由于其1.2V区域的部分电源没有关闭,还保留了内核的寄存器、内存的信息,所以从停止模式唤醒,并重新开启时钟后,还可以从上次停止处继续执行代码。停止模式可以由任意一个外部中断(EXTI)唤醒。在停止模式中可以选择电压调节器为开模式或低功耗模式,可选择内部FLASH工作在正常模式或掉电模式。停止模式的各种特性见表3。

表 3 停止模式的各种特性

特性

说明

调压器低功耗模式

在停止模式下调压器可工作在正常模式或低功耗模式,可进一步降低功耗

FLASH掉电模式

在停止模式下FLASH可工作在正常模式或掉电模式,可进一步降低功耗

进入方式

内核寄存器的SLEEPDEEP =1,PWR_CR寄存器中的PDDS=0,然后调用WFI或WFE指令即可进入停止模式;

PWR_CR 寄存器的LPDS=0时,调压器工作在正常模式,LPDS=1时工作在低功耗模式;

PWR_CR 寄存器的FPDS=0时,FLASH工作在正常模式,FPDS=1时进入掉电模式。

唤醒方式

如果是使用WFI指令睡眠的,可使用任意EXTI线的中断唤醒;

如果是使用WFE指令睡眠的,可使用任意配置为事件模式的EXTI线事件唤醒。

停止时

内核停止,片上外设也停止。这个状态会保留停止前的内核寄存器、内存的数据。

唤醒延迟

基础延迟为HSI振荡器的启动时间,若调压器工作在低功耗模式,还需要加上调压器从低功耗切换至正常模式下的时间,若FLASH工作在掉电模式,还需要加上FLASH从掉电模式唤醒的时间。

唤醒后

若由中断唤醒,先进入中断,退出中断服务程序后,接着执行WFI指令后的程序;若由事件唤醒,直接接着执行WFE后的程序。唤醒后,STM32会使用HIS作为系统时钟。

待机模式

待机模式,它除了关闭所有的时钟,还把1.2V区域的电源也完全关闭了,也就是说,从待机模式唤醒后,由于没有之前代码的运行记录,只能对芯片复位,重新检测boot条件,从头开始执行程序。它有四种唤醒方式,分别是WKUP(PA0)引脚的上升沿,RTC闹钟事件,NRST引脚的复位和IWDG(独立看门狗)复位。

表 4 待机模式的各种特性

特性

说明

进入方式

内核寄存器的SLEEPDEEP =1,PWR_CR寄存器中的PDDS=1,PWR_CR寄存器中的唤醒状态位WUF=0,然后调用WFI或WFE指令即可进入待机模式;

唤醒方式

通过WKUP引脚的上升沿,RTC闹钟、唤醒、入侵、时间戳事件或NRST引脚外部复位及IWDG复位唤醒。

待机时

内核停止,片上外设也停止;内核寄存器、内存的数据会丢失;除复位引脚、RTC_AF1引脚及WKUP引脚,其它I/O口均工作在高阻态。

唤醒延迟

芯片复位的时间

唤醒后

相当于芯片复位,在程序表现为从头开始执行代码。

在以上讲解的睡眠模式、停止模式及待机模式中,若备份域电源正常供电,备份域内的RTC都可以正常运行、备份域内的寄存器及备份域内的SRAM数据会被保存,不受功耗模式影响。

功耗模式选择及配置

功耗模式选择

睡眠模式:RTOS空闲任务进入休眠,sysTick中断唤醒;

停止模式:机器不工作(六轴静止)时,进入停止模式;六轴动时中断/RTC定时中断触发唤醒。

功耗模式配置

注:STOP模式下,唤醒后系统使用HSI作为系统时钟,用户可能需要未进入STOP模式前的系统时钟配置。

RTC定时唤醒喂狗

系统进入STOP模式后,需要RTC中断定时唤醒喂狗防止系统复位。

RTC定时唤醒中断使能:

HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0xA017, RTC_WAKEUPCLOCK_RTCCLK_DIV16);

RTC定时唤醒中断失能:

HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);

RTC定时唤醒喂狗:

void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)

{

feed_dog();

}

六轴BMI160

电源模式

在我们的产品场景中,Gyroscope(陀螺仪)未使用,默认配置为Suspend mode,Accelermoter(加速度)使用Normal mode(退出CPU休眠后)或Low power mode(进入休眠前配置);

中断模式

模式选择及配置

这里推荐使用BMI160官方驱动,源码获取参见参考资料第3项,关于驱动具体使用参照源码README.md文件,下面

struct bmi160_dev sensor;

BMI160初始化

structbmi160_dev sensor;/* BMI160初始化 */void AccelInit(void)
{/*You may assign a chip select identifier to be handled later*/sensor.id= 0;sensor.interface =BMI160_SPI_INTF;sensor.read=user_spi_read;sensor.write=user_spi_write;sensor.delay_ms=user_delay_ms;int8_t rslt=BMI160_OK;rslt= bmi160_init(&sensor);printf("bmi160 chip id: %02x, accel power:%d, gyro power:%d\r\n", sensor.chip_id, sensor.accel_cfg.power, sensor.gyro_cfg.power);/*After the above function call, accel_cfg and gyro_cfg parameters in the devicestructure are set with default values, found in the datasheet of the sensor*/}/* BMI160电源模式配置 */void AccelConfig(void)
{int8_t rslt=BMI160_OK;structbmi160_pmu_status pmuStatus;/*Select the Output data rate, range of accelerometer sensor*/sensor.accel_cfg.odr=BMI160_ACCEL_ODR_400HZ;sensor.accel_cfg.range=BMI160_ACCEL_RANGE_4G;sensor.accel_cfg.bw=BMI160_ACCEL_BW_NORMAL_AVG4;/*Select the power mode of accelerometer sensor*/sensor.accel_cfg.power=BMI160_ACCEL_NORMAL_MODE;/*Set the sensor configuration*/rslt= bmi160_set_sens_conf(&sensor);bmi160_get_power_mode(&pmuStatus, &sensor);//printf("accel power:%d, gyro power:%d\r\n", pmuStatus.accel_pmu_status, pmuStatus.gyro_pmu_status);}/* BMI160 Any-motion中断配置 */void AnyMotionIntCfg(void)
{structbmi160_int_settg int_config;/*Select the Interrupt channel/pin*/int_config.int_channel= BMI160_INT_CHANNEL_BOTH;//Interrupt channel/pin 1/*Select the Interrupt type*/int_config.int_type= BMI160_ACC_ANY_MOTION_INT;//Choosing Any motion interrupt/*Select the interrupt channel/pin settings*/int_config.int_pin_settg.output_en= BMI160_ENABLE;//Enabling interrupt pins to act as output pinint_config.int_pin_settg.output_mode= BMI160_DISABLE;//Choosing push-pull mode for interrupt pinint_config.int_pin_settg.output_type= BMI160_DISABLE;//Choosing active low outputint_config.int_pin_settg.edge_ctrl= BMI160_ENABLE;//Choosing edge triggered outputint_config.int_pin_settg.input_en= BMI160_DISABLE;//Disabling interrupt pin to act as inputint_config.int_pin_settg.latch_dur= BMI160_LATCH_DUR_NONE;//non-latched output/*Select the Any-motion interrupt parameters*/int_config.int_type_cfg.acc_any_motion_int.anymotion_en= BMI160_ENABLE;//1- Enable the any-motion, 0- disable any-motionint_config.int_type_cfg.acc_any_motion_int.anymotion_x= BMI160_ENABLE;//Enabling x-axis for any motion interruptint_config.int_type_cfg.acc_any_motion_int.anymotion_y= BMI160_ENABLE;//Enabling y-axis for any motion interruptint_config.int_type_cfg.acc_any_motion_int.anymotion_z= BMI160_ENABLE;//Enabling z-axis for any motion interruptint_config.int_type_cfg.acc_any_motion_int.anymotion_dur= 0;//any-motion durationint_config.int_type_cfg.acc_any_motion_int.anymotion_thr= 20;//(2-g range) -> (slope_thr) * 3.91 mg, (4-g range) -> (slope_thr) * 7.81 mg, (8-g range) ->(slope_thr) * 15.63 mg, (16-g range) -> (slope_thr) * 31.25 mg/*Set the Any-motion interrupt*/bmi160_set_int_config(&int_config, &sensor); /*sensor is an instance of the structure bmi160_dev*/}

方案验证

测试用例

typedef enum{  STOP_MODE_WAKE_FROM_NULL,  STOP_MODE_WAKE_FROM_RTC,  STOP_MODE_WAKE_FROM_ACCEL, }StopModeWakeEnum;
StopModeWakeEnum wakeReason=STOP_MODE_WAKE_FROM_NULL;void StopModeTest(void *pdata){ RCC_ClkInitTypeDef clkCfgPre; uint32_t flatencyPre= 0; uint32_t freqPre= 0; GPIO_InitTypeDef GPIO_InitStruct; AccelInit(); AccelConfig(); AnyMotionIntCfg();for(;;) { printf("\r\nSTM32 runing, system led off\r\n"); PrintSysClkInfo(); SysLedOff(); printf("\r\nSTM32 enter stop mode\r\n");/*## Configure the Wake up timer ###########################################*/ /*RTC Wake-up Interrupt Generation: Wake-up Time Base = (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSI)) Wake-up Time = Wake-up Time Base * WakeUpCounter = (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSI)) * WakeUpCounter ==> WakeUpCounter = Wake-up Time / Wake-up Time Base To configure the wake up timer to 20s the WakeUpCounter is set to 0xA017: RTC_WAKEUPCLOCK_RTCCLK_DIV = RTCCLK_Div16 = 16 Wake-up Time Base = 16 /(~32.768KHz) = ~0,488 ms Wake-up Time = ~20s = 0,488ms * WakeUpCounter ==> WakeUpCounter = ~20s/0,488ms = 40983 = 0xA017*/HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0xA017, RTC_WAKEUPCLOCK_RTCCLK_DIV16);/*FLASH Deep Power Down Mode enabled*/HAL_PWREx_EnableFlashPowerDown();/*Enter Stop Mode*/HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); HAL_PWREx_DisableFlashPowerDown(); HAL_RCC_GetClockConfig(&clkCfgPre, &flatencyPre); freqPre=HAL_RCC_GetSysClockFreq (); SYSCLKConfig_STOP();/*Disable Wake-up timer*/ if(HAL_RTCEx_DeactivateWakeUpTimer(&hrtc) !=HAL_OK) {/*Initialization Error*/Error_Handler(); }switch(wakeReason) {caseSTOP_MODE_WAKE_FROM_RTC: printf("\r\nSTM32 wake from stop mode from RTC, system led on\r\n");break;caseSTOP_MODE_WAKE_FROM_ACCEL: printf("\r\nSTM32 wake from stop mode from ACCEL, system led on\r\n");break;default: printf("\r\nSTM32 wake from stop mode from %d\r\n", wakeReason);break; } printf("SysFreq:%u, ClkSrc:%d(0:HSI, 1:HSE, 2:PLL, 3:PLLR)\r\n", freqPre, clkCfgPre.SYSCLKSource); printf("\r\nSTM32 recover system clk config\r\n"); PrintSysClkInfo(); OSTimeDlyHMSM(0, 0, 5, 0); } }void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc) { SysLedOn(); feed_dog(); wakeReason=STOP_MODE_WAKE_FROM_RTC; }voidHAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {  switch(GPIO_Pin) {     caseWAKED_FROM_BT_Pin:if(GPIO_PIN_SET ==HAL_GPIO_ReadPin(WAKED_FROM_BT_GPIO_Port, WAKED_FROM_BT_Pin)) {/*wake start*/BleSpiRxRestart(); }break;caseINT_ALARM_Pin:break;caseGYRO_INT1_Pin:if(GPIO_PIN_SET ==HAL_GPIO_ReadPin(GYRO_INT1_GPIO_Port, GYRO_INT1_Pin)) { }break;caseGYRO_INT2_Pin:if(GPIO_PIN_SET ==HAL_GPIO_ReadPin(GYRO_INT2_GPIO_Port, GYRO_INT2_Pin)) { SysLedOn(); wakeReason=STOP_MODE_WAKE_FROM_ACCEL; }break;default:        break; }}

实验步骤

  1. 测试用例烧录终端,连接打印串口、打开串口调试助手;
  2. 18:15:49前保持终端静止、待进入CPU休眠后再次震动终端1次,重复操作2次;

测试log输出:

实验结论

CPU进入停止模式后,RTC定时中断/六轴中断可唤醒CPU,唤醒后CPU使用HSI作为系统时钟源,CPU进入停止模式后功耗极大降低,可实现机器非工作时电流消耗的极大降低。

参考资料

1. 《STM32F401xB/C and STM32F401xD/E advanced Arm®-based 32-bit MCUs》

2.《Description of STM32F4 HAL and LL drivers》

3.https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMI160-DS000.pdf

4. https://github.com/BoschSensortec/BMI160_driver

作者:大毛孩 出处: https://www.cnblogs.com/damaohai/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果觉得还有帮助的话,可以点一下右下角的【推荐】。

转载于:https://www.cnblogs.com/damaohai/p/11411325.html

【原创】STM32低功耗模式及中断唤醒(基于BMI160及RTC)的研究相关推荐

  1. STM32低功耗模式测试

    stm32单片机低功耗模式共有3种,下来对3种低功耗进行分析测试. 先看手册上相关低功耗资料介绍: 先来分析睡眠模式: 进入睡眠模式比较简单,只需一条指令即可.唤醒睡眠模式,我们使用串口中断来唤醒,通 ...

  2. STM32低功耗模式与烟雾报警器触发信号电路设计

    STM32低功耗模式与烟雾报警器触发信号电路设计 https://www.cnblogs.com/kanite/p/5352642.html 1.STM32的3种低功耗模式 STM32有3种低功耗模式 ...

  3. STM32低功耗模式解读

    本文主要解读STM32低功耗模式的机制,并不侧重STM32低功耗的程序实现,而且借助STM32固件库实现STM32低功耗会变的非常简单. 一.STM32芯片性能 使用芯片型号:stm32f030f4, ...

  4. STM32低功耗模式下GPIO如何配置最节能?

    目录 1.将未使用的GPIO 配置为模拟输入模式 2.调节GPIO 速度 3.GPIO不使用时禁用寄存器时钟 4.避免悬空未使用的引脚 STM32低功耗模式下GPIO如何配置最节能,这里总结了一下四点 ...

  5. STM32停止模式进入中断以及中断唤醒遇到的问题及解决办法

    首先介绍一下使用环境:STM32CUBEIDE.STM32L051K8T6.Stop模式. 由于最近需要用到低功耗模式,所以也是第一次使用低功耗模式,把自己遇到的问题记录一下. 无法进入stop模式 ...

  6. 【STM32】【STM32CubeMX】STM32CubeMX的使用之八:低功耗模式及MCU唤醒

    文章目录 0.前言 1.低功耗模式简介 2.CubeMX设置 3.软件设计   下载工程文件:   https://gitee.com/Joseph_Cooper/stm32-cube-mx-stm3 ...

  7. STM32L051低功耗STOP模式串口中断唤醒

    STM32L051进入STOP模式后,除去通过RTC唤醒,还可通过外部中断唤醒,在stop without rtc模式下电流消耗能达到0.4uA.很多时候,我们需要使用STM32的串口进行唤醒,比如接 ...

  8. STM32低功耗模式

    STM32 的低功耗模式有 3种: 1)睡眠模式(CM3内核停止,外设仍然运行) 2)停止模式(所有时钟都停止) 3)待机(standby)模式(1.8V内核电源关闭) 从待机模式唤醒后的代码执行等同 ...

  9. STM32+ADXL计步器(中断唤醒+串口调试)

    本文介绍了利用ADXL345中断唤醒停止模式下的STM32F103C8T6,为进一步开发计步器做准备. 从上位机串口通讯记录了整个过程, 代码中有关OLED显示屏可以不接. 1. ADXL345寄存器 ...

  10. TI-RTOS实时操作系统开发之低功耗模式和外部唤醒

    写在前面 本文章适用基于TI-RTOS开发的芯片 以下说明是以CC2640R2F为例,低功耗模式分为两种:1.掉电模式(shutdown),2.睡眠模式(sleep或者standby) API说明 1 ...

最新文章

  1. mysql如何创建非管理员权限_mysql权限管理,一个非db管理员创建mysql的做法_MySQL...
  2. python pandas 数据透视表_python – Pandas数据透视表:列顺序和小计
  3. ic5141运行出现cannot compile ahdlcmi module解决方案
  4. .NET Core 返回结果统一封装
  5. React中antd的按需引入+自定主题
  6. Android日志[进阶篇]三-Logcat 命令行工具
  7. c语言打程序时会遇到什么问题,Sublime text3 实现C语言编译运行以及过程中可能遇到的问题...
  8. python为什么叫爬虫-可以写爬虫的那么多,为什么只有python火了?
  9. 10115 - Automatic Editing
  10. MATLAB调用C语言程序—一个简单的例子
  11. 使用python调用浏览器实现自动转发微博
  12. EnableQ,细腻让其与众不同
  13. [Ubuntu] 安装百度网盘客户端
  14. 海淘尺码表,贡献给论坛买衣服裤子鞋子的朋友
  15. matlab 三维图形改变线宽,用PANDAS改变线宽绘制三维线图
  16. arcgis如何将16bit栅格数据转换为8bit栅格数据
  17. CNN和机器学习算法性能测试
  18. 统计学中的第p百分位数的理解
  19. 前端HTML+CSS+JS
  20. 操作系统怎么把文件放到docker容器里

热门文章

  1. OMRON欧姆龙触摸屏维修NT620C-ST141-E
  2. GSM sim900a mini模块详解
  3. 模块“*.dll“已加载,但对DllRegisterServer的调用失败,错误代码0x8002801c
  4. bat批处理之for循环
  5. 关于无线充电的三大标准和四种实现方式的介绍
  6. RQNOJ 34 紧急援救 解题报告
  7. 前端(HTML css JS)开发工具及常用插件推荐
  8. Java日志框架 -- Logback(Logback入门案例、logback配置(FileAppender、异步日志、拆分Appender、过滤器)、logback-access)
  9. c语言鸡兔同笼的程序,C语言:鸡兔同笼问题
  10. html整体居中文字,html文字居中 html图片居中代码