1-5 A/D変換プログラム 公開講義(組込みプロセッサによる音信号処理入門) 岐阜県情報技術研究所 田畑 克彦 1 A/D変換 アナログ信号をディジタル信号に変換する アナログの電圧値を測定して、その値をデータレジスタに格納 アナログ信号 標本化 標本化 アナログ信号 量子化 ディジタル信号 量子化 ディジタル信号 2 A/Dコンバータの概要 SH7144FのA/Dコンバータ 分解能:10ビット 入力チャネル: 8チャネル (2個の独立したA/D変換モジュール内蔵)A/D0, A/D1 変換時間:1チャネル当たり5.4μs(Pφ=25MHz動作時),6.7μs(Pφ=20MHz動作時) 動作モード:3種類 シングルモード:1チャネルのA/D変換 連続スキャンモード:1~4チャネルの繰り返しA/D変換 1サイクルスキャンモード:1~4チャネルの連続A/D変換 データレジスタ: A/D変換結果は各入力チャネルに対応した16ビットデータレジスタに格納 サンプル&ホールド機能付き A/D変換開始方法:3種類 ソフトウェア マルチファンクションタイマパルスユニット(MTU)による変換開始トリガを選択可能 外部トリガ信号 割り込み要因 A/D変換終了割り込み要求(ADI)を発生 入力電圧-変換値 0V :0 3.3V:210 -1= 1023 bit = 0x3ff bit (max) 3 A/D データレジスタ0~7(ADDR0~ ADDR7) 変換結果が格納される 変換データは上位10ビットに格納され,下位6ビットには常に0が 補充される ビット 15 14 13 12 11 10 9 10 ビットのデータ 8 7 6 5 4 3 2 1 0 0 0 0 0 0 0 4 A/D コントロール/ステータスレジスタ (ADCSR) 動作モードや割り込みなどの設定と,現在の状態フラグ シングルモード 指定された1 チャネルのアナログ入力を1 回A/D 変換 1. 2. 3. 4. MTUや外部トリガ入力によってADCRのADSTビットが1にセットされると選択 されたチャネルのA/D変換を開始 A/D変換結果をA/Dデータレジスタに転送 A/D変換終了後,ADCSRのADFビットが1にセットされる.このとき,ADIEビッ トが1にセットされているとADI割り込み要求を発生 ADSTビットはA/D変換中は1を保持し,変換が終了すると自動的にクリアさ れてA/D変換器は待機状態になる 連続スキャンモード 指定されたチャネルのアナログ入力を順次連続してA/D 変換 5 ADCR,ADTSR その他のレジスタの設定 ADCR(コントロールレジスタ) 変換クロックや変換開始などの設定 ADTSR(外部トリガセレクトレジスタ) 外部からの信号を変換開始のトリガにする場合の設定用 スタンバイ設定 MTUと同様 6 例題1-5-1:電圧表示プログラム 可変抵抗で変化する電圧を取得し,その電圧をLED4ビットで、 2進数表示するプログラム 仕様 MTU4を使用し,定期的にA/D変換を行う 使用A/DコンバータはAD1 信号は AN4より入力 サンプリング・レート 48kHz 7 プログラムの概要 A/Dコンバータ チャネル0,シングル・モード サンプリング・レート 48kHz MTUのコンペアマッチにより起動 MTUはコンペアマッチでA/Dコンバータを起動できる 処理の流れ タイマのコンペアマッチによりA/D変換スタート A/D変換終了割り込みで処理スタート 取得した電圧をLEDで表示 8 プログラムの流れ init_ad() main() 初期化 ポートレジスタ設定 (データシート17.1.9) ADCの初期化 MTUの初期化 while(1) 初期化 動作の設定 変換終了で割り 込み (データシート15.3) init_mtu() 割り込み処理 int_adi1() 初期化 TGRAのコンペア マッチでAD変換 スタート 電圧に応じて LEDを表示 MTUスタート 9 タイムチャート プログラムの処理の時間経過 メインの処理(割り込みハンドラ)以外に,AD変換処理,割り込み処理(レジ スタ退避・復帰) A/DコンバータをMTUから自動で起動 次の回のAD変換の間も処理を継続可能 コンペアマッチ A D コンペアマッチ 割 り 込 み A D 割 り 込 み メイン処理 10 サンプリング周波数 サンプリング(標本化)周波数から設定値を求める サンプリング周波数=MTUの割り込み周期 今回は,割り込み周期はTGRAで設定 TGRAの設定方法 TGRA=(カウンタ周波数/サンプリング周波数)-1 -1は,マッチの次のカウント時にクリアされるため 今回の場合:48kHzサンプリング 24MHz(Pφ/1)でカウント(MTU4.TCR.BIT.TPSC = 0;) カウント回数は24MHz/48kHz=500 よってTGRAに499を設定( MTU4.TGRA = 499; ) 11 A/D変換結果のビット配置 A/Dコンバータの変換結果のビットシフト 上位4ビットをPE11~14へ A/D変換の結果は上位10ビットに格納される 16 9 ADDR 4 8 8 7 6 5 4 3 2 1 1 0 input ADDR4 6; 下位ビットにシフトする 16 8 9 8 7 上位4ビットを利用 1 6 5 4 3 2 PE 15 0 input 3; 8 PE.BYTE.H 1 1 9 8 7 6 PE 14 PE 13 PE 12 PE 11 PE 10 PE 9 PE 8 12 割り込みハンドラの設定 MTUの場合と同様に,A/Dコン バータの変換終了割り込みの割 り込みハンドラを設定 intprg.c 全ての割り込み要因に対するハ ンドラの設定が,vect.hと vecttbl.c,intprg.cに書かれてい る vect.h 各関数が割り込みハンドラであ るとコンパイラに示すための pragma宣言 … // 137 A/D ADI1 //追加 void int_adi1(); void INT_ADI1(void){ int_adi1(); } //コメントアウト //void INT_ADI1(void){/* sleep(); */} … vecttbl.c ベクタテーブルの宣言 intprg.c vect.hで書かれた各関数の実体 13 電圧表示プログラム(1/3) MTU4の初期化関数 MTU回路の起動 立ち上がりエッジでカウント TGRAコンペアマッチでクリア クロックサイクルの設定 void init_mtu() { MST.CR2.BIT._MTU = 0; //MTUを起動 //立ち上がりエッジ MTU4.TCR.BIT.CKEG = 0; //TGRAのコンペアマッチでクリア MTU4.TCR.BIT.CCLR = 1; //P_phi/1(24MHz)でカウント MTU4.TCR.BIT.TPSC = 0; //24Mhz / 48kHz = 500 MTU4.TGRA = 499; //カウンタを0に MTU4.TCNT = 0; 24MHz TGRAの値を設定 1秒に48000回サンプリング 24MHz / 48kHz – 1 = 499 通常動作 TGRAマッチでA/Dコンバータを 起動 タイマスタート //通常動作(16ビットタイマー) MTU4.TMDR.BIT.MD = 0; //TGRAのコンペアマッチでAD変換開始 MTU4.TIER.BIT.TTGE = 1; MTU.TSTR.BIT.CST4 = 1; //MTU4をスタート } 14 電圧表示プログラム(2/3) A/Dコンバータの初期化関数 AD1回路の起動 シングルモード AN4入力 変換終了で割り込み 1サイクル・スキャン 変換時間の設定 MTUトリガによる起動を許可 メイン関数 LEDポートの設定 割り込みマスクのクリア A/Dコンバータの初期化関数の呼 び出し MTUの初期化関数の呼び出し 無限ループ void init_ad() { MST.CR2.BIT._AD1 = 0; //AD1を起動 AD1.ADCSR.BIT.ADM = 0; //シングルモード AD1.ADCSR.BIT.CH = 0; //AN4入力 AD1.ADCSR.BIT.ADIE = 1; //割り込み許可 INTC.IPRG.BIT._AD = 1; //AD割り込みの優先度を1に AD1.ADCR.BIT.ADCS = 0; //ワンサイクルスキャン AD1.ADCR.BIT.CKS = 3; //P_phi/4時間で変換 AD1.ADCR.BIT.TRGE = 1; //トリガによる開始は有効 AD1.ADTSR.BIT.TRGS = 2; //MTUトリガ起動を許可 } void main(void) { //初期化 PFC.PEIORL.BIT.B14 = 1; //PE14を出力に設定 PFC.PEIORL.BIT.B13 = 1; //PE13を出力に設定 PFC.PEIORL.BIT.B12 = 1; //PE12を出力に設定 PFC.PEIORL.BIT.B11 = 1; //PE11を出力に設定 set_imask(0); //割り込みマスクをクリア init_ad(); //ADコンバータの初期化 init_mtu(); //MTUの初期化 while (1); } 15 電圧表示プログラム(3/3) 割り込みハンドラ A/D変換終了フラグのクリア A/D変換結果の取得 ビットシフトで場所をあわせ, ビット反転して表示 void int_adi1() { int input; AD1.ADCSR.BIT.ADF = 0; //AD変換終了フラグのクリア input = AD1.ADDR4.WORD >> 6; //変換結果の取得 PE.DRL.BYTE.H = ((~(input >> 3)) & 0x78) | (PE.DRL.BYTE.H & 0x87);//ビット表示(ビット反転) } 0で点灯のため メイン関数 LEDポートの設定 割り込みマスクのクリア A/Dコンバータ初期化関数の呼び 出し MTUの初期化関数の呼び出し 無限ループ void main(void) { //初期化 PFC.PEIORL.BIT.B14 = 1; //PE14を出力に設定 PFC.PEIORL.BIT.B13 = 1; //PE13を出力に設定 PFC.PEIORL.BIT.B12 = 1; //PE12を出力に設定 PFC.PEIORL.BIT.B11 = 1; //PE11を出力に設定 set_imask(0); //割り込みマスクをクリア init_ad(); //ADコンバータの初期化 init_mtu(); //MTUの初期化 while (1); } 16 演習1-5-2:電圧表示方法の変更 入力された電圧を,2進数表現ではなく,LEDの個数(0~4個の5 段階)で表示する 電圧が高くなるほど,多くのLEDを表示する 変更内容 入力値のビットをそのままLEDに出力するのではなく,入力値に応じて点灯 するLEDを変更する 17 例題1-5-3:音量表示プログラム A/Dコンバータを用いてPCから音を入力し,大きな音が入力され たらLEDを点灯するプログラム 例題1-5-1と基本は同じ 電圧ではなく音量でLED点灯・消灯を判断する LED表示は1 ビット 仕様 MTU4を使用し,定期的にA/D変換を行う 使用A/DコンバータはAD0 信号は AN0より入力 サンプリング・レート 48kHz 振幅(電圧-平均)の二乗和が 閾値以上の場合「大きな音」とする 18 プログラムの概要 処理の流れ タイマのコンペアマッチによりA/D変換スタート A/D変換終了割り込みで処理スタート 最初の8000回の割り込みで平均値を計算 以後は1000回ずつパワーを計算し,大きな音の有無をチェック 次の1000回の間,LEDを以下の状態に 音は大きい:点灯 音は小さい:消灯 19 プログラムの流れ init_ad() main() 初期化 ポートレジスタ設定 (データシート17.1.9) ADCの初期化 MTUの初期化 while(1) 初期化 動作の設定 変換終了で割り 込み (データシート15.3) init_mtu() 割り込み処理 int_adi1() 初期化 TGRAのコンペア マッチでAD変換 スタート 電圧に応じて LEDを表示 MTUスタート 20 割り込みハンドラの設定 AD1からAD0に変更 INT_ADI0(); … // 136 A/D ADI0 //追加 void int_adi0(); void INT_ADI0(void){int_adi0();} //コメントアウト //void INT_ADI0(void){/* sleep(); */} … 21 音量表示プログラム(1/4) MTU4の初期化関数 MTU回路の起動 立ち上がりエッジでカウント TGRAコンペアマッチでクリア クロックサイクルの設定 void init_mtu() { MST.CR2.BIT._MTU = 0; //MTUを起動 //立ち上がりエッジ MTU4.TCR.BIT.CKEG = 0; //TGRAのコンペアマッチでクリア MTU4.TCR.BIT.CCLR = 1; //P_phi/1(24MHz)でカウント MTU4.TCR.BIT.TPSC = 0; //24Mhz / 48kHz = 500 MTU4.TGRA = 499; //カウンタを0に MTU4.TCNT = 0; 24MHz TGRAの値を設定 1秒に48000回サンプリング 24MHz / 48kHz - 1 = 499 通常動作 TGRAマッチでA/Dコンバータを 起動 タイマスタート //通常動作(16ビットタイマー) MTU4.TMDR.BIT.MD = 0; //TGRAのコンペアマッチでAD変換開始 MTU4.TIER.BIT.TTGE = 1; MTU.TSTR.BIT.CST4 = 1; //MTU4をスタート } 例題1-4-1と同じ 22 音量表示プログラム(2/4) A/Dコンバータの初期化関数 AD0回路の起動 シングルモード AN0入力 変換終了で割り込み 1サイクル・スキャン 変換時間の設定 MTUトリガによる起動を許可 メイン関数 LEDポートの設定 割り込みマスクのクリア A/Dコンバータの初期化関数の呼 び出し MTUの初期化関数の呼び出し 無限ループ void init_ad() { MST.CR2.BIT._AD0 = 0; //AD0を起動 AD0.ADCSR.BIT.ADM = 0; //シングルモード AD0.ADCSR.BIT.CH = 0; //AN0入力 AD0.ADCSR.BIT.ADIE = 1; //割り込み許可 INTC.IPRG.BIT._AD = 1; //AD割り込みの優先度1 AD0.ADCR.BIT.ADCS = 0; //ワンサイクルスキャン AD0.ADCR.BIT.CKS = 3; //P_phi/4時間で変換 AD0.ADCR.BIT.TRGE = 1; //トリガによる開始は有効 AD0.ADTSR.BIT.TRGS = 2; //MTUトリガ起動を許可 } void main(void) { //初期化 PFC.PEIORL.BIT.B15 = 1; //PE15を出力に設定 set_imask(0); //割り込みマスクをクリア init_ad(); //ADコンバータの初期化 init_mtu(); //MTUの初期化 while (1); } 23 音量表示プログラム(3/4) 割り込みハンドラ(前半) A/D変換終了フラグのクリア A/D変換結果の取得 16ビットレジスタの上位10ビット にデータが収納されているので, 右に6ビットシフト 音の平均値の算出 A/Dの値を足し合わせていく 8000回分になったら平均値を 求める 平均値算出フラグのクリア 回数の変数をクリア void int_adi0() { static int time = 0; //変換回数 static char calc_avg_flag = 1; //平均値計算フラグ static int avg = 0; //音の平均値 static int power = 0; //パワー int input; AD0.ADCSR.BIT.ADF = 0; //AD変換終了フラグのクリア input = AD0.ADDR0.WORD >> 6; //変換結果の取得 if (calc_avg_flag) { //音の平均値の算出 avg += input; if (time++ == 8000) { //8000回の平均値を求め,フラグをクリア avg /= 8000; calc_avg_flag = 0; time = 0; } } 24 音量表示プログラム(4/4) 割り込みハンドラ(後半) …続き //音検出 power += (input-avg) * (input-avg); if (++time == 1000) { //1000回の平均で音の有無をチェック if (power / 1000 > 0x100) { PE.DRL.BIT.B15 = 0; //LED ON } else { PE.DRL.BIT.B15 = 1; //LED OFF } power = 0; time = 0; } 音検出 パワーを足し合わせていく 平均値との差の二乗 1000回分たまったら平均を求め, 音の有無をチェック パワーの大きさが一定値以上な らばLEDを点灯 大きさが一定値以下ならLEDを 消灯 パワーと計測回数のクリア } } 25 演習1-5-4:音量レベル表示 入力された音の大きさに応じて複数のLEDを表示する PE15のLEDで1bit表示からPE11~14の4bit表示に変更する 変更内容 演習1-5-2と同様 26
© Copyright 2025 ExpyDoc