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 2026 ExpyDoc