省電力モードの目的は、消費電力を削減することで、このモードには、Dozeモードと Sleepモードと Idleモードがあります。
Dozeイネーブル(DOZEN)ビットがセットされている場合(DOZEN = 1)、CPUは、DOZE モードになります。
CPUDOZEレジスタのアイドルイネーブル(IDLEN)ビットがクリア(IDLEN = 0)状態で、SLEEP命令を実行すると SLEEP モードになります。IDLENビットがセット(IDLEN = 1)状態で、SLEEP命令が実行されると、CPUは IDLE モードになります。
Dozeモードでは、周辺機器の動作に影響を与えることなく、CPU動作とプログラムメモリアクセスを削減することにより、電力を節約できます。Dozeモードは SLEEP モードとは異なり、システムオシレータは引き続き動作しますが、CPUとプログラムメモリのみが影響を受けます。命令実行の削減により、CPUとメモリ内の不要な動作が排除され、電力が節約されます。
Dozeイネーブル(DOZEN)ビットがセットされている場合(DOZEN = 1)、CPUは、CPUDOZEレジスタのDOZE <2:0>ビットで定義されているNサイクルごとに1命令サイクルのみ実行します。たとえば、DOZE <2:0> = 100の場合、命令サイクル比は1:32です。CPUとメモリは1命令サイクル実行すると、その後の31命令サイクルはアイドル状態になります。アイドルサイクル中でも、ペリフェラルはシステムクロック速度で動作し続けます。
割り込みが発生し、割り込み時にRecover-on-Interrupt(ROI)ビットがクリアされている(ROI = 0)場合、割り込みサービスルーチン(ISR)はDOZE <2:0>で選択されたレートで実行を継続します。 割り込みレイテンシ(遅延)は、DOZE <2:0>比率で延長となります。
割り込みが発生し、割り込み時にROIビットがセットされている場合(ROI = 1)、DOZENビットはクリアされ、CPUはフルスピードで実行されます。プリフェッチされた命令が実行された後、割り込みベクタシーケンスが実行されます。図8-1では、Doze期間の2番目の命令サイクル中に割り込みが発生し、すぐにCPUがDozeから抜け出します。Doze-on-Exit(DOE)ビットがセットされている(DOE = 1)場合、RETFIE動作の実行時にDOZENがセットされ、CPUはDOZE <2:0>比率に基づいて低減されたレートに戻り実行します。
CPUDOZEレジスタのアイドルイネーブル(IDLEN)ビットがクリア(IDLEN = 0)状態で、SLEEP命令を実行すると SLEEP モードになります。IDLENビットがセット(IDLEN = 1)状態で、SLEEP命令が実行されると、CPUは IDLE モードになります。
SLEEP モードでは、次の状態になります。
スリープ中の周辺機器動作の詳細については、個々の章を参照してください。
電流消費を最小限に抑えるには、次の項目を検討する必要があります。
ハイインピーダンス入力であるI/Oピンは、フローティング入力によって引き起こされるスイッチング電流を回避するために、外部でVDDまたはVSSに固定する必要があります。
電流が流れだす可能性のある内部回路には、DACやFVRモジュールなどが含まれます。これらのモジュールの詳細は、各セクションを参照してください。
デバイスは、次のいずれかのイベントによってスリープからウェイクアップできます。
最初の3つのイベントにより、デバイスはリセットされます。後の3つのイベントは、プログラム実行の継続と見なされます。デバイスのリセットまたはウェイクアップイベントが発生したかどうかを確認するには、セクション5.11「リセットの原因の特定」を参照してください。
SLEEP命令の実行中、次の命令(PC + 1)がプリフェッチされます。デバイスが割り込みイベントによってウェイクアップするには、対応する割り込みイネーブルビットを有効にする必要があります。ウェイクアップは、GIEビットの状態に関係なく発生します。
GIEビットが無効(GIE = 0)な場合、デバイスはSLEEP命令の後の命令で実行を継続します。
GIEビットが有効(GIE = 1)な場合、デバイスはSLEEP命令の直後の命令を実行し、デバイスは割り込みサービスルーチンを呼び出します。
重要:SLEEP命令の直後の命令の実行が望ましくない場合、ユーザーはSLEEP命令の直後に NOP を置く必要があります。
ウェイクアップのソースに関係なく、デバイスがスリープからウェイクアップすると、WDTはクリアされます。
グローバル割り込みが無効(GIE=0)で、クロックソース割り込みを除くすべての割り込みソースで、割り込み有効ビットと割り込みフラグビットの両方がセットされている場合、次のいずれかが発生します。
• SLEEP命令の実行前に割り込みが発生した場合
• SLEEP命令の実行中または実行後に割り込みが発生した場合
SLEEP命令を実行する前にフラグビットがチェックされた場合でも、SLEEP命令が完了する前にフラグビットがセットされる可能性があります。SLEEP命令が実行されたかどうかを判断するには、PDビットをテストします。PDビットがセットされている場合、SLEEP命令はNOPとして実行されました。
PIC16F18326/18346デバイスには内部低ドロップアウト(LDO)電圧レギュレータが含まれているため、デバイスのI/Oピンを最大5.5Vの電圧で動作させながら、内部デバイスロジックをより低い電圧で動作させることができます。LDOとそれに関連するリファレンス回路は、デバイスが SLEEP モードのときもアクティブのままである必要があります。
PIC16F18326/18346を使用すると、アプリケーションの要件に応じて、スリープ時の動作電流を最適化できます。
低電力 SLEEP モードは、VREGCONレジスタのVREGPMビットをセットすることで選択できます。これらのビットの構成に応じて、デバイスがスリープ状態のとき、LDOとリファレンス回路は低電力状態になります。
デフォルトの動作モードでは、LDOとリファレンス回路は、スリープ中も通常の構成のままです。すべての回路がアクティブなままであるため、デバイスは SLEEP モードをすばやく終了できます。低電力 SLEEP モードでは、スリープからウェイクアップするときに、これらの回路が通常の構成に戻って安定するまでに追加の遅延時間が必要です。
低電力 SLEEP モードは、長期間 SLEEP モードに留まるアプリケーションに役立ちます。ノーマルモードは、スリープからすばやく頻繁にウェイクアップする必要があるアプリケーションに役立ちます。
SLEEP モードで動作できる周辺機器の中には、低電力 SLEEP モードが選択されていると正しく動作しないものがあります。低電力 SLEEP モードは、次の周辺機器での使用を目的としています。
VREGPMの設定は、スリープ状態での動作を保証しアプリケーションで許容できるかを考慮し、エンドユーザーの責任で実施してください。
アイドルイネーブル(IDLEN)ビットがクリアされている場合(IDLEN = 0)、SLEEP命令はデバイスをフル SLEEP モードにします(セクション8.2「SLEEP モード」を参照)。IDLENがセットされている場合(IDLEN = 1)、SLEEP命令はデバイスを IDLE モードにします。 IDLE モードでは、CPUとメモリの動作は停止しますが、周辺クロックは動作し続けます。このモードはDozeモードに似ていますが、IDLEではCPUとプログラムメモリの両方が遮断される点が異なります。
注意:FOSCを使用するペリフェラルは、アイドル状態(スリープ状態ではない)でも動作し続けます。
注意:CLKOUTが有効(CLKOUT = 0、Configuration Word 1)の場合、クロックはアイドル中も出力し続けます。
割り込みが発生すると(GIE = 0であっても)、 Idle モードは終了しますが、IDLENは変更されません。デバイスは、SLEEP命令を実行することでIDLEに再び入ることができます。
Recover-on-Interruptが有効になっている場合(ROI = 1)、DOZEも有効になっている場合、デバイスをアイドル状態から戻す割り込みにより、CPUのフルスピード実行が復元されます。
アイドル状態のとき、WDTリセットはブロックされ、代わりにデバイスをウェイクアップします。WDTウェイクアップは割り込みではないため、ROIは適用されません。
注意:WDTは、デバイスをスリープから復帰させるのと同じ方法で、デバイスをアイドルから復帰させることができます。DOZENビットは影響を受けません。
レジスタ | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
---|---|---|---|---|---|---|---|---|
VREGCON | - | - | - | - | - | - | VREGPM | Reserved |
CPUDOZE | IDLEN | DOZEN | ROI | DOE | - | DOZE<2:0> |
レジスタ | BIT | 名 | 説明 | 1 | 0 | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
VREGCON | 1 | VREGPM | 低電力 SLEEP モード ON/OFF | 低電力 | 通常 | |||||||
0 | Reserved | 未使用 常にセットすること | 1 | - | ||||||||
CPUDOZE | 7 | IDLEN | Idle / Sleep 選択 | IDLE | SLEEP | |||||||
6 | DOZEN | Dozeモード選択 | Doze | 通常 | ||||||||
5 | ROI | Interrupt(ISR)でのDoze動作 | Doze | 通常 | ||||||||
4 | DOE | 復帰時のDozs | Doze | 変更なし | ||||||||
2 | DOZE2 | Doze動作時の間引き比率
|
||||||||||
1 | IDLEN1 | |||||||||||
0 | IDLEN0 |
<回路図>
SLEEP状態をTimer1またはPushSWでウェイクアップするプログラムです。
Timer1は LFINTOSC 31KHz を入力し4秒後にカウントアップします。カウントアップでSLEEPからウェイクアップし、LED4を短く点滅し再びSLEEPに入ります。
SWを押すとその立ち下がり信号で、SLEEPからウェイクアップし、LED7を短く点滅し、SWが話されるのを待て再びSLEEPに入ります。
<プログラム>
/************************************* * File: main.c * SLEEP状態から、Timer1またはPushSW * からの信号でウェイクアップする * 1MHz (内部クロック) * RA4 LED4 * RC5 LED7 * RC4 PushSW * PIC16F18346 MPLAB XC8 v2.10 * Created on June 22, 2020, 2:37 PM **************************************/ #include#define _XTAL_FREQ 1000000 // delay_ms(x) のための定義 #define LED4 LATA5 #define LED7 LATC5 #define SW RC4 #pragma config FEXTOSC = OFF,RSTOSC = HFINT1 // HFINTOSC (1MHz) #pragma config CLKOUTEN = OFF,CSWEN = OFF,FCMEN = OFF #pragma config MCLRE = ON,PWRTE = OFF,WDTE = OFF,LPBOREN = OFF #pragma config BOREN = OFF,BORV = LOW,PPS1WAY = OFF,STVREN = ON #pragma config DEBUG = OFF #pragma config WRT = OFF,LVP = ON,CP = OFF,CPD = OFF // ******************************************************** void main() { TRISA5 = 0; // LED4 出力 TRISC5 = 0; // LED7 出力 TRISC4 = 1; // SW(RC4) 入力 ANSC4 = 0; // SW(RC4) デジタル INTPPS = 0x14; // SW(RC4) interrupu pinに指定 T1CON = 0b11010101; // LFINTosc Sync PreS 1/2 4sec T1GCON = 0; // ゲート機能は使用せず TMR1 = 0; // Timerクリア TMR1IF=0; // Timer1割込みフラッグクリア INTEDG = 0; // 立ち下がりで割込み INTF = 0; // Pin割込みフラッグクリア INTE = 1; // Pin割込み許可 TMR1IE = 1; // Timer1割込み許可 PEIE = 1; // ペリフェラル割込み許可 while(1){ // ----- SLEEP状態にする ------------------ SLEEP(); NOP(); // ----- ウェイクアップ -------------------- if(TMR1IF){ // Timer1カウントアップなら TMR1IF=0; // Timer1割込みフラッグクリア LED4 = 1; // LED4を短く点滅 __delay_ms(20); LED4 = 0; } if(INTF){ // SWが押されたなら LED7 = 1; // LED7を短く点滅 __delay_ms(20); LED7 = 0; while(!SW); // SWが離れるのを待つ __delay_ms(10); // チャタリング防止 INTF = 0; // Pin割込みフラグクリア } } }