忍者ブログ

Fグループ電子工作講座

秋月電子SH7125ボードで始めるマイコン開発

AD変換

A/D変換とは

アナログ・デジタル変換の略

マイコンにおける入力は基本的にONかOFFかのみ(デジタル)を取り扱います。
SH7125においては電源電圧が5Vであるため、0Vか5VかでON/OFFを判定します。
これに対してA/D変換では0~5Vの間の中途半端な電圧値(アナログ電圧例えば2.67Vとか)を取り扱います。

マイコンに対して0~5Vで入力されたアナログ電圧をマイコン内で処理するためある範囲の値に置き換えます。
SH7125に搭載されたA/D変換は10bitの分解能なので、0~5Vを0~1023(0b1111111111)の間の整数値に変換します。
このアナログ電圧値をマイコン内のデジタル値に変換する機能をA/D変換と呼びます。

A/D変換の流れ

A/D変換のプログラムは以下の流れで動かします。

1) 端子の特殊機能設定
2) A/D変換の機能設定
3) A/D変換の実行
4) 変換結果の取得
以下、手順3)と4)を繰り返します。

端子の特殊機能設定

SH7125ではA/D変換機能は全てポートFに割り振られています。
ハードウェアマニュアルの「ピン配置図」を見てみましょう。

64ピン仕様と48ピン仕様の図がありますが、SH7125は64ピン仕様です。
AN0~AN7がアナログ入力に対応したピンですが、PF0~PF7に割り振られていることが分かります。
マ イコンのピン色々な機能に割り当てることができますがPF0~PF7にはAN以外の表記がありません。しかもハードウェアマニュアルの「端子機能」表を見るとPFは入力のみで出力に設定できないことが分かります。ということでポートFは汎用入力ポート(PF)として使うか、アナログ入力(AN)として使う かの2択となります。アナログ入力として設定した状態でも汎用入力ポートの代用としても使用することができます。
・PF以外にアナログ入力を割り当てることができない
・PFはアナログ入力以外の特殊機能が無い
・PFは入力としてしか設定できない
・アナログ入力に設定しても汎用入力として使うことができる
という事で、PFは全てアナログ入力に割り振ってしまいます。

おまけにPFにはピンファンクションコントローラの設定項目がありません。

という事で、SH7125のAD変換において端子の特殊機能設定は何もすることがありません

A/D変換の機能設定

続いてA/D変換の機能設定(初期化)を行います。

void init_ADC(void){
//  ADCモジュールのスタンバイ解除
    STB.CR4.BIT._AD0=0;    //AN0-3
    STB.CR4.BIT._AD1=0;    //AN4-7

//  A/D コントロール/ステータスレジスタの設定
    AD0.ADCSR.BIT.ADIE  =0;    // A/Dインタラプト(ADI)イネーブル
    AD0.ADCSR.BIT.TRGE  =0;    // トリガイネーブル
    AD0.ADCSR.BIT.CONADF=0;    // ADF コントロール
    AD0.ADCSR.BIT.STC   =0;    // ステートコントロール         
    AD0.ADCSR.BIT.CKSL  =0;    // A/D変換時間;Pφ/4
    AD0.ADCSR.BIT.ADM   =1;    // 変換動作モード(4チャネルスキャンモード)
    AD0.ADCSR.BIT.ADCS  =0;    // A/D連続スキャン(1サイクルスキャン)
    AD0.ADCSR.BIT.CH    =3;    // チャネルセレクト(AN0-3全て)

    AD1.ADCSR.BIT.ADIE  =0;    // A/Dインタラプト(ADI)イネーブル
    AD1.ADCSR.BIT.TRGE  =0;    // トリガイネーブル
    AD1.ADCSR.BIT.CONADF=0;    // ADF コントロール
    AD1.ADCSR.BIT.STC   =0;    // ステートコントロール         
    AD1.ADCSR.BIT.CKSL  =0;    // A/D変換時間;Pφ/4
    AD1.ADCSR.BIT.ADM   =1;    // 変換動作モード(4チャネルスキャンモード)
    AD1.ADCSR.BIT.ADCS  =0;    // A/D連続スキャン(1サイクルスキャン)
    AD1.ADCSR.BIT.CH    =3;    // チャネルセレクト(AN4-7全て)
}
※2017/02/13 関数名をInit_ADCからinit_ADCへ変更しました。

解説

AD変換機能が休眠状態のため、ADCモジュールのスタンバイ解除を行います。
AN0-3とAN4-7で設定項目が分かれているのでそれぞれスタンバイを解除します。
スタンバイコントロールレジスタに0を入力するとスタンバイが解除されます。

続いてコントロールステータスレジスタでどの様にA/Dを実行するか設定します。
ADIE:AD変換終了時に自動的に関数を実行したい場合に設定します。(完了割込:未使用)
TRGE:PA11に入力が来た時にAD変換を自動実行する際に設定します。(開始割込:未使用)
CONADF:2チャンネルスキャンモードを使用する際に設定します。(未使用)
STC:AD変換の時間設定を行います。
CKSL:AD変換の動作速度(クロック)を設定します。
ADM:いくつの端子を同時にAD変換するかモードを設定します。
ADCS:1回のみ変換するか、変換し続けるか設定します。
CH:どの端子のAD変換を実行するか設定します。

AD1(AN4-7)についても全く同じ設定を使用します。
A/D変換の初期設定はここまでです。

A/D変換の実行

/*==========アナログ変換実行関数==========*/
void check_ai(){
    AD0.ADCR.BIT.ADST = 1;        //AN0-3 AD変換開始
    AD1.ADCR.BIT.ADST = 1;        //AN4-7 AD変換開始
    while( AD0.ADCSR.BIT.ADF == 0 || AD1.ADCSR.BIT.ADF == 0 ){}    //変換終了待ち
}

ADCR.BIT.ADSTを1に設定するとAD変換が開始されます。
変換中はADCSR.BIT.ADFが0で、変換が完了すると1になります。
AD0、AD1ともにADCSR.BIT.ADFが1になった時点でAD変換完了です。

これでA/D変換が実行されます。
変換した結果は自動的にAD0.ADDR0~AD0.ADDR3およびAD1.ADDR4~AD1.ADDR7に格納されます。この結果は次に変換を開始するまで保持されたままになります。

変換結果の取得

0-5V を0-1023に変換した10bit分のデータがADDRに格納されるのですが、ADDRは16bitの変数です。16bitの下位10bitに格納され ていればそのまま取ってくるだけで良いのですが、上位10bitに格納されています。仮にAN0の変換結果が1023(0b11 1111 1111)だったとすると、AD0.ADDR0は65472(0b1111 1111 1100 0000)となります。
上位層としてはアナログ変換端子0~端子7の結果0-1023で知りたいのですが、実際にはAD0とAD1を切り替えつつ65472を1023に変換する必要があります。これを毎回上位層側で記述すると混乱が生じて入力ミスをすることになります。
そこでこの変換を自動的に行う関数を作成しておきます。

/*==========アナログ入力取得関数(ビット番号)==========*/
short get_ai(int bit){
    unsigned short value;    //一時保管用変数

    if( bit<0 || bit>7 )    //存在しないビットを指定した場合
        return -1;            //関数を強制終了

    value = (bit==0)? AD0.ADDR0:    //ビット番号に応じて参照する値を一時保管
            (bit==1)? AD0.ADDR1:
            (bit==2)? AD0.ADDR2:
            (bit==3)? AD0.ADDR3:
            (bit==4)? AD1.ADDR4:
            (bit==5)? AD1.ADDR5:
            (bit==6)? AD1.ADDR6:
            (bit==7)? AD1.ADDR7:0;

    return (short)(value>>6);        //下位6bitを削除して値を出力
}

3項演算子「 = ()? : 」と ビットシフト「>>」についてはポート数増加の回を参照ください。

ソースファイルとヘッダファイルの作成と組み込み

ファイル作成

A/D変換関連のファイル名を「ADConv.c」「ADConv.h」とします。
ソースファイルADConv.cの中身は上記関数の実体です。
ADConv.cの一番上でiodefine.hとADConv.hをincludeしてください。
ヘッダファイルADConv.hの中身は関数のプロトタイプ宣言のみです。
ファイルの作成方法はSHプログラム分割の回を参照ください。
ダウンロード:ADConv.cADConv.h

ここで今後使いまわすプロジェクトを新規作成しておきたいと思います。
HEW起動、ファイル → 新規ワークスペース
ワークスペース名:sh7125_base01
CPUシリーズ:SH2
CPUタイプ:SH7125
その他は初期設定のままでOK

ファイルの読み込み

作成したプロジェクトのあるフォルダにでSHプログラム分割の回作成したio_setup.cio_setup.hと今回作成したADConv.c、ADConv.hをコピーします。

プロジェクト → ファイルの追加
io_setup.cとADConv.cを追加

これでビルドが通ればAD変換が使用可能になります。

ソースファイルの編集

メインのソースファイルはSHプログラム分割の回の物をベースに使用します。
コピーしてまるごとsh7125_base01.cに上書きします。
更にAD変換を使った処理を行うように編集します。

#include "iodefine.h"    //マイコン設定に必要な情報読み込み
#include "io_setup.h"    //ポートの入出力設定に用いる関数読込
#include "ADConv.h"        //AD変換に用いる関数読込

main(){
    int i;
    int ad0;            //AD変換値を入れておく変数
    hardware_setup();    //マイコンの端子を初期化(汎用IO)
    init_ADC();            //AD機能の初期化

    set_LED_R(0);        //とりあえずLED赤消灯
    set_LED_G(0);        //とりあえずLED緑消灯
    while(1){
        check_ai();            //AD変換の実行
        ad0=get_ai(0);        //AN0のAD変換値(0-1023)を取得

        if(ad0<200){        //AD変換値が200以下(0.98V)
            set_LED_R(1);    //LED赤点灯
            set_LED_G(0);    //LED緑消灯
        }else if(ad0>1000){    //AD変換値が1000以下(4.88V)
            set_LED_R(0);    //LED赤消灯
            set_LED_G(1);    //LED緑点灯
        }else{
            set_LED_R(0);    //LED赤消灯
            set_LED_G(0);    //LED緑消灯
        }

        //AD変換値に応じて PE4-7を制御
        if(ad0>200)
            set_PortE_bit(4,1);    //PortEの4ビット目に出力
        else
            set_PortE_bit(4,0);    //PortEの4ビット目に出力

        if(ad0>500)
            set_PortE_bit(5,1);    //PortEの5ビット目に出力
        else
            set_PortE_bit(5,0);    //PortEの5ビット目に出力

        if(ad0>800)
            set_PortE_bit(6,1);    //PortEの6ビット目に出力
        else
            set_PortE_bit(6,0);    //PortEの6ビット目に出力

        if(ad0>1000)
            set_PortE_bit(7,1);    //PortEの7ビット目に出力
        else
            set_PortE_bit(7,0);    //PortEの7ビット目に出力
    }  // while end
// main end
※2017/02/13 関数名をInit_ADCからinit_ADCへ変更しました。

変更後のソースファイルダウンロード
上記プログラムの赤文字部分がAD変換機能に関する個所です。
このプログラムを実行するとAN0(PF0)の電圧に応じてベースボードの2つのLEDとPE4~PE7の出力が変化します。

次回はアナログポートに接続するテスト用の可変抵抗を作成します。

関連:当ブログで扱うSH7125の特殊機能一覧
PR

コメント

1. 分かりやすい

現在C言語とマイコンの学習の為にSH7125を使ったライントレーサを作成しているのですがそこらの書籍よりこちらのサイトの方が実践的で頼りになってます。これからもお世話にならせてもらいます!

2. 電子工作初心者のスキルアップの手助けを目指しています

専門知識があることを前提とした専門知識の解説を行うブログも多いのですが、始めたばかりの人にとっては前提となる専門知識を調べるのにかなり時間がかかってしまう事が多いと思います。このブログではひとつづつ調べなくても良いように知識を1パックにした解説を目指しています。
書いた本人だとどの解説が分かりにくいか分からないので、わかり難い部分があったらコメントを残して頂けると助かります。

プロフィール

HN:
ぼんどF博士
性別:
男性
自己紹介:

最新コメント