STM32+CC1101 低功耗

发布者:WhisperingWish最新更新时间:2018-05-04 来源: eefocus关键字:STM32  CC1101  低功耗 手机看文章 扫描二维码
随时随地手机看文章

只看帖不发帖是不好的,我也来发发帖子吧,写的不好谅解啊。
      前两个月在公司做了一个低功耗项目,现在功耗最低10uA不到,平均功耗40uA左右,算是达标了。因为是公司产品,就不方便贴代码、原理图了,该产品是一个小模块,可以方便的嵌入到各种系统里面。跟原子哥他们卖的NRF2401类似,是一个读卡器。
      做这个项目中间也请了技术支持,因为外围电路芯片的功耗一直降不下来,经过与对方的反复交流,对方提供了低功耗的测试结果、硬件方案、软件方案,经过修改测试,最终成为我们的产品,功耗比较满意。
      硬件方案选择的是STM32,外加某公司的读卡芯片。前期完成了读卡等功能的开发,最后一项开发内容是最艰巨也是最困难的---低功耗。在开发过程中,从硬件设计上不断裁剪元器件,软件上不断精简代码,功耗最低都保持在3-4mA。

      电路设计上,只用到了一个LED、串口1、一个模拟SPI、一个中断线、一个读卡芯片RESET线,硬件上就只剩下这么点东西了,这个时候我采用的是待机模式,使用的是读卡芯片的中断接PA0唤醒STM32,在此之前要先使得读卡芯片进入低功耗、然后STM32进入低功耗,这一步完成了,貌似没什么问题,功耗确实从几十mA骤降到3mA左右,开始还挺满意的,但是测试厂商提供的样板,功耗却只有几十uA,有点郁闷了。为什么会这样?反复查看硬件、程序,都找不出原因,而且这个时候的工作效果很烂,根本就不能唤醒,所以我就怀疑是读卡芯片一端低功耗有问题,因为我将PA0脚直接短接VCC,这样就可以产生一个边沿触发STM32唤醒了,但是用读卡芯片无法唤醒,所以我怀疑是读卡芯片的RESET脚电平不对,经检查,确实是因为RESET脚加了上拉电阻,读卡芯片是高电平复位,在STM32进入待机后,管脚全都浮空了,导致RESET被拉高,一直在复位;我去掉上拉电阻,觉得很有希望解决问题了,但是测试结果是:有时候能唤醒,有时候不能,我仔细一想难道是因为STM32待机后管脚电平不确定,导致读卡芯片RESET脚电平不定,而工作不正常,看样子只有换用其他方案了。后面确实验证了我的想法,使用STOP模式后,唤醒问题引刃而解。
     就在关键时刻,芯片原厂火种送炭,送来急需的技术支持资料,一个包含低功耗源代码,赶紧拿过来测试,先研读下代码,使用的是STOP模式,而不是待机模式,使用的是任意外部中断唤醒,功耗低制40uA,这个时候就相当激动啊,赶快下载测试啊,结果功耗确实降了,但还是有1mA,更人家一比多了几十倍啊。。。
    我第一反应是硬件不对,经过测试修改,首先找到第一个原因,读卡芯片RESET管脚上拉电阻又给焊上去了...,拆掉后功耗骤降到几百uA,还是不行。。 测试过程中,为了去掉LDO的干扰,整板采用3.3V供电,但是后面经过测试,LDO的功耗其实也只有5uA不到,这LDO功耗值得赞一个;虽然结果还是没达到预期,但是看到了希望,胜利就在眼前啊。
    为此我反复看了技术支持提供的程序,发现他们的STM32的所有管脚都的设置都有所考究:(因为公司保密原则,代码中删除掉了关于该读卡芯片的前缀信息等)

GPIO_InitTypeDef GPIO_InitStructure; 
  
  /* GPIOA Periph clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  /* GPIOB Periph clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  /* GPIOC Periph clock enable */
  //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); 
  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); 
  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
  //####################################################
  //USART1 Port Set
  //TXD 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  //RXD
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  //RST output pushpull mode
  GPIO_InitStructure.GPIO_Pin = TRST;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(PORT1, &GPIO_InitStructure);
  //IRQ input pull-up mode
  GPIO_InitStructure.GPIO_Pin = TIRQ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(PORT1, &GPIO_InitStructure);
  //MISO input pull-up mode
  GPIO_InitStructure.GPIO_Pin = MISO;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(PORT2, &GPIO_InitStructure);  
  //NSS,SCK,MOSI output pushpull mode
  GPIO_InitStructure.GPIO_Pin = (NSS|SCK|MOSI);
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(PORT2, &GPIO_InitStructure);
  //############################################################################
  //TEST Port set
  //TESTO input pushpull mode
  GPIO_InitStructure.GPIO_Pin = TESTO;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(TEST_PORT, &GPIO_InitStructure);
  //############################################################################
  //TEST Port set
  //TESTI output pushpull mode
  GPIO_InitStructure.GPIO_Pin = TESTI;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(TEST_PORT, &GPIO_InitStructure);
  //############################################################################
  //LED Port Set
  //LED output pushpull mode
  GPIO_InitStructure.GPIO_Pin = LED;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(LED_PORT, &GPIO_InitStructure);
  
  //############################################################
  GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_8|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_15);
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

 GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10);
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  
  GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
首先,想MOSI、SCK、CS、LED、RST这些管脚应该设置为推挽输出,TXD设置为复用输出,而IRQ、RXD、MISO设置浮空输入,什么都没接的管脚全都设置为下拉输入,而TESTI、TESO我一直不解是什么东东,开始就没管,而开始的时候MISO我也没怎么注意,设置成上拉输入(而不是浮空输入),反正大部分按照厂家提供的参考,我并没有照搬,测试效果一样,但功耗确是还有80-90uA,期间我找了好久没找到原因,给技术支持一看,原来是因为MISO没有设置成浮空输入,我是设置成了上拉输入,上拉电阻一直在消耗大约40uA的电流。。。 好吧,这是自己不够细心导致的,以后做低功耗的项目管脚配置是个大问题,不能再这么马虎了!!! 我将MISO设置成浮空输入之后,最低功耗还是有40+,离10uA的最低功耗还有段距离,到底是为什么呢?最后我发现

,该读卡芯片有个TESTIN/TESTOUT管脚,是用来测试用的,出厂后也就用不上了,我也一直以为这两个脚确实没什么用,就没接;可是我发现厂家提供的样板居然接了这两个脚,但是厂商也没说这两个脚接或不接会影响功耗啊,抱着试一试的心态,我我把TESTIN/TESTOUT两个管脚接到单片机上进行相应的配置,接下来是见证奇迹的时刻了,功耗居然真的、真的降到10uA了。。。。。。。。。。。 此处省略n个字
     这时候真的很激动,真的很想骂人啊,坑爹的厂家,为什么不给提示说这两个脚不接单片机会消耗电流呢?(也许是文档里面提到了,但是几百页的文档,还是全英文的,一堆堆的文字,我再看一遍,确实没有提到这两个管脚会有漏电流。)
    项目就这样完工了,中间最重要的是技术支持的强力支持,不然项目不能完工了,这个项目低功耗STM32方面难度不高,主要是读卡芯片上面的低功耗调试起来问题很多,还是人家原厂的出马才解决了问题,因为众多原因,不能公布该芯片的资料,包括该芯片怎么进入低功耗也无法公开,所以抱歉~~。
    关于STM32进入低功耗,我简单的总结了一下:
1.管脚设置,这个很关键,还是跟你电路有关系,外加上拉、下拉电阻切记不能随便加
2.STM32的systick clock、DMA、TIM什么的,能关就全都关掉,STM32低功耗很简单,关键是外围电路功耗是关键
3.选择一个低功耗的LDO,这个项目用到的LDO功耗就很不错,静态功耗10uA都不到。
4.确定STM32设置没问题,进入低功耗有好几种情况可以选择(睡眠、停机、待机),我还是推荐选择STOP模式,这个我觉的比较好是因为可以任意外部中断都可以唤醒,而且管脚可以保留之前的设置,进入停机模式的代码使用库函数自带的,就一句:

PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
意思是,在进入停机模式之前,也关掉电压调节器,进一步降低功耗,使用WFI指令(任意中断唤醒),但是经过测试,使用WFE(任事件唤醒)指令效果、功耗一模一样。
最后一步是从STOP模式怎么恢复了,恢复其实也很简单,外部中断来了会进入中断函数,然后STM32就被唤醒,唤醒还要做一些工作,需要开启外部晶振(当然你也可以选择使用内部自带振荡器)、开启你需要的外设等等。

    总之,低功耗关键我觉得还是在于管脚配置,以及你对于外围电路的掌握。


关键字:STM32  CC1101  低功耗 引用地址:STM32+CC1101 低功耗

上一篇:stm32.cube(一)——系统架构及目录结构
下一篇:MSP430+DMA

推荐阅读最新更新时间:2024-03-16 16:01

stm32闪存的理解
STM32f1xxx的闪存模块由:主存储器、信息块和闪存存储器接口寄存器等3部分组成。 各个部分的大小因不同型号有一定的差异,数据手册中可以看到 小容量产品主存储块1-32KB,每页1KB。系统存储器2KB。 中容量产品主存储块64-128KB,每页1KB。系统存储器2KB。 大容量产品主存储块256KB以上,每页2KB。系统存储器2KB。 主存储器:该部分用来存放代码和数据常数(如const类型的数据)。对于大容量产品,其被划分为256页,每页2K字节。注意,小容量和中容量产品则每页只有1K字节。从上图 可以看出主存储器的起始地址就是0X08000000, B0、B1都接GND的时候,就是从0X08000000开始运行
[单片机]
为什么要串口唤醒STOP模式?如何才能实现串口唤醒STOP模式呢?
前言 STM32常见的低功耗模式有三种:睡眠模式、STOP模式以及待机模式,STM32L系列还有其他低功耗模式。这里主要讲的是STOP模式,STOP模式可以通过外部中断或事件唤醒,但是不能通过串口中断唤醒,因为串口中断本身不是外部中断,那么如何才能实现串口唤醒STOP模式呢? 因为我这里只是为了做验证,为了快速验证,我也就没有用RT-Thread的PM电源管理组件进入STOP模式,感兴趣的读者可以用RT-Thread的电源管理组件去实现进行STOP模式。 一、为什么要串口唤醒STOP模式? 想象一下,在某些场合,如果你有一个无线通信模块(例如ESP8266、SIM800C)和STM32通过串口发送AT命令来对接服务器实现与服务
[单片机]
为什么要串口唤醒STOP模式?如何才能实现串口唤醒STOP模式呢?
基于绝热逻辑的低功耗乘法器电路设计方案
O 引言 过去的40年中,MOS器件尺寸的持续缩小一直是促进半导体工业发展的动力。人们可以在越来越小的芯片上实现越来越复杂的功能,并且芯片的价格不断下降,使得各种便携式产品如笔记本电脑、笔迹识别仪、语音识别器等相继问世。这些设备大多依靠电池供电,电池的寿命是有限的,而目前的镍镉电池最多能提供的电能只有 26 W/pound。而且,随着芯片集成度的增加,单位面积上消耗的功率也随之增加,这不得不增加为芯片散热的成本。因而,如文献中所述,电路的 低功耗 已成为电路设计的重要指标。 从已有的研究成果可知,电路中的功率消耗源主要有以下几种:由逻辑转换引起的逻辑门对负载电容充、放电引起的功率消耗;由逻辑门中瞬时短路电流引起的功率消耗;由器件的
[嵌入式]
STM32片上外设时钟使能 失能和复位的区别
今天分享的关于时钟知识,可能很多人没有在意过。这也是之前有朋友问过的问题,这里就简单给大家普及一下吧。 1 RCC时钟说明 在STM32参考手册中,都有Reset and Clock Control(RCC)复位和时钟控制的章节。 在这一章节就可以看到有两类寄存器:peripheral reset register(RSTR)外设复位寄存器和peripheral clock enable register(ENR)外设时钟使能寄存器。 我们拿STM32F1参考手册为例,可以看到如下图寄存器: 一种是控制外设时钟的寄存器,一种是复位外设的寄存器。 2 外设时钟使能和失能 我们都知道,配置STM32外设,会先开启对应的时钟
[单片机]
<font color='red'>STM32</font>片上外设时钟使能 失能和复位的区别
Atmel业界最低功耗蓝牙智能解决方案批量上市
Atmel SmartConnect 蓝牙平台解决方案实现业内最低功耗、最小封装和最高集成度, 将物联网及可穿戴应用提升至全新水平 中国上海, 2015 年 9 月 25 日 全球微控制器(MCU)及触控技术解决方案领域的领导者 Atmel 公司 (NASDAQ: ATML)今日宣布推出业界最低功耗和最小封装的量产型 Bluetooth Smart 解决方案 。该设备在3.6V电压时的接收电流强度仅为4mA,发送电流强度仅为3mA,于部分应用中可将电池寿命延长最多一年以上。 Atmel SmartConnect Bluetooth Smart BTLC1000解决方案进一步突破了空间局限,其采用绝无仅有的2.2
[网络通信]
stm32f030c8t6 MCU进入低功耗模式
1. sleep 模式 2. stop 模式,在这个模式下,IO管脚保持run状态下的电平,RAM保持不变,所以在进入这个状态之前,先先将IO口配置好,,否则可能会有漏电流 3,standby模式下,RAM不保持,IO管脚进入高阻态,,,激活就于系统reset RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE); //时钟必须要开启,在这个陷阱中折腾了好几天 PWR_BackupAccessCmd(ENABLE); PWR_WakeUpPinCmd(PWR_WakeUpPin_1,ENABLE); PWR_ClearFlag(PWR_FLAG_WU);
[单片机]
用MSP430设计超低功耗数字温度计
  概述   很多地方都需要测量温度。在设计温度遥测系统时,通常需要采用电池供电的极低功耗模块。传统的测温手段比较多,但不论是采用分立晶体管、热敏电阻,或者是热电偶,功耗都降不下来。本文介绍了一种满足低功耗要求的可行方案,该方案使用一枚极低功耗的、带Flash存储器的MCU,以及数字温度传感器、液晶模块(LCD)和一个32kHz的钟表用振荡器。该方案的突出特点是节能耐用,仅需一枚纽扣电池,就可以连续工作10年以上。   工作原理   图一所示MCU扩展系统的电源是一枚CR-2032型纽扣式锂电池,这种电池的容量为220mAh。要让系统达到连续工作10年(87600小时)的要求,允许的最大负载电流可以用以下方法计算出来:   2
[单片机]
用MSP430设计超<font color='red'>低功耗</font>数字温度计
如何在STM32中收发float数据?
实际应用中,我们可能需要两个设备通过串口传输浮点数据: 本篇笔记为了方便演示,使用串口助手模拟其中一个设备,本篇笔记内容如下: 我们创建一个用于管理float类型数据的共用体: union float_data { float f_data; uint8_t by te [4]; }; 数据的流向如: 本次使用串口助手模拟发送设备,省略了第一步,主要看第②、③步。 创建两个共用体变量,用于发送与接收: union float_data rx_float_data, tx_float_data; 收发相关代码: // 公众号: 嵌入式 大杂烩 if(HAL_ UART _Receive(&huart3, rx_float
[单片机]
如何在<font color='red'>STM32</font>中收发float数据?
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

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