3月3日に「Zigbee Journey (9)」を書いた後、著者は当初、これまでの散在した知識ポイントの要約として「温度モニタリングシステム」の小さな実験をすぐに書き始める予定でした。 しかし同時に、これまでの小さな実験は詳細に説明されていたものの、そのコードの規範的かつ構造的な性質は耐え難いものと言えるとも感じました。 要約であるため、前の小さな知識ポイントを機械的に組み合わせるのではなく、元の基盤で進展を進めるべきです。 そこで、元の計画を保留にし、組み込み開発の一般的な技術を学ぶ時間を取り、2つのエッセイを書きました組み込みC51プログラミング仕様「そして」組み込みプロジェクトコード構造の階層》。 このログはZigbeeの最初の旅の要約であるだけでなく、著者の最近の学びの経験も含めており、Zigbee初心者の皆さんの参考になればと思っています。
全文はソフトウェア開発の基本的なプロセス、すなわち要件分析、アウトライン設計、詳細設計、コーディング実装、テストに基づいて構成されています。
1. 需要分析「顧客」と「開発者」の間で話し合いの結果、以下のシステム機能記述が決定されました。
… 現在の室温はCC2430ベースのノードによって収集され、その温度値はPCを通じて監視可能です
… CC2430ノード自体は一定の安定性を持ち、自動的に通常状態に戻ることができます
… ノードのサンプリング間隔や電力管理はPCで制御可能です
2. アウトラインデザイン上記の要件分析によれば、このシステムは2つのモジュールに分けることができます。CC2430ノードそしてPC。
[CC2430ノード]
… 外部パラメータは定期的に収集し、PCに送信できます
… 機械の電源が切れたときの自動リセット
… PCからのコマンドは受信・処理可能です:サンプル間隔や電力管理の変更
[PC]
… Cマシンはシリアルポートツールを通じてデータを受信し表示します
… 命令はシリアルポートツールを通じてマイクロコントローラに送信され、サンプリング速度と電力管理を制御できます
3. 詳細設計(1) コード構造
このシステムのコード構造の層構造については、実際にエッセイで説明されています。組み込みプロジェクトコード構造の階層、コピーは以下の通りです:
(1) ハードウェア抽象化層
[ioCC2430.h](システム含む):CC2430のすべてのSFRおよび割り込みベクトルが定義されています
[はっ、一般的な型定義、共通割り当てマクロ、CC2430オンチップリソース(I/O、シリアル通信、ADC、タイマー、電源管理など)の共通設定が含まれています。
(2) 機能モジュール層
[module.hオンチップリソース(タイマー、I/O)、オフチップ拡張モジュール(LED)、および関連機能の宣言を定義します
[module.c各モジュール(LED)の初期化を実装します。
(3) アプリケーション層
[main.c温度取得、PCとの通信、シャットダウンやリセットなどの特定のアプリケーション要件を満たすには、hal.h、ioCC2430.h、module.hを参照してください
(2) 各モジュールの実装方法
概要設計に基づきモジュールに分けられ、内在システムは主に2つのモジュールに分けられます。CC2430ノードそしてPC。
PCにはシリアルポート通信ツールがあるため、その機能は要件を満たすことができ、この部分を自分で行う必要もなく、分析も不要です。 以下でCC2430セクションについて話しましょう
点の各部分関数の実装方法:
… タイマーのカウントオーバーフロー割り込みを使ってタイムドサンプリングをトリガーします
… シリアルポート付きのUART0モードは温度データをPCに送信します
… CC2430の内蔵ウォッチドッグ回路は、システムの自動リセット機能を実現するために使われています
… シリアルポートは、PCからの制御コマンドをキャプチャし応答するための割り込み受信に使用されます
1) 受け取った場合@この文字はサンプリング間隔制御コマンドで、その後にサンプリング間隔を示す数字が続きます:0-0.5秒、1-1秒、2-2秒
如:@0,表示每隔0.5秒采样一次。
2) 受け取った場合$ この文字はスリープコントロールコマンドで、その後に電源モードを示す数字が続きます
例えば:$3はシステムを電源モード3に切り替えることを意味します。
(3) プログラムフローチャート
- マスタープログラムフローチャート
- タイマー1オーバーフロー割り込みプログラムフローチャート
- シリアルポート受信割り込み手順のフローチャート
4. コーディング実装(1) ハードウェア抽象化層
ハードウェア抽象化層にはioCC2430.hとhal.hが含まれます。 前者のシステムが付属しているため、リストには載せません。
以下はhal.hのすべての内容のリストです(このファイルは長すぎて不便に見えるため、モジュールごとに示します):
- ヘッド
- I/Oポート
- 中断
- シリアルポート
- 電源とクロック管理
- タイマー
- 番犬
- ADC
[url=]
[/url]
/***********************************************************
*ファイル名:hal.h
*著者:hustlzp
*日付:2011年3月8日
*版:1.1
*機能説明:ハードウェア抽象化層
*修正された記録:
***********************************************************/
#ifndef HAL_H
#defineHAL_H
#include
/***********************************************************
一般的な型の定義
***********************************************************/
typedef 無署名チャー バイト;
typedef 無署名知力 言葉;
typedef 無署名長い DWORD;
/***********************************************************
一般的に使われるマクロ定義
***********************************************************/
//8位上
#defineHIGH_BYTE(a)((バイト)((WORD)(a))>> 8))
//8位下位
#defineLOW_BYTE(a)((バイト)(WORD)(a)))
//配属
#defineSET_WORD(regH, regL, word)
する{
(regH)=HIGH_BYTE(単語);
(regL)=LOW_BYTE(単語);
}ただし(0)
[url=][/url]
[url=][/url]
/***********************************************************
I/Oポート
***********************************************************/
/*I/Oポートの方向を設定する
-----------------------------------------*/
#defineIO_DIR_PORT_PIN(ポート、ピン、監督)
する{
もし(監督 == IO_OUT)
P##port##DIR |= (0x01<<(ピン));
そうでなければ
P##port##DIR &= ~(0x01<<(ピン));
}ただし(0)
//パラメータdirの値は次の通りです:
#defineIO_IN 0
#defineIO_OUT 1
/*I/Oポートの入力モードを設定する
-----------------------------------------*/
#defineIO_IMODE_PORT_PIN(ポート、ピン、imode)
する{
もし(iMode == IO_IMODE_TRI)
P##port##INP |= (0x01<<(ピン));
そうでなければ
P##port##INP &= ~(0x01<<(ピン));
}ただし (0)
#define IO_PUD_PORT(ポート、プッド)
Do {
if(pud == IO_PULLDOWN)
P2INP |= (0x01 << (ポート+5));
そうでなければ
P2INP &= ~(0x01 << (port+5));
} 一方で(0)
パラメータPUDの値は次の通りです:
#define IO_PULLUP 0 // プルアップ
#define IO_PULLDOWN 1 // 引き下げる
/*配置I/O口的功能
-----------------------------------------*/
#define IO_FUNC_PORT_PIN(ポート、ピン、ファンク)
Do {
if((port == 2) & (pin == 3)){
もし(func) {
P2SEL |= 0x02;
} そうでなければ {
P2SEL &= ~0x02;
}
}
else((port == 2) & (pin == 4)){
もし(func) {
P2SEL |= 0x04;
} そうでなければ {
P2SEL &= ~0x04;
}
}
そうでなければ{
もし(func) {
P##port##SEL |= (0x01<<(ピン));
} そうでなければ {
P##port##SEL &= ~(0x01<<(ピン));
}
}
} 一方で(0)
パラメータ関数の値は次の通りです:
#define IO_FUNC_GIO 0 // 一般I/O
#define IO_FUNC_PERIPH 1 // 周辺I/O
周辺I/Oの位置を設定する
#define IO_PER_LOC_TIMER1_AT_PORT0_PIN234() do { PERCFG = (PERCFG&~0x40)|0x00; } 一方で(0)
#define IO_PER_LOC_TIMER1_AT_PORT1_PIN012() do { PERCFG = (PERCFG&~0x40)|0x40; } 一方で(0)
#define IO_PER_LOC_TIMER3_AT_PORT1_PIN34() do { PERCFG = (PERCFG&~0x20)|0x00; } 一方で(0)
#define IO_PER_LOC_TIMER3_AT_PORT1_PIN67() do { PERCFG = (PERCFG&~0x20)|0x20; } 一方で(0)
#define IO_PER_LOC_TIMER4_AT_PORT1_PIN01() do { PERCFG = (PERCFG&~0x10)|0x00; } 一方で(0)
#define IO_PER_LOC_TIMER4_AT_PORT2_PIN03() do { PERCFG = (PERCFG&~0x10)|0x10; } 一方で(0)
#define IO_PER_LOC_SPI1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x08)|0x00; } 一方で(0)
#define IO_PER_LOC_SPI1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x08)|0x08; } 一方で(0)
#define IO_PER_LOC_SPI0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x00; } 一方で(0)
#define IO_PER_LOC_SPI0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x04; } 一方で(0)
#define IO_PER_LOC_UART1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x02)|0x00; } 一方で(0)
#define IO_PER_LOC_UART1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x02)|0x02; } 一方で(0)
#define IO_PER_LOC_UART0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x00; } 一方で(0)
#define IO_PER_LOC_UART0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x01; } 一方で(0)
//パラメータimodeの値は以下の通りです:
#defineIO_IMODE_PUD 0 //プルアップ/プルダウン
#defineIO_IMODE_TRI 1 //三つの州[url=][/url]
[url=][/url]
/***********************************************************
中断
***********************************************************/
//オン/オフの割り込み用
#defineINT_ON 1
#defineINT_OFF 0
//割り込みフラグの設置/クリアに使われました
#defineINT_SET 1
#defineINT_CLR 0
//グローバル割り込み設定
#defineINT_GLOBAL_ENABLE(オン) EA=(!! オン)
//ブレイクを定義する
#defineINUM_RFERR 0
#defineINUM_ADC 1
#defineINUM_URX0 2
#defineINUM_URX1 3
#defineINUM_ENC 4
#defineINUM_ST 5
#defineINUM_P2INT 6
#defineINUM_UTX0 7
#defineINUM_DMA 8
#defineINUM_T1 9
#defineINUM_T2 10
#defineINUM_T3 11
#defineINUM_T4 12
#defineINUM_P0INT 13
#defineINUM_UTX1 14
#defineINUM_P1INT 15
#defineINUM_RF 16
#defineINUM_WDT 17
/*中断は許されます
-----------------------------------------*/
#defineINT_ENABLE(inum、オン)
する{
もし (イヌム==INUM_RFERR) { RFERRIE = オン; }
そうでなければ もし(イヌム==INUM_ADC) { ADCIE = オン; }
そうでなければ もし(イヌム==INUM_URX0) { URX0IE = オン; }
そうでなければ もし(イヌム==INUM_URX1) { URX1IE = オン; }
そうでなければ もし(イヌム==INUM_ENC) { ENCIE = on; }
そうでなければ もし(inum==INUM_ST) { STIE = オン; }
そうでなければ もし(イヌム==INUM_P2INT) {(オン)? (IEN2 |=0x02) : (IEN2 &= ~0x02); }
そうでなければ もし(イヌム==INUM_UTX0) {(オン)? (IEN2 |=0x04) : (IEN2 &= ~0x04); }
そうでなければ もし(イヌム==INUM_DMA) { DMAIE = オン; }
そうでなければ もし(イヌム==INUM_T1) { T1IE = オン; }
そうでなければ もし(イヌム==INUM_T2) { T2IE = on; }
そうでなければ もし(イヌム==INUM_T3) { T3IE = オン; }
そうでなければ もし(イヌム==INUM_T4) { T4IE = オン; }
そうでなければ もし(イヌム==INUM_P0INT) { P0IE = オン; }
そうでなければ もし(イヌム==INUM_UTX1) {(オン)? (IEN2 |=0x08) : (IEN2 &= ~0x08); }
そうでなければ もし(イヌム==INUM_P1INT) {(オン)? (IEN2 |=0x10) : (IEN2 &= ~0x10); }
そうでなければ もし(イヌム==INUM_RF) {(オン)? (IEN2 |=0x01) : (IEN2 &= ~0x01); }
そうでなければ もし(イヌム==INUM_WDT) {(オン)? (IEN2 |=0x20) : (IEN2 &= ~0x20); }
}ただし (0)
/*障害の優先度を設定する
-----------------------------------------*/
#defineINT_PRIORITY(グループ、プリ)
する{
もし(プリ ==0) { IP0 &= ~group; IP1 &= ~グループ; }
もし(プリ ==1) { IP0 |= グループ; IP1 &= ~グループ; }
もし(プリ ==2) { IP0 &= ~group; IP1 |= グループ; }
もし(プリ ==3) { IP0 |= グループ; IP1 |= グループ; }
}ただし (0)
//パラメータpriの値は0/1/2/3(最高優先度)です。
//パラメータ群の値は次の通りです:
#defineRFERR_RF_DMA 0x01//グループIP0
#defineADC_P2INT_T1 0x02//グループIP1
#defineURX0_UTX0_T2 0x04//グループIP2
#defineURX1_UTX1_T3 0x08//グループIP3
#defineENC_P1INT_T4 0x10//グループIP4
#defineST_WDT_P0INT 0x20//グループIP5
/*割り込みフラグを取得してください
-----------------------------------------*/
#defineINT_GETFLAG(inum)(
(イヌム==INUM_RFERR)? RFERRIF:
(イヌム==INUM_ADC)? ADCIF:
(イヌム==INUM_URX0) ? URX0IF:
(inum==INUM_URX1) ? URX1IF:
(inum==INUM_ENC) ? ENCIF_0:
(イヌム==INUM_ST)? STIF:
(イヌム==INUM_P2INT)? P2IF:
(イヌム==INUM_UTX0)? UTX0IF:
(inum==INUM_DMA) ? DMAIF:
(イヌム==INUM_T1) ? T1IF:
(イヌム==INUM_T2) ? T2IF:
(イヌム==INUM_T3) ? T3IF:
(イヌム==INUM_T4)? T4IF:
(イヌム==INUM_P0INT)? P0IF:
(イヌム==INUM_UTX1) ? UTX1IF:
(イヌム==INUM_P1INT)? P1IF:
(イヌム==INUM_RF)? S1CON &= ~0x03 :
(イヌム==INUM_WDT) ? WDTIF:
0
)
/*割り込みフラグを設定してください
-----------------------------------------*/
#defineINT_SETFLAG(inum, f)
する{
もし (イヌム==INUM_RFERR) { RFERRIF= f; }
そうでなければ もし(イヌム==INUM_ADC) { ADCIF = f; }
そうでなければ もし(イヌム==INUM_URX0) { URX0IF = f; }
そうでなければ もし(イヌム==INUM_URX1) { URX1IF = f; }
そうでなければ もし(イヌム==INUM_ENC) { ENCIF_1 = ENCIF_0 = f; }
そうでなければ もし(inum==INUM_ST) { STIF = f; }
そうでなければ もし(イヌム==INUM_P2INT) { P2IF = f; }
そうでなければ もし(イヌム==INUM_UTX0) { UTX0IF= f; }
そうでなければ もし(イヌム==INUM_DMA) { DMAIF = f; }
そうでなければ もし(イヌム==INUM_T1) { T1IF = f; }
そうでなければ もし(イヌム==INUM_T2) { T2IF = f; }
そうでなければ もし(イヌム==INUM_T3) { T3IF = f; }
そうでなければ もし(イヌム==INUM_T4) { T4IF = f; }
そうでなければ もし(イヌム==INUM_P0INT) { P0IF = f; }
そうでなければ もし(イヌム==INUM_UTX1) { UTX1IF= f; }
そうでなければ もし(イヌム==INUM_P1INT) { P1IF = f; }
そうでなければ もし(イヌム==INUM_RF) {(女性)? (S1CON |=0x03) : (S1CON &= ~0x03); }
そうでなければ もし(イヌム==INUM_WDT) { WDTIF = f; }
}ただし (0)
[url=][/url]
[url=][/url]
/***********************************************************
シリアルポート
***********************************************************/
//異なるボー率に対応する BAUD_E の値
#defineBAUD_E(ボー、clkDivPow)(
(ボー==2400) ? 6 +clkDivPow :
(ボー==4800) ? 7 +clkDivPow :
(ボー==9600) ? 8 +clkDivPow :
(ボー==14400) ? 8 +clkDivPow :
(ボー==19200) ? 9 +clkDivPow :
(ボー==28800) ? 9 +clkDivPow :
(ボー==38400) ? 10+clkDivPow :
(ボー==57600) ? 10+clkDivPow :
(ボー==76800) ? 11+clkDivPow :
(ボー==115200) ? 11+clkDivPow :
(ボー==153600) ? 12+clkDivPow :
(ボー==230400) ? 12+clkDivPow :
(ボー==307200) ? 13+clkDivPow :
0 )
//BAUD_Mの値は異なるボーレートに対応します
#defineBAUD_M(ボー)(
(ボー==2400) ? 59 :
(ボー==4800) ? 59 :
(ボー==9600) ? 59 :
(ボー==14400) ? 216 :
(ボー==19200) ? 59 :
(ボー==28800) ? 216 :
(ボー==38400) ? 59 :
(ボー==57600) ? 216 :
(ボー==76800) ? 59 :
(ボー==115200) ? 216 :
(ボー==153600) ? 59 :
(ボー==230400) ? 216 :
(ボー==307200) ? 59 :
0)
/*UARTモードにおけるシリアルポートの設定
-----------------------------------------*/
#defineUART_SETUP(uart、receiveEnable、baudRate、options)
する{
もし((uart) ==0){
もし(PERCFG &0x01){
P1SEL |=0x30;
}そうでなければ{
P0SEL |=0x0C;
}
}
そうでなければ{
もし(PERCFG &0x02){
P1SEL |=0xC0;
}そうでなければ{
P0SEL |=0x30;
}
}
U##uart##GCR = BAUD_E((baudRate),CLKSPD);
U##uart##BAUD = BAUD_M(ボーレート);
U##uart##CSR |=0x80;
U##uart##CSR |= receiveEnable;
U##uart##UCR |= ((options) |0x80);
}ただし(0)
//パラメータの値 Enable:
#defineUART_RECEIVE_ENABLE 0x40 //許可の獲得
#defineUART_RECEIVE_DISABLE 0x00
//パラメータオプションの価値:
#defineFLOW_CONTROL_ENABLE 0x40 //流量制御
#defineFLOW_CONTROL_DISABLE 0x00
#defineEVEN_PARITY 0x20 //時折の検証
#defineODD_PARITY 0x00 //奇妙な検証
#defineNINE_BIT_TRANSFER 0x10 //9バイト転送
#defineEIGHT_BIT_TRANSFER 0x00 //8バイト転送
#definePARITY_ENABLE 0x08 //パリティチェックの有効化
#definePARITY_DISABLE 0x00
#defineTWO_STOP_BITS 0x04 //2ポジションストップポジション
#defineONE_STOP_BITS 0x00 //1ストップポジション
#defineHIGH_STOP 0x02 //停止レベルが高い
#defineLOW_STOP 0x00 //ストップポジションは低いです
#defineHIGH_START 0x01 //開始ビットレベルが高い
#defineLOW_START 0x00 //開始ビットレベルは低いです
//シリアルポートは文字を送信します
#defineUART_SEND(uart,data)
する{
ただし(U##uart##CSR &0x01);
U##uart##DBUF = データ;
}ただし (0)
#defineUART0_SEND(data) UART_SEND(0,data)
#defineUART1_SEND(データ) UART_SEND(1,data)
//シリアルポートは文字を受信します
#defineUART_RECEIVE(uart,data)
する{
ただし(! (U##uart##CSR&0x04));
data=U##uart##DBUF;
}ただし(0)
#defineUART0_RECEIVE(data) UART_RECEIVE(0,data)
#defineUART1_RECEIVE(data) UART_RECEIVE(1,data)
[url=][/url]
[url=][/url]
/***********************************************************
電源とクロック管理
***********************************************************/
//時計のクロスオーバーを手に入れた
#defineCLKSPD(CLKCONおよび0x07)
//電源モードを設定してください
#defineSET_POWER_MODE(モード)
する{
もし(モード==0) { 眠り &= ~0x03; }
そうでなければ もし(モード==3) { 眠り |=0x03; }
そうでなければ{ 眠り &= ~0x03; SLEEP |= モード; }
PCON |=0x01;
ASM("NOP");
}ただし (0)
//パラメータモードは以下の値に設定されます:
#definePOWER_MODE_0 0x00
#definePOWER_MODE_1 0x01
#definePOWER_MODE_2 0x02
#definePOWER_MODE_3 0x03
//高周波RC発振器の安定性検出に用いられます
#defineHIGH_FREQUENCY_RC_OSC_STABLE(SLEEP & 0x20)
//結晶発振器の安定状態を検出するために使用されます
#defineXOSC_STABLE(SLEEP & 0x40)
//タイマーのティック頻度値を取得します
#defineTICKSPD((CLKCONおよび0x38)>> 3)
//マスタークロック周波数を設定してください
#defineSET_MAIN_CLOCK_SOURCE(出典)
する{
もし(出典) {
CLKCON |=0x40;
ただし(! HIGH_FREQUENCY_RC_OSC_STABLE);
もし(チックスプド==0){
CLKCON |=0x08;
}
眠り |=0x04;
}
そうでなければ{
眠り &= ~0x04;
ただし(! XOSC_STABLE);
ASM("NOP");
CLKCON &= ~0x47;
眠り |=0x04;
}
}ただし (0)
//パラメータソースの値は次の通りです:
#defineクリスタル0x00 //結晶振動器
#defineRC 0x01 //RC発振器
[url=][/url]
[url=][/url]
/***********************************************************
タイマー1
***********************************************************/
//タイマー1はカウントオーバーフローを中断させます
#defineTIMER1_ENABLE_OVERFLOW_INT(val)
(TIMIF = (val) ? ティミフ |0x40:ティミフ & ~0x40)
//タイマー1のオーバーフロー割り込みフラグを設定します
#defineTIMER1_OVERFLOW_INT_SETFLAG(f)(T1CTL= ((T1CTL & (~0x10)) | f))
//タイマー1開始
#defineTIMER1_RUN(値)(T1CTL = (値) ? T1CTL|0x02 : T1CTL&~0x03)
//タイマーの時計分割をセットしてください
#defineSET_TIMER_TICK(value) do{ CLKCON = ((CLKCON & (~0x38)) | value); } while(0)
//価値の価値は以下の通りです:
#defineTIMER1_TICK_32M 0x00 //32MHz
#defineTIMER1_TICK_16M 0x08 //16MHz、システムリセットのデフォルト値
#defineTIMER1_TICK_8M 0x10 //8MHz
#defineTIMER1_TICK_4M 0x18 //4MHz
#defineTIMER1_TICK_2M 0x20 //2MHz
#defineTIMER1_TICK_1M 0x28 //1MHz
#defineTIMER1_TICK_500k 0x30 //500kHz
#defineTIMER1_TICK_250k 0x38 //250kHz
//TICKクロスオーバーをタイマー1に設定してください
#defineSET_TIMER1_TICKDIV(値)
する{
T1CTL &= ~0x0c;
T1CTL |= 値;
}ただし (0)
//ここで、値は次のようになります:
#defineTIMER1_TICKDIV_1 0x00 //1区
#defineTIMER1_TICKDIV_8 0x04 //8路周波数
#defineTIMER1_TICKDIV_32 0x08
#defineTIMER1_TICKDIV_128 0x0c
//タイマーのオーバーフロー期間を設定してください
#defineSET_TIMER1_PERIOD(値)
する{
T1CC0H = HIGH_BYTE(値);
T1CC0L = LOW_BYTE(値);
}ただし (0)
//タイマー1の動作モードを設定する
#defineSET_TIMER1_MODE(モード)
する{
T1CTL = ((T1CTL & (~0x03)) | モード);
}ただし (0)
//モードの値は次の通りです:
#defineTIMER1_MODE_STOP 0x00
#defineTIMER1_MODE_FREE 0x01
#defineTIMER1_MODE_MODULE 0x02
#defineTIMER1_MODE_UPDOWN 0x03
[url=][/url]
[url=][/url]
/***********************************************************
番犬
***********************************************************/
//ウォッチドッグタイマーのオーバーフロー期間を設定します
#defineWDT_SET_TIMEOUT_PERIOD(タイムアウト)
する{ WDCTL &= ~0x03; WDCTL |= タイムアウト; }ただし (0)
//パラメータタイムアウトの値は次の通りです:
#defineSEC_1 0x00 //1秒後
#defineM_SEC_250 0x01 //250ミリ秒後
#defineM_SEC_15 0x02 //15ミリ秒後
#defineM_SEC_2 0x03 //2ミリ秒後
//犬の給餌手順
#defineWDT_RESET() do {
WDCTL = (WDCTL & ~0xF0) |0xA0;
WDCTL = (WDCTL & ~0xF0) |0x50;
} ただし (0)
//ウォッチドッグタイマーの開始/停止
#defineWDT_ENABLE() WDCTL |= 0x08
#defineWDT_DISABLE() WDCTL &= ~0x08
[url=][/url]
[url=][/url]
/***********************************************************
ADC
***********************************************************/
//単一のADCを構成します
#defineADC_SINGLE_CONVERSION(設定)
する{ ADCCON3 = 設定; }ただし(0)
//パラメータ設定は以下の組み合わせで構成されています。
//基準電圧
#defineADC_REF_1_25_V 0x00 //内部1.25V基準電圧
#defineADC_REF_P0_7 0x40 //AIN7ピンの外部参照電圧
#defineADC_REF_AVDD 0x80 //AVDD_SOC ピン
#defineADC_REF_P0_6_P0_7 0xC0 //AIN6-AIN7 差動入力の外部参照電圧
//サンプリングレート
#defineADC_8_BIT 0x00 //8位
#defineADC_10_BIT 0x10 //10位
#defineADC_12_BIT 0x20 //12位
#defineADC_14_BIT 0x30 //14位
//チャンネルの登場
#defineADC_AIN0 0x00 //P0_0
#defineADC_AIN1 0x01 //P0_1
#defineADC_AIN2 0x02 //P0_2
#defineADC_AIN3 0x03 //P0_3
#defineADC_AIN4 0x04 //P0_4
#defineADC_AIN5 0x05 //P0_5
#defineADC_AIN6 0x06 //P0_6
#defineADC_AIN7 0x07 //P0_7
#defineADC_GND 0x0C //土地
#defineADC_TEMP_SENS 0x0E //チップ内温度センサー
#defineADC_VDD_3 0x0F //VDD/3
ADC変換完了
#define ADC_SAMPLE_READY()(ADCCON1 & 0x80)
#endif
//启动ADC转化
#define ADC_START()
Do { ADCCON1 |= 0x40; } 一方で(0)//ADCのトリガーモードをマニュアル(つまりADC_SAMPLE_READY)として選択します。
#defineADC_STOP()
する{ ADCCON1 |=0x30; }ただし (0)[url=][/url]
(2) 機能モジュール層
[url=][/url]
/***********************************************************
*ファイル名:module.h
*著者:hustlzp
*日付:2011年3月6日
*バージョン:1.0
*関数説明:機能モジュール層ヘッダーファイル
*機能リスト:空虚led_init()
ヴォイドtimer1_init()
虚無uart0_init(虚無);
void Uart0SendString(unsigned char *s);
浮かぶadc_start(ヴォイド)
void get_temperature(unsigned char *output, float temp);
虚無watchdog_init(虚無);
*修正された記録:
***********************************************************/
#ifndef MODULE_H
#defineMODULE_H
#include"はっ、"
/***********************************************************
LED
***********************************************************/
//LEDピンの定義
#defineLED1 P1_0
#defineLED2 P1_1
#defineLED3 P1_2
#defineLED4 P1_3
//LEDランプと消灯
#defineLED_OFF 1
#defineLED_ON 0
//LEDの初期化
虚無led_init(虚無);
/***********************************************************
タイマー1
***********************************************************/
//タイマーのオーバーフロー期間値を設定するために使われます
#defineTIMER1_OVF_2SEC 0xF424 //2
#defineTIMER1_OVF_1SEC 0x7A12 //1
#defineTIMER1_OVF_dot5SEC 0x3D09 //0.5秒
//タイマー1が初期化します
虚無 timer1_init(虚無);
/***********************************************************
UART0
***********************************************************/
//UART0の初期化
虚無 uart0_init(虚無);
//シリアルポート伝送文字列
虚無 Uart0SendString(unsigned)チャー*s);
/***********************************************************
ADC-14
***********************************************************/
//ADCで得られたデータを摂氏温度に変換するために使用されます
#defineADC_TO_CELSIUS(温度)(温度 * 0.06229 - 311.43)
//ADCへの変換を開始する
浮き上がるadc_start(虚無);
//転換
虚無 get_temperature(署名なし)チャー*出力、浮き上がる臨時);
/***********************************************************
ウォッチドッグ
***********************************************************/
//ウォッチドッグの初期化
虚無 watchdog_init(虚無);
#endif
[url=][/url]
[url=][/url]
/***********************************************************
*ファイル名:module.c
*著者:hustlzp
*日付:2011年3月11日
*バージョン:1.0
*機能記述:機能モジュール層のソースファイル
*機能リスト:(省略)
*修正された記録:
***********************************************************/
#include"module.h"
/***********************************************************
*機能名:led_init
*機能関数:LED初期化
*入口パラメータ:なし
*エクスポートパラメータ:なし
***********************************************************/
虚無led_init(虚無)
{
//P1.0、P1.1、P1.2、P1.3を一般的なI/Oポートとして設定してください
IO_FUNC_PORT_PIN(1, 0、IO_FUNC_GIO);
IO_FUNC_PORT_PIN(1, 1、IO_FUNC_GIO);
IO_FUNC_PORT_PIN(1, 2、IO_FUNC_GIO);
IO_FUNC_PORT_PIN(1, 3、IO_FUNC_GIO);
//P1.0、P1.1、P1.2、P1.3を出力として設定します
IO_DIR_PORT_PIN(1, 0、IO_OUT);
IO_DIR_PORT_PIN(1, 1、IO_OUT);
IO_DIR_PORT_PIN(1, 2、IO_OUT);
IO_DIR_PORT_PIN(1, 3、IO_OUT);
led1 = LED_ON;
led2 = LED_OFF;
led3 = LED_OFF;
led4 = LED_OFF;
}
/***********************************************************
*機能名:timer1_init
* 関数関数:タイマー1の初期化
*入口パラメータ:なし
*エクスポートパラメータ:なし
***********************************************************/
虚無timer1_init(虚無)
{
INT_GLOBAL_ENABLE(INT_ON); //グローバル中断を開く
INT_ENABLE(INUM_T1、INT_ON); //オープンT1割り込み
TIMER1_ENABLE_OVERFLOW_INT(INT_ON); //オープンT1カウントオーバーフロー割り込み
SET_TIMER_TICK(TIMER1_TICK_4M); //タイマーTICKを4MHzに設定してください
SET_TIMER1_PERIOD(TIMER1_OVF_2SEC); //T1のカウント期間を2に設定します
SET_TIMER1_TICKDIV(TIMER1_TICKDIV_128); //T1のクロッククロスオーバーを128に設定してください
SET_TIMER1_MODE(TIMER1_MODE_MODULE); //T1の実行モードをモジュールに設定してください
}
/***********************************************************
*機能名:uart0_init
*関数関数:シリアルポートUART0の初期化
*入口パラメータ:なし
*エクスポートパラメータ:なし
***********************************************************/
虚無uart0_init(虚無)
{
//UARTの所在地を選択してください
IO_PER_LOC_UART0_AT_PORT0_PIN2345();
//UARTの設定:受信許可、115200bps、1ビットのストップビット、パリティなし
UART_SETUP(0、UART_RECEIVE_ENABLE、115200、ONE_STOP_BITS | PARITY_DISABLE);
//完全な中断を開けろ
INT_GLOBAL_ENABLE(INT_ON);
//割り込み受信のためにシリアルポート0を開く
INT_ENABLE(INUM_URX0、INT_ON);
}
/***********************************************************
*関数名:Uart0SendString
* 関数関数:タイマー1の初期化
*エントリパラメータ:符号なし文字 *s
送りたい文字列
*エクスポートパラメータ:なし
***********************************************************/
虚無Uart0SendString(unsigned)チャー*s)
{
ただし(*s !=0)
UART0_SEND(*s++);
}
/***********************************************************
*機能名:adc_start
*機能機能:ADC変換開始
*入口パラメータ:なし
*エクスポートパラメータ:float
タブレット内の温度値
***********************************************************/
浮き上がるadc_start(虚無)
{
署名なし知力テンポンシブ;
//基準電圧は1.25V、サンプリング精度は14ビット、変換対象はオンチップ温度センサーです
ADC_SINGLE_CONVERSION(ADC_REF_1_25_V | ADC_14_BIT | ADC_TEMP_SENS);
ADC_STOP(); //ADCを手動に変換するためのトリガーメソッドを設定してください
ADC_START(); //ADCへの変換を開始する
ただし(! ADC_SAMPLE_READY()); //変換が完了するまで待ちます
temp = ADCL >>2; //変換結果を一時的に保存してください
temp |= (((符号なし)知力) ADCH) <<6);
帰還ADC_TO_CELSIUS(臨時); //変換後の実際の温度値を返します
}
/***********************************************************
*関数名:get_temperature
*関数関数:温度値を処理し、シリアル出力用の文字配列に格納する
*エントリパラメータ:符号なし文字 *出力
変換後の温度値を格納するために使用されます
フロート温度
摂氏の温度値
*エクスポートパラメータ:なし
***********************************************************/
虚無get_temperature(署名なし)チャー*出力、浮き上がる臨時)
{
出力[0] = (符号なし)チャー(temp) /10 + 48; //10名
出力[1] = (符号なし)チャー(temp) %10 + 48; //一桁の数字
出力[2] ='.'; //小数点
出力[3] = (符号なし)チャー(臨時*10) %10 + 48; //第10
出力[4] = (符号なし)チャー(臨時*100) %10 + 48; //パーセンタイル
出力[5] =''; //弦の終末語
}
/***********************************************************
*機能名:watchdog_init
*関数関数:ウォッチドッグの初期化
*入口パラメータ:なし
*エクスポートパラメータ:なし
***********************************************************/
虚無watchdog_init(虚無)
{
WDT_SET_TIMEOUT_PERIOD(SEC_1); //タイムアウトの時間は1秒に設定してください
WDT_ENABLE(); //監視犬を起動しろ
}
[url=][/url]
(3) アプリケーション層
[url=][/url]
/*******************************************************************
ファイル名:main.c
著者:hustlzp
日付:2011年3月11日
バージョン:1.0
関数説明:マスタープログラムファイル
機能一覧:(省略)
修正記録:
*******************************************************************/
#include
/********************************************************************
割り込みサービス手順
********************************************************************/
/* 定时器1溢出中断子程序
-------------------------------------------------------*/
#pragma ベクトル=T1_VECTOR
__interrupt void T1_ISR(void)
{
EA=0; 門が遮られた
led2 = LED_ON;
get_temperature(output,adc_start()); 温度値を出力する文字の配列に変換します
Uart0SendString(output); 出力温度値
Uart0SendString("°C");
LED2
/* 串口接收中断子程序
-------------------------------------------------------*/
#pragma ベクトル=URX0_VECTOR
__interrupt ヴォイド RE_ISR(ヴォイド)
{
EA=0;
led3 = LED_ON;
受信 = U0DBUF;
IF(type==1) // type=1。これは受信文字がタイマーオーバーフロー期間を設定するために使われていることを示します
{
タイプ=0;
スイッチ(受信)
{
ケース「0」:// タイマーのオーバーフロー期間は0.5秒です
{
SET_TIMER1_PERIOD(TIMER1_OVF_dot5SEC);
休憩;
}
ケース「1」:// タイマーのオーバーフロー期間は1秒です
{
SET_TIMER1_PERIOD(TIMER1_OVF_1SEC);
休憩;
}
ケース『2』:// タイマーのオーバーフロー期間は2秒です
{
SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);
休憩;
}
}
}
それ以外の場合は IF(type==2) // type=2(受信文字がスリープ制御に使われることを示します)
{
タイプ=0;
LED1 = LED_OFF;
led2 = LED_OFF;
led3 = LED_OFF;
スイッチ(受信)
{
ケース「1」:// 電源モードPM1に入力
{
SET_POWER_MODE(1);
休憩;
}
ケース『2』:// 電源モードPM2に入力
{
SET_POWER_MODE(2);
休憩;
}
ケース『3』://電源モードPM3に入力
{
SET_POWER_MODE(3);
休憩;
}
}
}
それ以外の場合は if(type==0) // type=0。これは受信文字が制御コマンドのタイプである @ または $ であることを示します
{
if(receive=='@')
{
タイプ=1; 「@」は、次の文字がオーバーフロー期間を設定することを示すために受信されます
}
それ以外の場合は(receive=='$')
{
タイプ=2; 「$」が受信され、次の文字がシステムスリープ制御に使われることを示します
}
}
led3 = LED_OFF;
EA=1;
}
=LED_OFF;
TIMER1_OVERFLOW_INT_SETFLAG(INT_CLR); 割り込み標識をクリアしてください
EA=1; オープン・インターセプション
}
/* 主函数
-------------------------------------------------------*/
ヴォイドメイン(ヴォイド)
{
SET_MAIN_CLOCK_SOURCE(クリスタル); システムクロックを32MHzのクリスタルオシレーターに設定します
led_init(); LEDの初期化
uart0_init(); シリアルポートUART0の初期化
timer1_init(); タイマー1が初期化します
watchdog_init(); ウォッチドッグの初期化
while(1)
{
WDT_RESET(); 犬に絶えず餌をあげましょう
}
}/********************************************************************
メインプログラム
********************************************************************/
/* 全局变量
-------------------------------------------------------*/
符号なし文字出力[6]={0}; 温度データはシリアル出力が容易にできるよう保存されます
署名なしのチャーレシーブ; 受信した文字を保存します
符号なしのcharタイプ=0; 受信文字の型フラグは0/1/2に設定されています"module.h"[url=][/url]
5. テストああ~ついにコードが貼り付けられた。本当に疲れる。この小さなシステムをテストしよう:
(1) タイミングサンプリング
シリアルポートを開き、IARデバッグを開始すると、LED1が点灯し、シリアルポートツールの温度値が常に生成され、サンプリング間隔は2秒と判定されています。
(2) サンプリング間隔制御
シリアルポートツールで「@1」を入力し、サンプリング間隔をテストすると、それが1になっていることがわかります。 「@0」と入力すると、サンプリング間隔が0.5秒に変更されます。
(3) 睡眠コントロール
シリアルポートツールで「$1」と入力すると、すべてのLEDが消え、温度サンプリングも停止しています:
テストの結果、システムは正常かつ安定して動作し、基本的に要件を満たしています。
ソースコードが必要な学生たちダウンロードはこちらをクリックしてください
6. 結論本論文では、やや包括的な実験を例として、CC2430のオンチップリソースを統合して比較的標準化された小規模システムを書く方法を示します。 数日後には、私も皆さんもCC2430を簡単に操作できるように、hal.hの簡単なユーザーマニュアルを書く時間を取るつもりです。
次に、CC2430オンチップリソースの研究を終え、TI Z-Stackプロトコルスタックの学習に専念します~
このシリーズのブログ記事は一時的に終了しましたが、ジグビーの旅はこれからも続きます。 これからの景色は未だに分かりませんが、著者は皆と共に困難を乗り越え、浮き沈みを味わい、必ず得られるものがあると信じています。
お楽しみに:「TI Z-Stackに参加」ブログ記事!