|
1. 上層と下層の接続 前回のセクションでは、ADCの使用について話し、オンチップ温度センサーをサンプリングしました。 実際のプロジェクトでは、センサーの数が多いことが多く、大量の変換データを処理する必要があります。 このデータを移動するとCPUに大きな負担がかかります。 CPUを解放し、他の作業にエネルギーを与えるためには、DMA(ダイレクトメモリアクセス)が役立ちます~ 以下の紹介はZigbeeテクノロジー実践チュートリアルからの抜粋です: DMAはダイレクトメモリアクセスの略称で、「ダイレクトメモリアクセス」の略です。 これは高速データ伝送モードで、ADC/UART/RFトランシーバやメモリなどの周辺機器が「DMAコントローラ」の制御下で直接データを交換し、CPUの介入がほとんどありません。 データ転送の開始と終了時に少量の処理を行うことに加え、CPUは転送中に他の作業を行うこともできます。 こうすることで、CPUとこれらのデータ相互作用はほとんどの場合並列で動作します。 その結果、システムの全体的な効率が大幅に向上します。
紹介からもわかるように、DMAは多くのシナリオで使えます。 この実験は最も単純なDMA伝送のみを含み、DMAの一般的な利用を示すことを目的としています。 DMAの他のシナリオへの応用については、将来的に包括的な実験で実装される予定です。 2. DMA伝送実験(1) 実験への導入配列文字sourceStringコンテンツはDMAを介して文字配列に転送されますdestString変換結果はシリアルポートを通じてPCに表示されます。 (2) プログラムフローチャート
(3) 実験的ソースコードと解析/*
実験的説明:文字配列sourceStringの内容はDMAを通じて文字配列destStringに転送され、変換結果はシリアルポートを通じてPC上で表示されます。
*/
#include
#define リード1 P1_0
#define led2 P1_1
#define led3 P1_2
#define led4 P1_3
/*用于配置DMA的结构体
-------------------------------------------------------*/
#pragma bitfield=反転
タイプdef struct
{
署名なし チャーSRCADDRH; //源地址高8位
署名なし チャーSRCADDRL; //源地址低8位
署名なし チャーDESTADDRH; //目的地址高8位
署名なし チャーDESTADDRL; //目的地址低8位
署名なし チャーヴレン:3; //长度域模式选择
署名なし チャーLENH:5; //传输长度高字节
署名なし チャーLENL:8; //传输长度低字节
署名なし チャー語数:1; //字节(byte)或字(word)传输
署名なし チャーTMODE:2; //传输模式选择
署名なし チャートリグ:5; //触发事件选择
署名なし チャーSRCINC:2; //源地址增量:-1/0/1/2
署名なし チャーDESTINC:2; //目的地址增量:-1/0/1/2
署名なし チャーIRQMASK:1; //中断屏蔽
署名なし チャーM8:1; //7或8bit传输长度,仅在字节传输模式下适用
署名なし チャー優先事項:2; //优先级 }DMA_CFG; #pragma bitfields=default
/*系统时钟初始化
-------------------------------------------------------*/
虚無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 =1; //关闭所有LED led2 =1; led3 =1; led4 =1;
}
/*UART0通信初始化
-------------------------------------------------------*/
虚無Uart0Init(署名なし チャーStopBits、署名なし チャーパリティ)
{ P0SEL |= 0x0C; //初始化UART0端口,设置P0.2与P0.3为外部设备IO口 PERCFG&= ~0x01; 最初のオプション位置としてUART0を選択し、すなわちRXDからP0.2、TXDからP0.3へ
U0CSR =0xC0; UARTモードに設定し、受容体を有効にします
U0GCR =11; U0BOUD =216; //设置UART0波特率为115200bps
U0UCR |= StopBits|パリティ; //设置停止位与奇偶校验
}
/*UART0发送数据
-------------------------------------------------------*/
虚無 Uart0Send(署名なし チャーデータ)
{
ただし(U0CSR&0x01); //等待UART空闲时发送数据 U0DBUF = data;
}
/*UART0发送字符串
-------------------------------------------------------*/
虚無Uart0SendString(署名なし チャー*s)
{
ただし(*s !=0) //依次发送字符串s中的每个字符 Uart0Send(*s++);
}
/*主函数
-------------------------------------------------------*/
虚無メイン(虚無)
{ DMA_CFG dmaConfig; //定义配置结构体
署名なし チャーsourceString[]=「俺はソースストリングだ!"; //源字符串
署名なし チャーdestString[サイズ(sourceString)]=「俺はdestStringだ!"; //目的字符串
チャー私;
チャー誤差=0;
xtal_init(); //系统时钟初始化 led_init(); Uart0Init(0x00,0x00); //UART初始化
Uart0SendString(sourceString); //传输前的原字符数组 Uart0SendString(destString); //传输前的目的字符数组
//配置DMA结构体 dmaConfig.SRCADDRH=(署名なし チャー)((署名なし 知力)&sourceString >>8); //源地址 dmaConfig.SRCADDRL=(署名なし チャー)((署名なし 知力)&sourceString);
dmaConfig.DESTADDRH=(署名なし チャー)((署名なし 知力)&destString >>8); //目的地址 dmaConfig.DESTADDRL=(署名なし チャー)((署名なし 知力)&destString);
dmaConfig.VLEN=0x00; //选择LEN作为传送长度
dmaConfig.LENH=(署名なし チャー)((署名なし 知力)サイズ(sourceString)>>8); //传输长度 dmaConfig.LENL=(署名なし チャー)((署名なし 知力)サイズ(sourceString));
dmaConfig.WORDSIZE=0x00; //选择字节(byte)传送
dmaConfig.TMODE=0x01; //选择块传送(block)模式
dmaConfig.TRIG=0; トリガーなし(手動トリガーと理解できます)
dmaConfig.SRCINC=0x01; //源地址增量为1
dmaConfig.DESTINC=0x01; //目的地址增量为1
dmaConfig.IRQMASK=0; //DMA中断屏蔽
dmaConfig.M8=0x00; //选择8位长的字节来传送数据
dmaConfig.PRIORITY=0x02; //传输优先级为高
DMA0CFGH=(署名なし チャー)((署名なし 知力)&dmaConfig >>8); //将配置结构体的首地址赋予相关SFR DMA0CFGL=(署名なし チャー)((署名なし 知力)&dmaConfig);
DMAARM=0x01; //启用配置
DMAIRQ=0x00; //清中断标志 DMAREQ=0x01; //启动DMA传输
ただし(! (DMAIRQ&0x01)); //等待传输结束
に対して(i=0; 私<サイズ(sourceString); i++) //校验传输的正确性 {
もし(sourceString!=destString) error++; }
もし(エラー==0) //将结果通过串口传输到PC { Uart0SendString(「正解!」); Uart0SendString(destString); //传输后的目的字符数组 }
そうでなければ Uart0SendString(「エラー!」);
ただし(1);
}
DMAの基本的な使用手順は以下の通りです:DMAの設定 → 設定を有効にする → DMA転送を開始→DMA転送が完了するまで待ちます。以下はそれぞれです: (1) DMAの設定まず、DMAは設定が必要ですが、DMAの構成は特殊です。一部のSFRに直接値を割り当てるのではなく、外部で構造を定義し、それに値を割り当て、その構造の最初のアドレスの上位8ビットを割り当てますDMA0CFGHこれにより、下位8桁となりますDMA0CFGL。 (構成構造の詳細な説明についてはCC2430中国語マニュアルをご参照ください) CC2430のヒント上記のソースコードにおける構成構造体の定義について明確にすべき点が2つあります: (1) ビットドメイン この構造体を定義する際には、多くのコロン(:)が使われ、その後に「ビットフィールド」と呼ばれる数字が続きます。 ビットドメインとは、情報が保存時に1バイト全体を占める必要はなく、数ビットまたは1ビットの2進数だけを占有することを意味します。 例えば、スイッチング量を格納する際には状態が0と1の2つしかなく、1ビットの2進数を使うことができます。 ストレージ容量を節約し処理を容易にするために、Cは「ビットフィールド」または「ビットフィールド」と呼ばれるデータ構造を提供します。 いわゆる「ビットフィールド」は、バイト内のバイナリをいくつかの異なる領域に分割し、それぞれの領域におけるビット数を表します。 各ドメインにはドメイン名があり、プログラム内でドメイン名による操作が可能です。 これにより、複数の異なるオブジェクトをバイトバイナリビットフィールドで表現することが可能になります。 (2) 抽象的な共通関数 注意深い読者は、構造体に値を割り当てる際には、16ビットの符号なしint型値を2つの8ビット符号なし文字型値に割り当てることがよくわかります。以下のように。 dmaConfig.SRCADDRH=(署名なし チャー)((署名なし 知力)&sourceString >>8); //源地址 dmaConfig.SRCADDRL=(署名なし チャー)((署名なし 知力)&sourceString);
この種の頻繁に使われる関数については、以下のように一般関数として抽象化しましょう。 #define SET_WORD(destH, destL, word)
する{ destH=(署名なし チャー)((署名なし 知力)単語>>8); destL=(署名なし チャー)((署名なし 知力)単語); }ただし(0)
将来的には、同様の分割操作を行う際には、以下のように直接呼び出すことができます。 SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, &sourceString);
(2) 設定を有効にするまず、構造物の最初のアドレス&dmaConfig高・低8ビットはそれぞれSFRに割り当てられていますDMA0CFGHそしてDMA0CFGL(ここで0はチャネル0の構成を表し、CC2430は5つのDMAチャネルを含み、ここではチャネル0が使われます。) はいDMAARM.0チャンネル0の設定を有効にするために値1を割り当て、そのチャンネル0が動作モードになるようにします。 (3) DMA伝送を有効にする:右DMAREQ.0チャネル0のDMA送信を開始するために値を1に割り当てます。 (4) DMAの送信を待つ:チャネル0のDMAが送信された後、割り込みがトリガーされ、チャネル0の割り込みフラグがトリガーされますDMAIRQ.0自動的に1に設定されます。 2つの文字列の各文字を比較し、検証結果がPCに送信されます。 (4) 実験結果まずシリアルポートデバッグツールを開き、CC2430デバッグを開始すると、次の画面が表示されます。
あなたは見つけるでしょうdestString内容は完全に明かされましたsourceString満たされた。 完成です~ 3. 結論このセクションではDMAの使い方を紹介しますが、とてもシンプルですが、基本的な使い方は理解できていると思いますし、将来複雑な使用状況に直面した際に冷静に分析することも可能です。 どんなに優れたデスクトップでもフリーズし、同様に組み込みシステムも必然的に停滞します。 次のセクションでは、非常に効果的な体系的リセットの方法、ウォッチドッグを紹介します。
|