这几天对公司的一个生产小工具进行了升级,因为准备将小工具发给客户使用,所以须要制做的精良一些,因而便卡在低功耗上。html
程序是公司前辈几年前写的,在stm32f042单片机中使用正常,本身画的初版电路板也是f042单片机,刷进去程序后实测功耗低于0.01mA,万用表显示0.00mA。
然而将程序刷进更新后的板子,功耗就上去了,达到了0.88mA,翻了百倍。
好的起先是怀疑硬件电路问题,将外围电路拆除后,功耗居然上升到1.5mA了。
得,直接找了块新板子只焊了单片机和几个电容,测试仍是1.5mA。
这时候基本肯定就是程序问题了,固然也有多是我PCB画的有问题,可是检查了一下子没发现什么问题,就直接去查程序了。网络
在网络上检索了“stm32f0”“低功耗”“STOP模式”“中止模式”等关键词后,查询到了如下几篇文章,在这里只列出与如今的问题相关的,多是检索词有问题,最后也只有这几篇文章。工具
https://bbs.21ic.com/icview-329660-1-1.html测试
http://www.stmcu.org.cn/module/forum/thread-613274-1-1.htmlspa
https://bbs.21ic.com/icview-2533200-1-1.html.net
https://blog.csdn.net/hanping1020/article/details/89431935
前辈说多是单片机有什么功能没有关掉,因此检索的时候也着重检索了“STOP模式”和“耗电”相关内容。
翻了一下子帖子,基本上都是说IO口配置没有配置好,以为仍是得本身尝试一下。
在单片机开机时,将全部IO口都设置为下拉输入(注意:这里是由于当前PCB只焊了单片机,能够说全部引脚都是悬空状态),而后直接延时五秒钟,而后进入STOP模式,这里要注意必定要延时一下子,否则接下来在STOP模式是没法下载程序的!
程序下载进去,果真,5秒后进入中止模式,单片机功耗达到0.006mA。
OK!
接下来就是要测试一下什么程序没有关掉。
ADC、USB、定时器、各IO模块晶振应该是所有关掉了,没有检查出什么问题来。
这时候,重点来了,这时候心知肚明的是,必定是有什么东西没有关掉,可是不知道是哪里出的问题。
!直接从初始化入手!
把初始化部分的几个模块逐个注释掉!
果真!注释到USB_Init();时,功耗没有了。
就是USB的锅!
继续检索,这时候检索到写一篇文章,在这里看到了大佬的留言:htm
USB先复位,再关闭。blog
检查一下本身的程序,只关闭了,没有复位。
而后抱着试试看的成分在USB关闭以前,写了下面一句话:ip
RCC->APB1RSTR = RCC_APB1RSTR_USBRST;
我认可有赌的成分,但是......很差意思跳戏了......
功耗正常了,就是USB的问题,USB的关闭除了须要关闭如下几个模块以外,须要先将USB复位。
其实在测试过程当中还有个小插曲,到了小插曲就基本上锁定了问题所在。由于同一个程序,在F042上ok,在F072上GG。区别是F042使用的20pin,F072使用的48pin,在引脚上除了普通IO口以外,有1个区别:
F042的USB是使用的IO口复用功能,将PA9和10重映射到11和12,11和12这两个引脚拥有USB功能。
总结一下,若是网友们有遇到中止模式或是睡眠模式功耗太高的问题,能够按如下顺序着手测试:
1.先清除PCB上其余元器件,或是只焊单片机,确认GPIO所有悬空。
2.程序初始化阶段,将全部GPIO置下拉输入,延时几秒钟,进入STOP模式或是SLEEP模式,检查功耗是否正常。通常而言,这一步若是正常,那么PCB的问题基本就排除了,固然前提是全部IO都是悬空状态,若是有直接接到VCC或是其余高电平处,该引脚置上拉输入。
3.而后将本身的程序中的初始化部分逐个注释,排查是哪一个模块没有关掉。到这一步基本能排查出问题了。
4.根据第3步排查出的问题,检索解决办法。
须要注意的是:要仔细观察功耗的变化,若是程序修改完功耗有变化,那么修改处必定是有问题的。
再总结一下可能出现问题的地方:
1.IO口配置,可先所有下拉,而后检查电路,对须要上拉的地方上拉。悬空脚、接地脚下拉,接VCC或其余高电平信号脚上拉。也可设置输出模式,具体输出当时能够本身测试一下。
2.检查使用到的模块,USB,ADC等都是重点,像USB,要关的话,里面有不少地方都须要关,例如:
CRS_AutomaticCalibrationCmd(DISABLE); CRS_FrequencyErrorCounterCmd(DISABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_CRS, DISABLE); NVIC_InitStructure.NVIC_IRQChannel = USB_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 1; NVIC_Init(&NVIC_InitStructure); NVIC_DisableIRQ(USB_IRQn); RCC->APB1RSTR = RCC_APB1RSTR_USBRST; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, DISABLE);
3.注意各模块关闭程序的顺序,例如:
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 |GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN; GPIO_Init(GPIOF, &GPIO_InitStructure); RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOF, DISABLE);
先设置下拉再关相关IO模块的时钟。对于每一个模块,时钟最后关。
-谢谢-