1. 程式人生 > 實用技巧 >微控制器低功耗

微控制器低功耗

出處:http://www.amobbs.com/thread-4932393-1-1.html

不知從什麼時候開始,隨便做個什麼電子產品,至少是電池供電的,都要求低功耗
特性了。好在市面上隨便什麼晶片都敢在自己的資料手冊的第一頁赫然寫著低功耗。究
竟怎樣算低功耗?小於5mA?小於1ms?小於100uA?離開了應用場合,似乎數值也失去了
單純的意義,總之越小越好。但感覺上,能用水果點亮的應用應該就是低功耗了吧。
認真說來,有點懷念當年隨便一個應用500mA,晶片微微發燙,用手一摸只要還能放
得住就大手一揮“沒問題”的時代了。最近總是和uA打交道,超過100uA,周圍的人臉色
就不好看了,好容易達到了傳說中的20uA以內,也會覺得沾沾自喜,哎……uA啊……情

何以堪啊,傷不起啊……
久病成醫,漸漸的也就有了一些心得,似乎低功耗開發的過程也可以一板一眼,按部
就班,似乎不單純是一些零散的“看情況而定”“只可意會”的東西了。於是忍不住,將
這些似是而非的步驟記錄下來,以簞初來者。


事半功倍還是事倍功半——思路決定成敗



“肚子餓的時候,睡著了也就不覺得餓了……於是乎,難得的雙休日宅在家中補覺,往往也就
一天只吃一餐飯了”——技術宅人_大體如此。
應該沒有人能在夢遊的時候幹活吧?所以,平常工作的時候,飯還是要吃的。休眠和幹活應該
是一對矛盾體。於是乎,晶片資料手冊上那些“小的出奇”的休眠功耗,似乎大部分時候只是用來
擺設的;而工作功耗才是實實在在的東西。有時候,為了體現所謂的低功耗,還要在應用中設計一種

所謂的低功耗模式——當系統確認沒有事情可做一段時間以後就乾脆回家睡覺了——這大體就是現在
市面上常見的低功耗應用的某種程度上的現狀吧。於是乎,降低工作頻率這種“馬兒跑,馬兒不吃草”
的邏輯,就成為降低正常工作模式下系統功耗的常規選擇。苦啊……多少人在工作頻率和功耗間糾結
……又有多少功能實現的本身對對頻率擁有最低要求……苦啊——我說的是寫程式碼的程式設計師。

說起來,降低功耗似乎是一個軟體和硬體協同工作才能解決的問題。比如AD取樣時候的分壓電阻,
如果直接接了地,那麼就會一直消耗電流,如果通過一個IO口來控制其接地的方式,只在需要取樣的
時候接地,取樣完成以後就懸浮或者拉高,就可以將這部分開銷降低的最小。

顯然,將低功耗完全化作硬體設計的工作或者軟體設計的工作都是不合適的。




>>Figure A

VCC------------------[ R1 ]---+---[ R2 ]--------------GND
|
_____________ |
| |
AD IO []---+
|
|

>>Figure B

VCC------------------[ R1 ]---+---[ R2 ]----+
| |
_____________ | |
| | |
AD IO []---+ |
| |
CTRL IO []------------------
|




從硬體角度來說,找到所有可能的消耗電流的迴路,一一確定哪些是可以通過軟體控制的方式來
優化功耗的,哪些是不可避免的,並給程式的編寫人員提供一個所有IO口狀態對功耗影響的關係(通
常用簡單的表格說明一下高電平會怎樣,低電平會怎樣,懸浮會怎樣就足夠了,並不需要精細到具體
的數值。)做到這一點,基本上硬體的工作就告完成,剩下的就是軟體開發人員的發揮空間。而基於
軟體的功耗降低策略,正是本文所要討論的重點。

說到軟體功耗優化,說簡單也簡單,說複雜也複雜。簡單總結過來就是:應用模組化、功能任務
化、任務週期化、功耗自理化、休眠一票否決化。還不夠簡單?再濃縮就是:能休眠就休眠,怎麼休眠
投票選。呵呵……估計簡單過頭了,失去了資訊量,下面將這幾個方面一一展開:

1、應用模組化、功能任務化、任務週期化
一個具體的應用,通常由很多子功能,子任務組成。對嵌入式系統軟體構架有所瞭解的人
更能理解:一個應用是由對若干服務(servie)的呼叫實現的。這裡服務可以是硬體服務,比
如AD取樣,比如串列埠通訊,比如外中斷觸發,比如定時器服務;也可以是軟體服務,比如各種
通訊協議棧,FAT檔案系統,佇列,軟體濾波等等。一個服務通常實現一個或多個功能(好的
任務劃分不會讓一個服務包含多於2種以上不相關的功能)。簡單的功能,比如CRC校驗這樣函
數進去函數出來基本上可以立即獲得結果的,我就不說了;複雜的功能最好都使用任務的方式
來實現。說到任務,就要牽涉到作業系統、排程器或者乾脆是簡單的狀態機了。總之,可以將
任務的實現理解為一個流程。既然是流程,那麼任務所要做的工作就是週期性的。舉例來說,
AD取樣任務由至少3個步驟組成:通道選擇和啟動取樣,取樣以及等待取樣完成,資料的處理。
這樣三個步驟共同組成了一個任務週期,當三個步驟完成以後,我們可以認為一個週期結束了。
再舉一個例子,I2C通訊,一個完整的資料包的傳送通常包含了若干的狀態,這一系列狀態構成
了一個任務,當最後一個狀態(或者某些異常退出狀態)結束後,一個任務週期就結束了。
總結來說,應用模組化,功能任務化,任務週期化的最終目的就是任務週期化。只有實現了
週期化,一件事情才有始有終。有始有終,就可以根據需要發放“工資”,避免浪費。而做到
任務週期化的最常見辦法就是通過模組化的服務將功能獨立出來從而便於管理,便於找到一件
事情的開頭和結尾。
找到不拉馬的士兵,是功耗管理的起點。而做到這一點,是需要對嵌入式系統擁有全域性的
概念,需要有基於模組化開發,面向服務和介面開發的經驗的。經驗的積累和全域性的概念,是
最複雜的一個部分。


2、功耗自理化、休眠一票否決化
一旦實現了任務週期化,也就等於將整個系統分成了很多週期性工作的小任務,他們可能
看起來是交錯的、並行的或者毫無先後關係的,但從本質上說,每個小任務只要關心自己的起
始和中止就好了。系統的功耗管理最後就化簡為每個任務的功耗管理——只要每個任務做到了
功耗最小,那麼系統整體在一個有效的協調方式下,就能做到功耗最小。
根據上面的描述,基於任務的功耗管理實際上就被人為的分成兩個部分:微觀角度任務
自身的功耗管理和巨集觀角度多工休眠的協調。

我們先從微觀來看。一個任務,首先肯定能獨立完成自己的功能,這一點看似不起眼,其實
很關鍵,他保證了任務中所有的步驟都是確定的,都是“自己說了算的”,對外界來說“都是黑
盒子”的——簡而言之就是“自治”的。在這一基礎上,如果要求任務滿足低功耗的要求,不外
乎以下幾種情形:
1)任務執行的過程中,是不允許休眠的,因此任務的開頭和結尾處要設定標誌——告知協調
       系統,“只要我還沒有說OK就不允許休眠”“人在任務在”;
      2)任務執行的過程中,某一些階段允許休眠,而另外一些步驟是不允許休眠的;如果我們將
“不允許休眠”看作是休眠的最低等級,那麼根據功耗的大小,休眠可以由低到高分為若干
各等級。這種情況下,我們可以修改上面的定義為:任務的執行過程中,不同階段允許不同
的休眠等級。
3)任務執行的過程中,不在乎是否有休眠。

      顯然,如果這三類任務同時存在於系統中,第三類任務基本上是“空氣”可以無視的,而第一
種任務是相當霸道的,只要他在執行,就根本不允許休眠;對於第二類任務,即完成了任務,又兼
顧了休眠,是一個值得表揚的“好同志”。我們在系統任務設計的時候,應該儘可能編寫後兩類任
    務,而避免或者嘗試拆分第一類任務。
      
從巨集觀角度來看,任意時刻,可能有多個任務同時在執行,因此每個任務對休眠的需求都是
不同的。如果要設立一個協調機制,該怎麼辦呢?難道這個協調機制需要了解每個任務的細節,
然後“智慧”的找到合適的時間點使用合適的等級來休眠麼?太繁雜了吧?其實很簡單,讓每個
任務都選派一個代表來開會好了——每次這個協調機構想休眠了,就召集所有的代表投票,大家
每個人提供一個自己覺得能夠容忍的最高休眠等級,最後會議的仲裁者從這些投票中找到一個最
小的休眠等級——也就是水桶的最矮一環作為“會議共識”,然後進入相應的休眠等級。顯然,
如果有人投了“不休眠”得票,仲裁就只能無奈的選擇放棄休眠。所以,每一個“任務”都應該
是一個負責的任務,而不能因為一己私利,為了保證自己任務的執行就草率的選擇自己在執行的
期間“不允許休眠”。正確的做法就是,每個任務都應該根據自己的不同步驟及時的更新自己對
休眠的容忍度,從而保證開會的時候,能夠達成有意義的結果。

總結來說,如果每一個做事的人都很負責任,任務的劃分又很合理,那麼通過這種協商機制,
體統自然就不存在“不拉馬的士兵”,也能做到“能休眠時就休眠”了。這種情況下,晶片資料
    手冊上那些休眠的功耗數字對你就有了實實在在的意義。怎麼樣?如果你已經領悟到了,就偷著
    樂吧。如果你還不知道如何具體去實現這些步驟,彆著急,隨後的章節我們一一為您展開。

低功耗設計第一步:自底向上,順藤摸瓜




假想一下,現在有一個新的專案放在你的手上,具體的專案需求包含了AD多通道資料取樣,
AD取樣後資料的處理(較為複雜),同時還要支援I2C通訊,I2C的通訊協議較為複雜。這樣一個
裝置必須做到功耗最低。應對這樣一個需求,如果已經有一個建議的晶片,比如AVR Mega或者Tiny
我們應該怎麼做呢?


"先搞清楚我們是怎麼睡的"



第一步,查閱資料手冊,找到可被喚醒的最大休眠模式,編寫一個測試工程——按照資料手冊
所說的要求,實現一個純粹的什麼都不做的休眠模式,同時,關閉所有能關閉的功耗——比如掐斷
某些外設的時鐘,比如正確設定IO口狀態。這樣我們就獲得了一個極限功耗,也就是正常情況下你
通過系統設計可以無限接近的一個功耗。
這個時候,你需要的是,根據硬體設計工程師提供的IO口設定建議配置IO狀態,以獲得一個
子人為的最低功耗。下載程式碼到目標電路,測量功耗。如果將電路板上無法優化的固有功耗——比
如某些固定消耗電流的電阻功耗——消除以後,仍然沒有達到資料手冊上所說的對應休眠模式下的
最大值時,你就要找硬體設計的兄弟喝茶了,兩個人一起同時從硬體的角度和軟體的角度找原因。
直到我們獲得一個滿意的可自行喚醒的“純休眠功耗”。
這個過程非常關鍵,他直接決定了日後你能達到的最好效果。多花費一點時間是值得的,因為
在這一過程中,你能非常細微的“初步”瞭解到哪些外設和配置影響功耗,如何影響,有多大的影響。
千里之行始於足下,多花點時間,值!
切忌,做軟體的同學不要一口咬定說問題一定出在硬體設計上。舉一個例子:我在這個步驟地
時候,始終達不到資料手冊上標註的休眠模式下的最大允許功耗,而根據資料手冊,我認為我已經將
所有能關斷的外設都關閉了。於是我開始聯絡IC設計部門抱怨。最後的結果是,有一個外設使用了不
同於CPU的獨立時鐘——也就是可以理解為非同步時鐘,在這種情況下,CPU對他的暫存器設定需要一定
的時鐘週期才能完成同步。而我在系統中簡單的設定暫存器將其“關閉”後立即就去休眠了,可想而
知由於沒有等待非同步始終同步,也就是這個操作還沒有生效,我就去休眠了,這個外設還處於開啟狀
態,功耗自然居高不下。哎……臉紅啊……


"再搞清楚我們是怎麼醒的"



第二步,確認系統的脈搏。所謂確認系統的脈搏就是要總體審查整個應用的工作方式,找到一個
系統時鐘的最大節拍,並根據這一要求確認晶片所使用的喚醒源。也許很多人都有使用定時器溢位中
斷或者比較匹配中斷產生一個系統毫秒級時鐘的習慣,然而,除使用外部手錶晶振的RTC或者非同步時
鍾源的定時器以外,普通定時器的正常工作都需要系統主時鐘提供時鐘源,這是我們所追求的低功耗
模式所不允許的。有時候仔細想一想,一個毫秒級別的系統時鐘真的是必須的麼?
在AVR中,在低功耗模式下能提供系統時鐘的通常就是看門狗了,通過設定,看門狗能夠以一個
固定的時間間隔(16ms / 32ms / 64ms / 128ms)將系統從最大的休眠模式下喚醒。因此在那些必須
要用到系統節拍的應用中,如果16ms是你所需系統節拍週期的約數,你就可以考慮採用看門狗來提供
一個並不是那麼準確但是非常穩定的時鐘源;否則你就要面對以下的選擇:
a. 我的系統工作模式決定了我必須要一個小於16ms的系統時鐘;那麼整個設計是否允許使用外部
時鐘源給非同步定時器(Timer2的非同步模式)或者某些專門的RTC提供時鐘源——這些外設通常支援將系
統從最大的休眠模式下喚醒,就像看門狗做到的那樣。
b. 如果我的系統不允許增加外部時鐘源,系統是否允許通過外部觸發的模式來工作——也就是
通過外中斷或者引腳電平變化中斷來喚醒系統,並開始一次工作流程,完成後系統再次陷入永久睡眠。
c. 如果以上都不行,你可以考慮換晶片或者修改系統的需求的——至少系統需求在功耗的部分
需要做一些妥協。

以上“確認系統脈搏”的步驟實際上是一個“例子”——系統設計的例子,或者說系統工作模式
設計的例子,這是一個系統構架師或者說像我這樣“自覺的”系統構架師應該要認真學會並經常實踐
的工作。一個籠統而完整的描述如下:
1) 對一塊目標晶片進行調查和確認:確認其所有的休眠模式,以及對應休眠模式關閉的時鐘源,
這些時鐘源涉及到的外設——巧婦難為無米之炊,這一步首先搞清楚系統設計的時候手上有
哪些材料。
2)研究具體應用的需求,明確系統的工作模式(以取樣類的模式來說就是取樣,休息,再取樣,
再休息,整個系統是一個狀態機並以取樣事件作為驅動;取樣不僅提供資訊,也提供系統的
脈搏。即便這類系統還涉及到LCD重新整理或者I2C/串列埠通訊,由於資訊的本源是取樣,因此取樣
週期本身決定了資訊的有效性,那麼LCD的重新整理週期,或者通訊的緩衝跟新週期沒有理由必須
大於取樣的更新週期)。在這一前提下,明確系統對喚醒源以及喚醒模式的需求,由此便確定
了系統的基礎休眠模式,進一步說,比較這一基礎休眠模式功耗和應用所需的功耗,便可給出
系統設計的一個初步評估結果。有時候甚至能給出一些系統功耗的直接預期資料。

舉例來說:
假如通過評估,我們發現“實現應用所涉及到的外設”可以將系統從某個最大允許的SLEEP模式
喚醒(例如Power-Save Mode),則這個SLEEP模式就是基礎Sleep模式,我們評估系統功耗的
方法就是估算,在完成一次任務的情況下(任務節拍),sleep所佔的時間是百分之幾,系統
工作的時間是百分之幾(active time),然後用下面的公式就可以估算出系統的正常功耗:

Equation A:
normal power-consumption =
sleep consumption * sleep time(%) + active consumption * active time(%)

3)根據研究報告,討論系統的可行性。如果不可行,則根據已經明確的系統工作模式,對應的喚
醒源要求重新選擇晶片,並返回步驟1)。如果可行,則可以進行後續的設計。

Figure 1.1 一個能體現低功耗節拍設計的系統狀態圖





這種系統設計模式看似有點本末倒置——還沒有搞清楚需求就已經把晶片定了——實際上,這種
方式非常符合我們通常的開發模式:先有了一個初步的概念或者備選晶片方案,這些方案可能來自一個
已有的方案,一個已有方案的相容方案,一個老闆或者老員工/經驗者提出的方案——總之有了一個基
礎或者說原形,我們開始調查和研究具體低功耗的可行性,並形成了一個研究報告,這一報告將直接
指導下一步的行為:由於需求非常明確,我們可以決定是否更換晶片或者直接進入下一步的開發。上
面三個步驟實際上形成了一個LOOP,這一loop其實來自於“快速原型法”這一古老的“敏捷”開發模式
自然,規範,高效。

  完成了以上兩個步驟,可以說這一階段就結束了,至此我們對系統的關鍵效能資料已經成竹在胸:
系統最低能實現多大的功耗;外設某些敏感的引數設定將如何影響功耗——當我們需要在外設效能和
功耗之間做妥協和權衡的時候這些資訊就將發揮巨大的作用;我們甚至對系統外來如何工作,或者說
系統最基本的問題:“時間問題,整個複雜的多米諾骨牌是從哪裡被什麼推倒第一張牌的”大致有了
瞭解。我們甚至知道,如果不出意外系統將會達到怎樣的功耗。
  簡單說,我們已經知道系統是能夠實現的,功耗會在什麼範圍也是大體有所概念的。萬事俱備,
只欠東風。欲知後事,請聽下回分解。


本小結的一個附錄:試探功耗底限的系統配置方式——分享一些實實在在的經驗



A. 對AVR來說,不用的引腳怎麼辦?
>> 如果這個引腳屬於ADC取樣引腳
i) 通過DIDRn暫存器關閉對應引腳的數字輸入,這個時候PINX對應位將永遠讀取到0
ii)通過DDRx和PORTx暫存器將對應的引腳設定為輸入,“關閉”上拉電阻
>> 如果這個引腳是普通的GPIO
官方推薦的方式是給這個引腳一個確定的電平,比如:
i) 通過DDRx和PORTx暫存器將對應的引腳設定為輸入狀態,並“開啟”上拉電阻
ii)通過DDRx和PORTx暫存器將對應的引腳設定為輸出狀態,並輸出低電平,PCB設計上,
將該引腳接地。
>> 如果這個引腳是RESET引腳
當電路要求保證穩定的情況下儘可能簡化,同時,VCC電壓在上電時刻電壓升高速度不會很緩慢,
則接外部上拉電阻到VCC,這樣雖然對功耗影響不大,但是可以適當提高一點抗干擾性。
>> 如果這個引腳是擴充套件的ADC引腳
基本可以不管,或者接地。

B. 對AVR來說,需要使用的引腳怎麼辦?
>> 如果這個引腳是開漏輸出/線與輸入的引腳,比如TWI,同時需要與外部裝置連線,而這一連線是允許
拔插的
i) 如果邏輯上允許,接下拉電阻。
ii)如果是外中斷引腳或者因腳電平變化中斷引腳,避免懸浮,相比上拉來說,儘可能選擇
下拉。這樣設定的目的是避免不確定電平經常將系統喚醒。選擇下拉的原因是將高電平
的選擇權力交給外部裝置,同時更傾向於盜電(*^_^*)。
>> 對於ADC引腳
i) 如果永遠不會用於數字訊號的輸入用途,請參考空閒引腳的處理方式。
ii)如果需要用作數字訊號的輸入用途,請在通過PINx讀取電平前,通過DIDRn暫存器開啟
對應引腳的數字輸入,並插入兩個NOP後讀取電平,完成讀取後,立即關閉數字輸入功
能。
>> 對於控制訊號引腳
i) 直接驅動LED總是悲劇的開始,別忘記加入限流電阻,儘可能使用高亮LED。
ii)如果非要輸出電平的控制訊號,請認真考量有沒有漏出電流的可能,如果有,請儘可能
在不需要輸出控制訊號的情況下,將IO口處理為無電流漏出的狀態(或最小小電流漏出
的狀態,關於出還是入的語言文字問題,你懂的),具體狀態圖應該由硬體設計人員給
建議。總原則就是按需分配。

C. 說說PRR暫存器
>> 如果某個外設的供電通過PRR暫存器的設定被掐斷了
i) 除非特殊說明,否則這個外設的所有暫存器都是無法正確讀寫的
ii)如果在外設供電關閉前,外設的中斷標誌沒有被清零;或者說正在執行這個中斷處理程
序的時候該外設被斷電了,則中斷標誌不會被清除。表現症狀就是中斷持續被觸發。其
實想想很簡單,參考i)就知道了。
iii) 很多時候,關閉定時器這樣的外設並不能減少多少功耗,基本上都是小於5uA的。經驗
上關閉那些和模擬特性相關度較大,或者擁有獨立相關的時鐘源的模組,通常會減少不小
的功耗。
iv) 謹慎使用該功能,除非你認真閱讀了資料手冊。這也是很多人所謂休眠醒不過來或者工
作不正常的主要原因之一。

D. 說說工作頻率
>> 在正常的工作模式下,頻率越高功耗越高。
i) 推論1:對於同樣一個工作,頻率越高,完成該工作的時間越短
ii)推論2:根據Equation A,對於同樣一個工作,Active的時間越短,則Sleep的時間越長。
>> 假設頻率翻倍,功耗增加4倍,則:
i) 推論3:通常Sleep功耗至少為某一個頻率功耗的4分之一甚至更大。當頻率翻倍的時候,
工作時間縮短一半,假設功率翻倍時功耗為4倍,則Active部分的實際功率翻倍
(50% * 4);同時,節省出來的時間成為Sleep功耗,此時,系統的功耗變化為:

假設頻率翻倍前的Active功耗認作 C,工作時間為T,則:
翻倍前Active部分的功耗為C * T
頻率翻倍後,Active的功耗為 4C,工作時間為 T/2;同時,假設Sleep的功耗為 C/4,則
翻倍後的實際功耗為
4C * (T/2) + (C/4) * (T/2) = 4.25C * T / 2 = 2.125 (C * T)
可見頻率翻倍後實際功率為增加前的2.125倍。顯然從功耗的角度來說並不划算。

但請注意,Sleep功耗通常遠遠小於這裡的1/4,以ATmega88為例,1MHz VCC = 2V的情況下
最大功耗是550uA,而Sleep模式(Power-down VCC=3V)最大功耗是15uA,差不多36倍。在
這種情況下,顯然頻率翻倍,功耗接近2倍。

有意思的是,如果對以上公式進行迭代,你會發現,頻率越翻倍,Sleep功耗和翻倍前的
Active功耗差距越大。也就是說基本上每次翻倍,功耗基本上可以認為是翻倍的。同時
頻率增高帶來的好處卻是運算速度每次都翻倍的。從這個角度來說,是否頻率越高越好呢?
(速度快,功耗增加小)。再聯絡到那些與外部引腳操作直接相關的功耗,頻率越高,外部
引腳操作中可控的功耗部分就小(請聯絡前面AD的例子),那麼從這個角度來說,似乎功耗
還會減小一些。

再次強調,以上結論建立在工作完成後立即休眠的工作模式下,同時Sleep模式的功耗必須
遠遠小於Active功耗(通常8~10倍),使用外部時鐘源,以及晶體振盪器所需的額外功耗,
及從休眠中喚醒時時鐘穩定期間所需功耗都未作考慮。
>> 實際上,MCU的功耗分為兩個部分,一個與頻率有關,一個與工作電壓有關,即
E = E(V) + E(f)
當頻率翻倍時,影響的只是E(f),而這部分功耗並不會最終導致4倍的功耗,其值往往在2倍
甚至更低。在這種情況下,Sleep+Active的工作模式會帶來更低的功耗。證明略。

>> 通常,我們測量功耗的方式就是測量電流
i) 推論4:在非積分式功耗測定方式中,如果工作頻率越高,則Sleep時間越長,在電流測量的
時候,Active電流越接近於“毛刺”,這就導致了頻率越高,功耗越低的假象。因為大部分的
電流取樣點都落在了Sleep上。
ii)推論5:採用積分式功耗測定方法才能正確的測定實際功耗。當然,如果你想騙騙普通客戶,
高精度電流表的電流結果(甚至是平均電流)都將反饋給你一個“非常理想的結果”。

低功耗設計第二步:讓我們來下棋,很大很大的一盤棋



通過上一節的討論,假設在您的設計中對應的步驟已經完成,則我們至少獲得了以下資訊和結果:
1. 一個極限功耗
2. 一個可行的系統工作模式(滿足應用需求同時兼顧低功耗的系統節拍)
3. 當使用2中提及的系統工作模式時,通過公式計算獲得的理論系統功耗(系統正常工作下的功耗)

顯然,萬事俱備,只欠東風,就只剩下具體實現了。彆著急,我們先來搞清楚幾個定義。

a. 普通工作模式(Normal Mode / Active Mode)
這裡的普通工作模式是指能夠實現正常系統功能的模式,在這種模式下,MCU並非一直處於工作狀態,
而是根據前面一章提到的功耗公式,結合了Active和Sleep兩種MCU狀態的模式。簡而言之,一個保證了應用
基本功能的同時能休眠就休眠的工作模式。
b. 低功耗模式(Idle Mode / Sleep Mode)
這裡所說的低功耗模式是指根據使用者的應用需求,在使用者指定或者系統自動偵測滿足某些特定條件的
情況下,儘可能關閉不需要的功能,僅保留某些應用必須的任務以降低功耗為目的的模式。(例如一段時間
沒有使用者操作就關閉LCD和LED背光)

總結來說,這裡的普通工作模式和低功耗模式都不直接對應MCU提供的Active和Sleep模式,而是兩個
根據使用者功能需求定義的具有不同功能配置的功耗模式。他們可能都牽涉到MCU的Active和Sleep狀態。明確
了這兩個定義,我們後續討論中牽涉到的很多說法才不會混淆。

2.1 工欲善其事,必先利其器
在實踐低功耗系統設計前,我們必須要有一個有效的手段來檢測或者說觀察系統當前的工作模式,通俗
的說就是要能夠隨時知道系統什麼時候工作,什麼時候休眠,並且最好能夠準確的知曉工作和休眠的時間比
例。對於缺乏高精度電流表的場合來說,這種觀測手段就更為重要了。
簡而言之,我們需要一種實時追蹤(trace)系統功耗模式的除錯(Debug)手段。既然是實時追蹤,意
味著斷點、單步這種常見的手段是不行的,系統必須保證處於正常的非間斷工作狀態下。同時,作為Debug,
必須能夠準確顯示休眠和工作的狀態,並能夠將這些資訊儲存下來,大家可以在腦海裡想像有這麼一個類似
地震記錄儀的裝置,一直不停的在紙帶上記錄著功耗變化的資訊。
說的這麼複雜,其實做起來很簡單。Debug階段,我們關係的是系統如何休眠的,其實際功耗可能由於
Debug手段的存在而並不準確,但這一資訊已經足夠了,因為在隨後的檢測中,我們可以生成一個release版
本(移除了debug相關的程式碼)直接通過電流表檢驗系統功耗。Code 2.1就是一個很好的例子。程式碼在休眠前
在某一個訊號引腳上輸出高電平,在退出休眠模式後輸出低電平。此時,藉助示波器或者邏輯分析儀的幫助,
我們就可以記錄並檢測系統的功耗模式,甚至根據資料手冊提供的Active電流和Sleep電流計算出一個非常
接近實際結果的理論_功耗。


Code 2.1 一個Tiny下進入Sleep模式的程式碼例子

  1. static void enter_sleep_mode(uint8_t chLevel)
  2. {
  3. /*! \brief sleep mode select bits
  4. *! MODE SM2SM1 SM0
  5. *! idle 0 0 0
  6. *! ADC Noise Reduction0 0 1
  7. *! Power-save 0 1 1
  8. *! Power-off 1 0 0
  9. */
  10. static FLASH uint8_t c_chSleepLevel[] = {
  11. ((0x00 << SM0) | _BV(SE)),
  12. ((0x01 << SM0) | _BV(SE)),
  13. ((0x02 << SM0) | _BV(SE)),
  14. ((0x03 << SM0) | _BV(SE)) };
  15. uint8_t chSleepMode = c_chSleepLevel[chLevel] /* | _BV(SE)*/;
  16. SAFE_ATOM_CODE(
  17. MCUCR = (MCUCR & ~(_BV(SM0) | _BV(SM1) | _BV(SE))) | chSleepMode;
  18. ENABLE_GLOBAL_INTERRUPT(); //! enable interrupt
  19. set_signal_a(); //! 即將進入sleep前將訊號引腳置高
  20. __sleep(); //! sleep
  21. //!< clear sleep control register
  22. MCUCR &= ~(_BV(SM0) | _BV(SM1) | _BV(SE));
  23. clear_signal_a(); //!< 退出sleep模式後將訊號引腳拉低
  24. )
  25. }

複製程式碼



有了這樣一個手段,我們就能很方便的進行實時除錯,設計出“能休眠就休眠”的好演算法。這也是我們
後續討論的基礎。

Figure 2.1 一個可能的系統功耗模式監測的樣例


TO BE CONTINUE...

以前網上找的:
現在,有許多微控制器應用領域,都是用電池供電,節能成為設計工程師普遍關心的問題。希
望大家就這方面展開討論。

以下提供一些討論的方向:

1、如何降低系統功耗?(軟體?硬體?)
2、各位在這方面有何經驗教訓?(可以拿出來與大家分享)
3、各種晶片的功耗比較?
4、SLEEP模式應用的注意事項?
5、一些新型的節能器件的介紹?
6、其它與低功耗設計相關的話題?……

進入掉電模式
現在有很多的低功耗的片子,特別是在進入掉電模式之後,只有1uA的電流。也可以使用電源管理
的方法,在不工作的時候,把系統電源關斷,這樣更省電

我用了很久51晶片,本來對它的功耗非常不滿,但是因為其價格越來越便宜,本身的價效比依舊
很好,所以總也甩不掉。

1、休眠。一般的系統都不會到了忙不過來的地步,適當的休眠還是可以節省一些功耗的,在一些
簡單的系統,多抽時間休眠成了省電的關鍵,你看別的晶片都不耗電,只有微控制器了,它就是關
鍵了,在有些時候,提高主頻反而會獲取更多的休眠時間,反而使系統功耗更小了。但是值得注
意的是,經常性的切換休眠和工作狀態會讓電源產生mV級的波動,特別對於很多線性穩壓器只有
100mA以內的輸出能力的情況更明顯,這樣的波動或許會影響系統內的AD和一些其他類比電路,
值得注意。

2、掉電。如果進入了掉電模式,很多51晶片是無法通過中斷重新開始工作的,可以外加一個微功
耗的微控制器來提供復位,這個微控制器只負責鍵盤掃描和復位51微控制器,以及傳送鍵盤編碼到51芯
片。 我以前見過一個手持裝置,耗電很小,但是包括了大容量儲存、顯示、輸入、資料輸出、檢
索等功能,平時89C51總是處於掉電狀態,但是有了鍵盤操作後,就復位開始執行,處理完鍵盤送
來的任務之後又自動掉電了。

3、複雜運算。複雜運算(譬如指數運算、浮點乘除)一定會佔據更多系統時序,響應減少休眠時
間,可以通過查表方式,這樣用大容量的表格代替了現場計算,更多的時間不就可以睡覺了嗎?

4、如果軟體任務少到一定程度,那麼可以考慮把晶體搞到32k去執行,其實這樣更省電,但是這
意味著51軟體基本沒什麼高速的事情做,也不需要序列通訊,否則,還是老老實實面對現實吧。

我覺得,51晶片用於電池供電的系統不是很合適,但是從開發週期看,它的開發環境很好,畢竟
可以承載8位機的相對大型的應用,有時候又不得不用它。我覺得距離51最靠近的AVR微控制器更適
合將來的應用,因為其效能價格比相對其他微控制器還是不錯的,除非51晶片可以將來做到在3MIP
下,工作電流小於2mA,休眠電流小於500uA,掉電電流小於10uA。
在很多的設計中,採用線性降壓的方法,電源損耗大,如提高供電電壓,並用高效率的DC-DC電
源,可延長電源使用的時間
89C8252掉電工作,看門狗做“系統執行時鐘”同時把看門狗復位“軟體模擬成看門狗中斷”
“狗”叫一次跳起來看看,“RAM值班室登個記”,同時還登記下當前PC+1的值,然後“睡死”
過去!
平均功耗不大於5V/0。3MA,而且有很強的抗干擾性!
軟體優化很重要!
如64MS一次“狗”叫!起來做40條指令,24MHZ下最多:40*0。5=20US
於是佔空比:20/64000=1/3200 即平均電流下降3200倍!!!
外設會受復位改變嗎?當然!但鎖存器幹什麼啊?!
如何知道程式能執行多久?下一條執行指令執行到那?
如果任何時刻,你自己編的程式執行在那個片區,你都不知道,那還叫什麼搞軟硬體的要天人合
一啊?!
系統任務不忙的情況下,你的看門狗定時復位方法還可以,但是。。。好多情況下似乎做不到呀


我的51系統只有200微安
省電是個大難題,特別是51,但只有用心還是可以做到的,特別是工作任務少的時候。我的一個
水文遙測系統,用12伏電池供電耗電只有200微安,有8Mbit data flash,一個調變解調器,一
個時鐘,一個485通訊口,一個232通訊口,還有6個數碼管,是不是夠多的了,但它們平時都不
工作,我也是用看門狗復位來喚醒51微控制器的,每1.6秒一次,用的是x25045,可是25045的復位
時間有200毫秒之多,實驗發現,51從掉電返回到正常工作只要有30個毫秒足了,別小看節省的
這一百多毫秒,因為51在每次醒來是隻要發現沒有任務就可以馬上POWERDOWN了,所以加了一個
CMOS的單穩來複位。其它的就是口線的狀態一定要注意,不要讓它吸收電流也不要輸出電流,要
是做不到可以試著加一此電路,如反相器.

穩壓電源是個要權衡的事,雖然開關穩壓有較高的效率,但在低功耗設計不一定對,開關電源本
身消耗的電流就是一個大問題,一個微安級的系統也許要特別對待,我用的是max667線性穩壓數
微安靜態電流.我想開關電源做不到
對於外部事務頻繁的應用,無法使用掉電方式
雖然很多51晶片支援外中斷觸發晶片脫離POWER DOWN狀態(如華邦的W78E58、W77E58),但還
是解決不了序列通訊的問題,而且對於需要內部精確定時的場合,從POWER DOWN到正常工作需要
很長時間,這個恐怕還是難於讓人接受。莫非沒有一個廠家可以產出高速小功耗的51晶片?沒到
理呀,PHILIPS不是玩了很久嗎?怎麼弄出的晶片在12MHz下還是大於10mA,休眠也有幾個mA,這
也吹牛沒下功夫嘛!

用51做低功耗,太累了
低功耗多得是,象PIC、EMC輕鬆做到20uA以下,51有POWER DOWN,但只能復位喚醒,有少數可
用INT喚醒,太麻煩。有些有雙晶體的微控制器,做低功耗最簡單,平時用32768工作也只有20uA,
這種微控制器一般帶有LCD。EMC內有PLL微控制器做功耗系統很方便,象78565,567,功能強價格低

samgsung的微控制器可以做到
565匠人也用過。平時進IDLE模式,功耗只有幾個UA
分級供電和外部喚醒確是一種可行的辦法
在分級供電中要注意的是如果電源是小電流的穩壓器件最好有一個比較大的蓄電電路,要不然
微控制器喚醒和上電時可能會起動不了,而且可能會進入一個不希望的振盪期,比如微控制器要起
振,電流增大,這時電源供不起,電壓就下降,引起的是微控制器又停振電壓又回升!所以一個合
理的電源管理電路就顯得很關鍵,這方面的專業IC將是未來一個很有前途的產業!這個IC應有一
個內部低速的定時器和一個專門的蓄電管理電路,當電路進入低功耗後應該將蓄電電路衝滿以備
喚醒和大功耗時用,這種電路主要用於小電流供電的環境,它可以為小電流供電環境提供一個短
時間的大電流工作。 另外微控制器的耗電除了核本身的耗電外,大多是IO口的耗電,大家可以
通過降低主頻,將IO口置在比較合適的狀態來達到一個比較省心又省力的方式。而且不全理的頻
繁喚醒有時會帶來更多的電耗!

用TI的微控制器MSP430系列非常省電。正常工作時幾百微安,掉電時約1微安
87LPC76X低功耗51,32k時20uA
使用雙振的微控制器,在系統不忙的時候使用32768的晶振,同時進入SLEEP這樣處理通常耗電都在
幾個uA.在處理SLEEP喚醒後的程式需要小心處理,特別是臺灣的微控制器,有時廠家給出的資料都
要小心,我碰到過。
我不知道您是用的哪家的51微控制器,功耗能做到這麼低。據我所知ATMEL89C52 Powerdown mode
下最少是40微安。您的系統中有這麼多的器件,即使都是低功耗可關斷的器件,那你的系統每次
工作時都要啟動所有的器件才能運轉起來,這個啟動過程是多長呢?還有您的微控制器不會工作在
12V的,你還需要一個電壓變換器,它平時不用電的嗎?你的CMOS單穩不用電的嗎?據我所知常
用的485,232,modem,flash都不是低功耗可關斷的,如果您都使用的是特殊器件,那實用的意
義何在呢?或者您使用了其他器件來控制這些耗電多的裝置,那您一定是硬體高手了。可否指點
一二?
高速51: C8051FXXX在1M指令流下,VDD僅僅1.5mA
用IO口控制RC振盪頻率?
用RC振盪方式,並將IOSI口接一個電阻到IO口上。通過切換IO口的電平來切換頻率,方法如
下: 功耗,在電池供電的儀器儀表中是一個重要的考慮因素。PIC16C××系列單片
機本身的功耗較低(在5V,4MHz振盪頻率時工作電流小於2mA)。為進一步降低功耗,在保證滿
足工作要求的前提下,可採用降低工作頻率的方法,工作頻率的下降可大大降低功耗(如PIC16C
××在3V,32kHz下工作,其電流可減小到15μA),但較低的工作頻率可能導致部分子程式(如
數學計算)需佔用較多的時間。在這種情況下,當微控制器的振盪方式採用RC電路形式時,可以採
用中途提高工作頻率的辦法來解決。 具體做法是在閒置的一個
I/O腳(如RB1)和OSC1管腳之間跨接一電阻(R1),如圖1所示。低速狀態置RB1=0。需進行快速
運算時先置RB1=1,由於充電時,電容電壓上升得快,工作頻率增高,運算時間減少,運算結束又
置RB1=0,進入低速、低功耗狀態。工作頻率的變化量依R1的阻值而定(注意R1不能選得太小,
以防振盪電路不起振,一般選取大於5kΩ)。

改用C8051Fxxx,20MHz 僅僅10mA,若降到1MHz,可以做到1~2mA;
2. 或是乾脆採用MSP430,一般<1mA,稍稍採取措施,馬上可以接近零功耗!

大家不要以為更換CPU是很難的事情,我們僅僅用2周就更換成功CPU
先天不足,51低功耗沒前途的
msp430,m16等有很多低功耗微控制器,功能強,又是精簡指令,全天uA級工作
成本也是關鍵,不一定非要低功耗器件。
我覺得要很好的利用微控制器的中斷和休眠功能,微控制器儘可能的處於休眠等待狀態,同時注意空
閒IO口的狀態,輸出的最好置低,輸入的要視外圍電路而定,不用的腳要處理好,不是簡單不接
就可以的
另外,外圍電路可以做分割槽域的電源開關,不用時,關閉電源,並將與其相連的微控制器的IO口置
低,減少訊號線饋電。
不知說的對不對。
剛開始做電池產品時,只有8031 ,考慮用PSEN什麼的控制外部RAM,休眠方式,但是還是在十毫
安級. 現在好了,有許多型號微控制器本身就是低功耗,為了減少體積,還要追求更低. 1.系統
設計,好的系統設計是降低功耗的關鍵. 減少外圍器件,降低晶體頻率.可以採用帶lcd,ad,實時
時鐘功能的微控制器,即降低成本,又減少了故障率,可謂一舉兩得.HOLTEL,PHILIPS,PIC 都有此類
微控制器. 低的主頻也可以降低功耗,如ZILOG的微控制器可以程式控制對主頻的分頻,在不忙時把
頻率降低,需要時在提高. HOLTEK的可以採用雙頻率工作,高主頻可以關閉,32768可以提供內部精
確計時,還可以啟用休眠的微控制器工作. 2.降低系統電壓,可以降低功耗. 3.合理處理不用
的IO口,最好設為輸入態.對外圍電路也要考慮,如光耦,儘量使其導通態<斷開態.驅動三極體的狀
態.還有就是上拉,下拉電阻值,太小也會造成漏電.

Mega8的一個特點是帶有內部的RC振盪器,別小看他,他與晶振的不同之處在於他的起振時間很
短,只要幾uS,而晶振一般要幾十mS,所以低功耗設計時一定要用,430的宣傳不是也講起動時
間6uS嗎,那一樣是指的RC振盪開始工作的時間。
我得設計靜態電流50uA,實際只是LCD模組的電流,微控制器平時處在掉電的狀態。每隔1S倍液晶
模組喚醒一次,作一次顯示的重新整理工作,耗時約4mS,正常工作時如果有脈衝來的話,就作一些運
算,脈衝頻率50Hz,每次運算不過200uS,這樣下來,正極的功耗大大降低,加上一些外圍電
路,平均在100uA以下。

低功耗設計

現象一:我們這系統是220V供電,就不用在乎功耗問題了
點評:低功耗設計並不僅僅是為了省電,更多的好處在於降低了電源模組及散熱系統的成
本、由於電流的減小也減少了電磁輻射和熱噪聲的干擾。隨著裝置溫度的降低,器件壽命則
相應延長(半導體器件的工作溫度每提高10度,壽命則縮短一半)

現象二:這些匯流排訊號都用電阻拉一下,感覺放心些
點評:訊號需要上下拉的原因很多,但也不是個個都要拉。上下拉電阻拉一個單純的輸入信
號,電流也就幾十微安以下,但拉一個被驅動了的訊號,其電流將達毫安級,現在的系統常
常是地址資料各32位,可能還有244/245隔離後的匯流排及其它訊號,都上拉的話,幾瓦的功
耗就耗在這些電阻上了(不要用8毛錢一度電的觀念來對待這幾瓦的功耗)。

現象三:CPU和FPGA的這些不用的I/O口怎麼處理呢?先讓它空著吧,以後再說
點評:不用的I/O口如果懸空的話,受外界的一點點干擾就可能成為反覆振盪的輸入訊號
了,而MOS器件的功耗基本取決於閘電路的翻轉次數。如果把它上拉的話,每個引腳也會有
微安級的電流,所以最好的辦法是設成輸出(當然外面不能接其它有驅動的訊號)

現象四:這款FPGA還剩這麼多門用不完,可盡情發揮吧
點評:FGPA的功耗與被使用的觸發器數量及其翻轉次數成正比,所以同一型號的FPGA在不同
電路不同時刻的功耗可能相差100倍。儘量減少高速翻轉的觸發器數量是降低FPGA功耗的根
本方法。

現象五:這些小晶片的功耗都很低,不用考慮
點評:對於內部不太複雜的晶片功耗是很難確定的,它主要由引腳上的電流確定,一個
ABT16244,沒有負載的話耗電大概不到1毫安,但它的指標是每個腳可驅動60毫安的負載
(如匹配幾十歐姆的電阻),即滿負荷的功耗最大可達60*16=960mA,當然只是電源電流這
麼大,熱量都落到負載身上了。

現象六:儲存器有這麼多控制訊號,我這塊板子只需要用OE和WE訊號就可以了,片選就接地
吧,這樣讀操作時資料出來得快多了。
點評:大部分儲存器的功耗在片選有效時(不論OE和WE如何)將比片選無效時大100倍以
上,所以應儘可能使用CS來控制晶片,並且在滿足其它要求的情況下儘可能縮短片選脈衝的
寬度。

現象七:這些訊號怎麼都有過沖啊?只要匹配得好,就可消除了
點評:除了少數特定訊號外(如100BASE-T、CML),都是有過沖的,只要不是很大,並不一
定都需要匹配,即使匹配也並非要匹配得最好。象TTL的輸出阻抗不到50歐姆,有的甚至20
歐姆,如果也用這麼大的匹配電阻的話,那電流就非常大了,功耗是無法接受的,另外訊號
幅度也將小得不能用,再說一般訊號在輸出高電平和輸出低電平時的輸出阻抗並不相同,也
沒辦法做到完全匹配。所以對TTL、LVDS、422等訊號的匹配只要做到過沖可以接受即可。

現象八:降低功耗都是硬體人員的事,與軟體沒關係
點評:硬體只是搭個舞臺,唱戲的卻是軟體,總線上幾乎每一個晶片的訪問、每一個訊號的
翻轉差不多都由軟體控制的,如果軟體能減少外存的訪問次數(多使用暫存器變數、多使用
內部CACHE等)、及時響應中斷(中斷往往是低電平有效並帶有上拉電阻)及其它爭對具體
單板的特定措施都將對降低功耗作出很大的貢獻。