對于手持式、便攜式等移動設備來講,為了讓設備有更長的待機和工作時間,系統必需具備完善的電源管理功能。英創公司針對手持式、電池供電設備應用而推出的嵌入式核心主板EM9283,預裝了Windows CE6.0操作系統,提供了完善的電源管理支持。在與EM9283配套的通用開發評估底板上測得的EM9283在各個電源狀態下的功耗指標為:
? 系統正常運行:110mA
? 系統掛起:8mA。通過PSwitch鍵,可在1S內恢復到正常運行狀態
? 系統關機:<15uA。系統僅維持實時時鐘的供電,系統重新啟動時間小于10S
本文將以EM9283為例,介紹用戶應用程序如何實現電源管理,以減少整機功耗,延長設備工作時間。在這之前,有必要先對Windows CE系統的電源管理功能做一個了解。所以我們將先介紹WinCE系統的電源狀態,然后是設備的電源狀態,接著才是應用程序電源管理。文檔的最后是一個實際的電源管理例子:LCD背光的電源管理。
1、系統電源狀態
上面提到了EM9283的運行,掛起和關機三種直觀電源狀態下的功耗指示,而至Windows CE.NET 4.2版本以后的系統具有的高級電源管理組件:WinCE電源管理器,為系統定義的電源狀態如表1:
系統電源狀態 | 簡要描述 |
On | 用戶與系統交互的常規運行狀態 |
UserIdle | 用戶與設備停止交互,但仍可能使用設備 |
SystemIdle | 經過一段時間UserIdle后進入此狀態,但驅動和系統仍然活動 |
SystemIdle | 掛起狀態,系統大部分外設關閉,僅RAM外于自刷新狀態 |
WinCE電源管理器維護了一個監控用戶活動的定時器,通過監控這個定時器的超時來使系統進入用戶空閑模式、系統空閑模式,最終掛起系統。基本的電源管理功能所采用的節能方法是使系統適時的進入掛起狀態,此時系統RAM處于自刷新狀態,整機功耗降到了較
低的水平,同時又能快速恢復到正常運行狀態。下面的幾種方法都可以讓系統進入Suspend狀態:
1、監控的用戶活動定時器超時。通過控制面板里的電源屬性項設置超時時間。如圖1
圖1中設置的意圖是:在電池供電情況下,當用戶停止操作1分鐘后,系統電源管理器將控制系統進入用戶空閑模式,如果2分鐘后用戶仍然沒有操作,系統進入系統空閑狀態,系統空閑3分鐘后還是沒有用戶操作,系統掛起。
在用戶的最終產品中,由于種種原因,可能不能通過控制面板來直接設置系統超時,或者用戶希望自己設計設置系統超時的界面,此時用戶應用程序可以通過修改系統注冊表來實現與通過控制面板設置一樣的功能。具體的做法是修改[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Power\Timeouts]下面的超時時間。通過控制面板設置后的注冊表如圖2所示。
可以看到,在注冊中超時時間的單位是秒。應用程序要利用系統的電源管理器,除了在控制面板中做了上述設置外,還需要在應用程序啟動時設置系統的'PowerManager/ReloadActivityTimeouts'自動事件為有信號狀態,電源管理器才會正常工作。當在應用程序中直接修改了對應的Timeouts注冊表項后,也需要打開(或創建)'PowerManager/ReloadActivityTimeouts'的自動重置事件,并SetEvent置這個事件為有信號狀態,這樣可以使電源管理器再次從注冊表中讀取狀態切換定時器的設置。
HANDLE hReloadActivityTimeouts;
hReloadActivityTimeouts = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T('PowerManager/ReloadActivityTimeouts'));
if(hReloadActivityTimeouts)
{
SetEvent(hReloadActivityTimeouts);
CloseHandle(hReloadActivityTimeouts);
}
2、應用程序調用API。除了通過超時讓系統自動進入掛起狀態外,應用程序還可以調用API函數讓系統掛起:SetSystemPowerState(NULL,POWER_STATE_SUSPEND,0);
3、EM9283提供了一鍵開關機PSwitch鍵。所以最直接的方法是通過PSwitch按鍵讓系統在掛起狀態和運行狀態之間切換。
通過上面的三種方法讓可以讓系統掛起,而當下面的一種事件發生時,系統將退出掛起狀態:
1、用戶再次按下PSwitch鍵。
2、發生某個警告事件,如時間定時器到時提醒。
3、發生某個喚醒事件。
2、設備電源狀態
雖然通過用戶操作、應用程序或者外設都可以使系統進入或退出掛起狀態,但基本的電源管理功能所能控制的粒度過大,整個系統只有三種狀態,On,Idle和Suspend,對應于所有外設只有On和Suspend兩種狀態。加入了電源管理組件的Windows CE具有高級的電源管理功能,它允許每個外設具有自己的電源狀態——設備電源狀態。應用程序有能力單獨設置外設的電源狀態,比如在保持串口通訊時,關閉顯示和背光。Wince通常對設備電源狀態的描述如表2:
設備電源狀態 | 注冊表鍵值 | 描述 |
Full on | D0 | 此狀態表示設備已開啟或正在運行,設備將以系統允許的最在功耗及最高性能運行 |
Low on | D1 | 此狀態表示設備已開啟或正在運行,但以低于D0狀態的功耗及性能運行。D1狀態適用于設備已經被使用,但以較低的性能運行即可 |
Standby | D2 | 此狀態表示設備被部份供電 |
Sleep | D3 | 睡眠狀態。保證喚醒的最小供電,在需要時能自動喚醒并初始化 |
off | D4 | 關閉狀態,不供電 |
物理設備并不需要支持上面所有的設備電源狀態,但所有設備必需要支持D0電源狀態,EM9283上的各種外設,如背光、顯示等至少支持D0和D4兩種狀態,也就是說應用程序在能力決定是否單獨給某個設備供電,以盡可能降低整機功耗。
3、應用程序電源管理
上面所提的系統電源狀態和設備電源狀態都是系統或驅動一級對電源管理的支持,對使用英創公司工控主板的用戶來講,這些功能都是由英創公司直接提供并維護的,用戶如果知道如何利用系統提供的這些功能,就能輕松實現適用于自己設備的電源管理策略。
電源管理器提供了一組接口供應用程序參與到電源管理的活動中,應用程序可以通過RequestPowerNotifications函數請求電源管理器向其發送電源相關的通知,也可以通過SetPowerRequirement通知電源管理器將設備設置在特殊的電源狀態下。這樣,指定設備的電源狀態就不會隨系統電源狀態的改變而改變。
3.1 電源通知機制
電源相關的通知通過消息隊列傳遞給應用程序,通常應用程序新建一個消息隊列,并通過RequestPowerNotifications將這個消息隊列的句柄傳遞給電源管理器,同時創建一個線程偵聽來自這個隊列的消息。電源管理器定義了如下幾種通知:
? PBT_RESUME:當系統從休眠狀態被喚醒是產生;
? PBT_POWERSTATUSCHANGE:當系統接入或者斷開外部電源時產生;
? PBT_TRANSITION:當電源管理器執行系統電源狀態轉換時發生;
? PBT_POWERINFOCHANGE:當電池信息更新時發生。
下面的代碼演示了應用程序如何偵聽電源管理器發出的通知。
// 1.新建一個消息隊列
ghPowerNotifications= CreateMsgQueue(NULL, &msgOptions);
if (!ghPowerNotifications) {
DWORD dwErr = GetLastError();
RETAILMSG(1, (TEXT('%s:CreateMessageQueue ERROR:%d\n'), pszFname, dwErr));
goto _Exit;
}
// 2.請求得到電源通知
hNotifications = RequestPowerNotifications(ghPowerNotifications, POWER_NOTIFY_ALL);
if (!hNotifications) {
DWORD dwErr = GetLastError();
RETAILMSG(TRUE, (TEXT('%s:RequestPowerNotifications ERROR:%d\n'), pszFname, dwErr));
goto _Exit;
}
// 3.創建偵聽線程
ht = CreateThread(NULL, 0, ProcessPowerNotification, NULL, 0, NULL);
// 4.電源通知消息偵聽線程
void ProcessPowerNotification(HANDLE hMsgQ)
{
……
if (ReadMsgQueue(hMsgQ, buf, QUEUE_SIZE, (LPDWORD)&dwSize, 0, &dwStatus))
{……} // 5.電源通知消息處理
3.2 電源請求機制
電源請求機制為應用程序提供了強大的能力控制電源管理器調整設備的電源等級,與其他所有的電源設置相比,它具有很高的優先級。舉例來說,假設有一個條形碼閱讀器連接在COM3端口,并且COM3只有在最高電源等級(D0)時才能驅動這個條形碼閱讀器。為了使其正常工作,應用程序將調用SetPowerRequirement把COM3指定為D0狀態。假設之后串口驅動自身決定降低一個電源等級,驅動程序調用DevicePowerNotify通知電源管理器它期望的設備電源狀態D1,實際上驅動程序的這個請求將不起作用,直到應用程序調用ReleasePowerRequirement為止。繼續這個例子,假設這時的系統電源狀態轉換為低能耗等級,雖然與系統電源狀態對應的COM3電源等級為D2,由于應用程序的電源請求,COM3仍將繼續維持在D0狀態。
在調用SetPowerRequirement函數時,指定POWER_FORCE標志將強制設備不進入休眠狀態,即使這時系統已處于休眠狀態。
3.3 設置電源狀態
在某些應用的場合下,應用程序可能需要改變系統的電源狀態。 應用程序可以通過GetSystemPowerState返回當前系統電源狀態的名稱,也可以通過SetSystemPowerState改變系統的電源狀態。同樣的,如果應用程序需要改變某個設備的電源狀態,可以通過GetDevicePower返回設備當前的電源狀態,也可以通過SetDevicePower改變設備的電源狀態。
4、電源管理實例——LCD背光控制
上面依次描述了系統電源狀態,設備電源狀態以及電源管理器的應用程序接口,但對于沒有此類經驗的用戶來講,可能仍不清楚如何在自己的設備中實現所謂的電源管理,本節將以控制LCD背光為例,介紹實現對背光進行電源管理的方法。
4.1 背光控制方法一
對背光的電源控制有很多方法,設備電源狀態的定義是在驅動程序中實現的,電源管理器通過DeviceIoCtrol與設備驅動程序交互,實現對設備的電源管理,同樣,應用程序也可以通過DeviceIoCtrol實現對設備電源直接的控制。
// 1.打開背光句柄
HANDLE hBLK = CreateFile(L'BKL1:', // name of device
GENERIC_READ|GENERIC_WRITE, // desired access
FILE_SHARE_READ|FILE_SHARE_WRITE, // sharing mode
NULL, // security attributes (ignored)
OPEN_EXISTING, // creation disposition
FILE_FLAG_RANDOM_ACCESS, // flags/attributes
NULL);
// 2.通過DeviceIoCtrol關閉LCD背光
CEDEVICE_POWER_STATE stPower;
stPower = D4;
DWORD dwReturn;
bResult = DeviceIoControl(hBLK,
IOCTL_POWER_SET,
NULL,
0,
& stPower,
sizeof(CEDEVICE_POWER_STATE),
&dwReturn,
NULL);
// 3.通過DeviceIoCtrol打開LCD背光
stPower = D0;
bResult = DeviceIoControl(hBLK,
IOCTL_POWER_SET,
NULL,
0,
& stPower,
sizeof(CEDEVICE_POWER_STATE),
&dwReturn,
NULL);
4.2 背光控制方法二
方法一僅適用于系統沒有電源管理器的情況下使用,如果使能了系統的電源管理功能,則應禁止使用上面的方法來控制背光。用戶可以將第2節提到的設備電源狀態和第1節的系統電源狀態做一個映射,當系統在不同的電源狀態間切換時,設備電源狀態隨之改變。系統電源狀態與設備電源狀態的映射是通過系統注冊表來實現的。如用戶希望在系統On狀態時,背光最亮,系統電源狀態切換到UserIdel時,背光變暗一點,系統處于SystemIdel和Suspend時,背光滅,則注冊表配置如下:
[HKEY_LOCAL_MACHINE\System\ CurrentControlSet \Power\State\On]
“Default” =dword:0 ;D0 當系統為On狀態時,所有設備默認在D0狀態
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Power\State\UserIdle]
“Default” =dword:1 ;D1所有設備默認在D1狀態,包括LCD背光
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Power\State\SystemIdle]
“Default” =dword:0 ;D2所有設備默認在D2狀態
“bkl1:”=dword:4 ;D4 背光處于D4關閉狀態
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Power\State\Suspend]
“Default” =dword:3 ;D3所有設備默認在D3狀態,如果設備不支持D3,自動進入D4狀態
上面的第1、2、4條注冊表使用的是系統默認值,所以實際上只需要在SystemIdle狀態下增加一項就可以了,如圖3:
這里必需使用小寫字母的設備名稱,電源管理器才能識別。注冊表設置好后,用戶再通過控制面板\電源屬性設置好系統超時,背光就能隨系統電源狀態的變化而自動切換了。
如果系統使能了電源管理器,而應用程序又想直接修改背光的電源狀態應該怎樣做呢?
首先肯定不能使用DeviceIoCtrol的方法,也不推薦使用SetDevicePower函數,而應調用較為溫和的DevicePowerNotify。DevicePowerNotify會與系統電源管理器商量改變背光的電源狀態,電源管理器最終決定并實施背光狀態的改變。
4.3 背光控制方法三
實際上,在手持設備或便攜式等移動設備中,背光功耗在整個設備功耗中占很大一部份,對背光電源的靈活控制十分必要,EM9283的控制面板\顯示屬性中有專門對背光進行管理的選項,如圖4。
背景光的高級選項可以分別設置EM9283在電池供電或適配器供電情況下LCD背光的亮度,如圖5。EM9283 LCD背光的亮度調節范圍是5%~100%。
與通過控制面板設置系統超時一樣,如果應用程序希望直接設置背光的點亮時間和背光亮度,可以通過修改注冊表來實現。與圖4,圖5對應的注冊表設置如下:
[HKEY_CURRENT_USER\ControlPanel\BackLight]
“UserExt” =dword:1 ;允許在適配器供電情況下對背光進行控制
“UseBattery:”=dword:1 ;允許在電池供電情況下對背光進行控制
“ACTimeout”=dword:60 ;適配器供電情況下用戶停止操作60秒后關閉背光
“BatteryTimout”=dword:15 ;電池供電情況下用戶停止操作15秒后關閉背光
如果應用程序修改了背光亮度相關的注冊表項,需要創建名為BackLightLevelChangeEvent的事件,并置為有信號狀態,相應的驅動程序就會自動更新剛剛的設置,使設置生效。
Handel hBackLightLevelChange=
CreateEvent(NULL, FALSE, FALSE, L'BackLightLevelChangeEvent' );
SetEvent(hBackLightLevelChange);
同樣,如果應用程序修改了背光點亮時間,需要創建名為BackLightChangeEvent的事件,并置為有信號狀態使設置生效。
Handel hBackLightChange=
CreateEvent(NULL, FALSE, FALSE, L'BackLightChangeEvent' ) ;
SetEvent(hBackLightChange);
在控制面板系統電源屬性設置和背景光設置中,都講到當用戶停止操作某某長時間后,系統會怎樣怎樣。Windows CE和桌面Windows系統一樣,將沒有鼠標和鍵盤輸入定義為用戶停止操作,但用戶停止操作并不意味著用戶已經停止使用設備。比如用戶正打開一個串口,查看串口收到的數據,查看過程中用戶沒有使用鍵盤,也沒有移動鼠標,系統認為用戶已經停止操作設備,并在一段時間后關閉了LCD背光,顯示這不是用戶所希望的。在這種情況下,用戶只能周期性的移動鼠標或使用一下鍵盤來提醒設備,我還在使用你。
如果應用程序能夠確定當自己被打開時,用戶需要屏幕和背光一直點亮(比如動畫播放程序),那么應用程序可以自己來提醒操作系統的電源管理:用戶還在使用設備,而不需要用戶去頻繁的移動鼠標。應用程序可以創建或打開名為PowerManager/ActivityTimer/UserActivity事件,并以合適的時間,周期性的置這個事件有信號來達到提供電源管理器的目的。
Handle hUserActivity = OpenEvent( EVENT_ALL_ACCESS ,
FALSE,
L'PowerManager/ActivityTimer/UserActivity');
SetEvent( hUserActivity );
背光控制的方法三,對用戶來講是獨立于電源管理器的,也就是說無論用戶是否通過控制面板使能了系統電源超時切換功能,都可以通過此方法單獨控制系統背景光。
5、電源管理實例——系統屏保
上述三種方法能實現對系統背光的靈活控制,當系統關閉背光時,EM9283會將背光控制引腳LCD_BKLIGHT置低,控制外部電路關閉背光,但實際上這時候EM9283的顯示信號仍在輸出,如果EM9283外接的是VGA顯示或其它獨立背光的顯示設備,就會看到顯示界面,而我們所期望的是系統空閑一段時間后,LCD屏的背光和顯示都關閉,即通常說的屏保。
以VGA顯示器為例,當沒有檢測到輸入信號時,顯示器會自動關閉背光并進入低功耗模式,此時EM9283控制LCD_BKLIGHT是不行的,而需要將輸出的顯示信號關閉,我們同樣可以利用WinCE的電源管理器來實現屏保功能。比如讓系統空閑10分鐘后屏保的設置如下:
設備系統10分鐘后關閉顯示器
系統空閑10分鐘后會關閉背光和顯示輸出,控制原理已經在第1節中進行了描述,同時需要注意對系統事件'PowerManager/ReloadActivityTimeouts'進行合適的設置,屏保功能才會正常啟用。
6、結束語
本文主要從應用的角度出發,結合英創工控主板EM9283,介紹了WinCE系統電源管理的實現過程。從背光的電源管理可以看到,有多種方法對系統設備的電源進行控制管理,但應該注意,盡量避免使用不同的方法同時管理一個設備的電源,以免造成用戶甚至應用程序開發者本身的混亂。
本文中涉及到的API函數、事件、注冊表等,用戶可以參考微軟的MSDN,對Windows CE電源管理更全面、更權威的描述,也請參考MSDN。對于文中使用的程序片段,感興趣的用戶可以聯系英創索要完整的測試代碼。
-
WINDOWS
+關注
關注
3文章
3524瀏覽量
88437 -
嵌入式主板
+關注
關注
7文章
6085瀏覽量
35218
發布評論請先 登錄
相關推薦
評論