這幾天對公司的一個生產小工具進行了升級,因爲準備將小工具發給客戶使用,所以須要製做的精良一些,因而便卡在低功耗上。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模塊的時鐘。對於每一個模塊,時鐘最後關。
-謝謝-