端子の特殊機能設定
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.c、
ADConv.hここで
今後使いまわすプロジェクトを新規作成しておきたいと思います。
HEW起動、ファイル → 新規ワークスペース
ワークスペース名:sh7125_base01
CPUシリーズ:SH2
CPUタイプ:SH7125
その他は初期設定のままでOK
ファイルの読み込み
作成したプロジェクトのあるフォルダにで
SHプログラム分割の回作成した
io_setup.c、
io_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の特殊機能一覧
1. 分かりやすい