|
1. 上層と下層の接続 この記事では、CC2430の睡眠機能と起床方法について解説します。 実際の使用では、CC2430ノードは一般的にバッテリーで駆動されるため、消費電力の制御が極めて重要です。 以下はCC2430の4つの消費電力モード導入に関するCC2430中国語マニュアルからの抜粋です。
上の表からもわかるように、CC2430には合計4つの電源モードがあります。PM0(完全に目が覚めている)、PM1(少し眠そうに)、PM2(半分目が覚めていて半分眠っている)、PM3(ぐっすり眠っている) 下に行けば下がるほど、多くの機能がオフになり、消費電力はどんどん低くなります。 それらの変換関係は以下の通りです。
プットPM1、PM2起きてくださいPM0、方法は3つあります:リセット、外部中断、スリープタイマー中断; しかし、PM3起きてくださいPM0方法は2つしかありません:リセット、外部割り込み(これはPM3すべての発振器が動かなくなり、もちろんスリープタイマーもオフになりました~) スリープモードに入る方法と起き方を紹介する小さな実験を始めましょうPM0州。 2. 体系的な睡眠と中断した覚醒実験(1) 実験への導入システム初期化、PM0
→ 入るPM1
→ 1秒後にスリープタイマーで起きるPM0
→ 入るPM2
→2秒後にスリープタイマーで目を覚ましたPM0
→ 入るPM3
→ キーS1が押されて外部割り込みが起動し、起動するのを待ちますPM0
(2) プログラムフローチャート
(注:上の画像の丸みを帯びたボックスはシステムの健康状態を示しています)
(3) 実験的なソースコードと解析(以下のボックスをクリックしてください~)ヘッダーファイルとマクロ定義[url=]
[/url]
/* 実験的説明:3つの睡眠モードで覚醒を導入する中断型覚醒睡眠実験
*/
#include #define LED_ON 0 #define LED_OFF 1#defineLED1 P1_0
#defineLED2 P1_1
#defineLED3 P1_2
#defineLED4 P1_3 [url=][/url]
部分機能[url=][/url]
/*システムクロックの初期化 -------------------------------------------------------*/
虚無xtal_init(虚無)
{ 眠り &= ~0x04; //すべて動力付きです
ただし(! (眠りと0x40)); //クリスタルオシレーターはオンで安定しています
CLKCON &= ~0x47; //32MHzのクリスタルオシレーターを選びましょう
眠り |=0x04;
}
/*LEDの初期化 -------------------------------------------------------*/
虚無led_init(虚無)
{ P1SEL =0x00; //P1は通常のI/Oポートです
P1DIR |=0x0F; //P1.0 P1.1 P1.2 P1.3 出力
LED1 = LED_OFF; //すべてのLEDを消してください
led2 = LED_OFF; led3 = LED_OFF; led4 = LED_OFF;
}
/*外部割り込み初期化 -------------------------------------------------------*/
虚無io_init(虚無)
{ P0INP &= ~0X02; //P0.1にはプルアップとプルダウンがあります
EA =1; //完全な中断が許される
IEN1 |= 0X20; //P0IE = 1、P0割り込みが有効化
PICTL |= 0X09; //P0.1は割り込みやドロップエッジトリガーを許可しています
P0IFG &= ~0x02; //P0.1 割り込みマーククリア0
}
/*スリープタイマー割り込み初期化 -------------------------------------------------------*/
虚無sleepTimer_init(虚無)
{ STIF=0; //スリープタイマーの割り込みマークはクリア0です
STIE=1; //スリープタイマーを起動する 中断
EA=1; //完全な中断を開けろ
}
/*スリープタイマーの予定された間隔を設定してください -------------------------------------------------------*/
虚無setSleepTimer(unsign)知力SEC)
{ 署名なし長いsleepTimer =0;
sleepTimer |= ST0; //現在のスリープタイマーのカウント値を取得してください
sleepTimer |= (署名なし)長い)ST1 <<8; sleepTimer |= (署名なし)長い)ST2 <<16;
sleepTimer += ((符号なし)長い)sec *(署名なし)長い)32768); //さらに、必要なタイミング時間も必要です
ST2 = (符号なし)チャー(睡眠タイマー>>16); //スリープタイマーの比較値を設定します
ST1 = (符号なし)チャー(睡眠タイマー>>8); ST0 = (符号なし)チャー)sleepTimer;
}
/*パワーモードを選択してください -------------------------------------------------------*/
虚無PowerMode(符号なし)チャーモード)
{
もし(モード<4) { 眠り &=0xfc; //SLEEP.MODEを0にクリアしてください
SLEEP |= モード; //パワーモードを選択してください
PCON |=0x01; //このパワーモードを有効にしてください
}
}
/*遅延関数 -------------------------------------------------------*/
虚無遅延(符号なし)知力n)
{ 署名なし知力i,j;
に対して(i=0; i<n; i++)
に対して(j=0; j<1000; j++);
}
[url=][/url]
主な機能[url=][/url]
/*主な機能 -------------------------------------------------------*/
虚無メイン(虚無)
{ xtal_init(); led_init();
//PM0の状態、点灯と遅延
led1 = LED_ON; //輝度LED1はシステムがPM0モードで動作していることを示します
遅延(10);
//PM1状態、照明消灯
setSleepTimer(1); //スリープタイマーの時間間隔を1に設定してください
sleepTimer_init(); //スリープタイマーを起動する 中断
LED1 = LED_OFF; パワーモード(1); //電源モードをPM1に設定してください
//1の後、PM1がPM0に入り、点灯して遅延します
led1 = LED_ON; 遅延(50);
//PM2、照明消去
setSleepTimer(2); //スリープタイマーの時間間隔を2秒に設定してください
LED1 = LED_OFF; パワーモード(2); //電源モードをPM2に設定してください
//2秒後にPM2がPM0に入り、点灯して遅延します
led1=0; 遅延(50);
//PM3、消灯
io_init(); //外部割り込みの初期化
LED1 = LED_OFF; パワーモード(3); //電源モードをPM3に設定してください
//外部の中断が発生すると、PM3はPM0に入り点灯します
led1 = LED_ON;
ただし(1);
}
[url=][/url]
割り込みサービス手順[url=][/url]
/*外部割り込みサービスプログラム -------------------------------------------------------*/
#pragmaベクトル = P0INT_VECTOR __interrupt虚無P0_ISR(虚無)
{ EA =0; //門が遮られた
遅延(50);
もし((P0IFG &0x02) >0) //鍵が中断される
{ P0IFG &= ~0x02; //P0.1 割り込みマーククリア0
} P0IF =0; //P0 割り込みマーク クリア0
EA =1; //オープン・インターセプション
}
/*スリープタイマーがサービスプログラムを中断します -------------------------------------------------------*/
#pragmaベクトル=ST_VECTOR __interrupt虚無sleepTimer_IRQ(虚無)
{ EA=0; //門が遮られた
STIF=0; //スリープタイマーの割り込みマークはクリア0です
EA=1; //オープン・インターセプション
}
[url=][/url]
スリープタイマーを使ってシステムを起動させる方法は、以下のようにまとめられます:スリープタイマー割り込みを開→スリープタイマーのタイミング間隔を設定し→電源モードを設定します (注:「スリープタイマー間隔を設定する」ステップは「電源モードを設定する」前に行う必要があります。なぜなら、システムはスリープ入り後にプログラムの実行を継続しないためです) 次に、スリープタイマー間隔を設定する部分関数に焦点を当てましょう。setSleepTimer まず最初に、スリープタイマーの簡単な紹介です:それは動作し続けます32.768kHzの24位タイマー、システムが稼働している時PM3に加えてすべての電源モードで、スリープタイマーは中断のない運行。 スリープタイマーで使用されるレジスタは以下の通りです:ST0,ST1,ST2。 以下はCC2430中国語マニュアルからの詳細な機能紹介です。
その機能には2つの側面が含まれていることがわかります。読む,書く。 読む現在のタイマーのカウント値、読み取りに従う順序を読み取るために使用されます:ST0を読んで→ST1を読んで→ST2を読んでください 書くタイマーの比較値を設定するために使用されます(タイマーのカウント値=比較値が発生した場合、割り込みが発生する場合)、書き込み順は以下に従わなければなりません。ST2を書く→ST1を書く→ST0を書く では、ソースコードと組み合わせて説明しましょう。 (1) まず、無符号の長変数(32ビット)スリープタイマーを定義し、スリープタイマーの現在のカウント値を受け取る: 署名なし長いsleepTimer =0;
sleepTimer |= ST0; //現在のスリープタイマーのカウント値を取得してください
sleepTimer |= (署名なし)長い)ST1 <<8; sleepTimer |= (署名なし)長い)ST2 <<16;
(2) 次に必要な時間区間を加えます: sleepTimer += ((符号なし)長い)sec *(署名なし)長い)32768); //さらに、必要なタイミング時間も必要です
少し説明します: なぜ1は32768を表すのでしょうか? タイマーは32.768kHz以下で動作するため、タイマーに1を追加するごとに1/32768秒かかります。 32768を加えると1が必要になります。 (3) 最後に、sleepTimerの値はタイマーの比較値として用いられます: ST2 = (符号なし)チャー(睡眠タイマー>>16); //スリープタイマーの比較値を設定します
ST1 = (符号なし)チャー(睡眠タイマー>>8); ST0 = (符号なし)チャー)sleepTimer;
こうしてタイマーのタイミングを正しく設定できます~ (注:ソースコードの他の部分については、詳細な注釈と組み合わせれば簡単に理解できると思いますので、ここでは繰り返しません) (4) 実験結果プログラムを実行し、LED1を観測すると、現象は以下の通りです:LED1が点滅(つまり点灯・>消し1回)、1秒後に点滅し、2秒後に点滅し、その後は消灯し、S1を押すとLED1が点灯します。 この実験現象は期待と完全に一致しています。オーバー~
3. 結論ああ~2日間の暇を取って、ついにこの記録を手に入れた。 特に「読者に優しい」ブログ記事を書くことは、確かに身体的な仕事だと感じました。厳密さ、美学、論理性... すべては配慮の問題です。 コードを投稿するたびに長すぎると思うのですが、ブログガーデンに付属している折りたたみツールを使うのはためらっています。 そのため、このブログ記事では、著者がコードの滑らかな折りたたみを実現するためにJQueryの要素を仮に追加しましたが、それでも少しの達成感があります(へへと(JQueryの新人、マスターを笑わないで~)。 ただ、これが記事の読みやすさを本当に向上させるかはわかりませんし、読者や友人のコメントも歓迎します:) 今月は著者がブログの庭に根を下ろすことを決めたので、私はたくさんの余暇をブログ記事の執筆に費やしました。 初めてブログを書いたとき、コメントは少なかったものの、ほとんどのログのクリック率が500以上あり、私にとっては小さな励みになりました! ブログガーデンでマイクロコントローラに関するコンテンツを公開するには勇気が必要ですが、私は続けます~ 創刊から現在までの9本のブログ記事は、CC2430チップ上の基本的なハードウェアモジュールの利用に焦点を当てています。 これまでのところ、CC2430の周辺機器のほとんどは確認済みですが、フラッシュアクセス、乱数生成器、AESコプロセッサ、RF通信などはまだ触れられていません。 しかし、Zigbeeの旅はまだ終わっておらず、著者は次のトピック(Z-Stackプロトコルの実装)でこれらの欠落を選択的に補うつもりです。 次回のブログ記事では、Zigbeeの最初の旅を、より包括的で拡張された実験「温度モニタリングシステム」で締めくくり、先に学んだ知識ポイントを包括的に応用する方法を説明します。 実際、それは「説明初心者として、著者はお互いに励まし合い、博士論文執筆の過程で共に前進できることを願っています! </n; i++)
|