忍者ブログ

Fグループ電子工作講座

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

RL78のコード生成を使う(AD編)

PWMの設定に続き、AD変換も設定してみます。
コード生成の準備が出来ていない人はコード生成準備の回を参照のこと。

関連:
コード生成(準備編)
コード生成(PWM編)
コード生成(UART編)
・I2Cスレーブ(現象対策

コード生成→周辺機能→A/Dコンバータ

A/Dコンバータの動作設定→使用する
コンパレータの動作設定→許可

ここでのコンパレータとはオペアンプの親類のコンパレータではなく、AD変換に用いる
機能の事です。

ANI3,4,6は前回PWMを設定した端子と重複しているので設定不可
ANI0(P01)は後でRXD0として使いたいので除外
ANI1,2,5で設定してみます。

ANI0を除外したので、変換開始チャンネル設定の変更が必要になります。
とりあえずANI1としておきます。

ここまで編集したらコード生成を実行。


生成されたコードの実行

とりあえず生成されたコードを見てみます。
r_cg_adc.c

void R_ADC_Create(void)
・AD変換機能の初期化
・自動実行されるので、自分で実行しなくてもOK

void R_ADC_Start(void)
・AD変換の実行

void R_ADC_Stop(void)
・AD変換の停止

void R_ADC_Set_OperationOn(void)
・コンパレータ機能のON
・コード生成時にONに設定したので実行しなくてOK

void R_ADC_Set_OperationOff(void)
・コンパレータ機能のOFF
・ONしっぱなしで構わないので実行しなくてOK

void R_ADC_Get_Result(uint16_t * const buffer)
・AD変換結果の取得
・コード生成時の分解能設定が10bitなので、0~1023で

基本的には
void R_ADC_Start(void)
void R_ADC_Stop(void)
void R_ADC_Get_Result(uint16_t * const buffer)
を繰り返すことになります。

動作確認のためAD変換結果をPWM出力してみます。
PWM出力はPWMの設定をそのまま使用します。

<設定>
#include "iodefine.h"    //端子の基本設定読み込み
#include "r_cg_macrodriver.h"    //uint16_tとか読み込み
#include "r_cg_wdt.h"    //ウォッチドッグタイマー
#include "r_cg_tau.h"    //PWM設定
#include "r_cg_adc.h"    //ADC設定

void user_main(void){
    unsigned short duty1;    //デューティー比 0-1000
    unsigned long pwm_out1;    //出力
    unsigned short pwm_max=TDR00H*0x100+TDR00L;
    unsigned short ad_value; //AD値格納先
    int i;    //空ループ用

    R_TAU0_Channel0_Start();    //PWM開始
    while(1){
        R_ADC_Start();                    //AD変換開始
        for(i=0;i<100;i++);                //ちょっと待機
        R_ADC_Stop();                    //AD変換終了
        R_ADC_Get_Result(&ad_value);    //結果を取得

        duty1=ad_value;      //デューティー比を設定
        set_pwm(1,duty1);    //TO01へPWM出力
        R_WDT_Restart();    //ウォッチドッグタイマーリセット
    }
}

<解説>
変換開始→変換するまでちょっと待機→AD変換停止→結果を取得
取得した結果(0~1023)をPWMで出力しています。

ちょっと待機部分
変換開始直後に変換終了or結果取得しても正しく動作しません。
必ずちょとだけ変換待ち時間が必要です。
コード生成時に変換時間が9.4μsと出ていたのでそれ以上は必要です。
デバッグビルドだと空ループ30回程度から安定して動作するようになりました。
真面目に使う場合はr_cg_adc_user.cに生成される変換完了割込みr_adc_interruptを
利用するのが良いでしょう。

このプログラムでAD変換が実行されるのは変換開始チャンネル設定で設定した
1ポートのみです。

複数ポートのAD変換

せっかくADポートを複数設定したのに、AD変換を実行できないと意味がありません。
そこで、各ポートをAD変換します。
RL78G13とかだと連続スキャンモード等の複数のポートを連続してAD変換し続ける
モードが用意されているのですが、RL78G10だと
 ポートを選択→AD変換→ポートを選択→AD変換→・・・
を繰り返す必要がある様です。

そこでR_ADC_Start()を実行する前に変換対象を設定します。
コード生成された初期化関数R_ADC_Createを見ると
 ADS = _01_AD_INPUT_CHANNEL_1;
にてポートを設定していることが分かります。
ADSをハードウェアマニュアルを確認するとポート番号をそのまま入力すれば良いこと
が分かります。
従って、
        ADS=1;    //ANI1を指定
        R_ADC_Start();                    //AD変換開始
        for(i=0;i<100;i++);                //ちょっと待機
        R_ADC_Stop();                    //AD変換終了
        R_ADC_Get_Result(&ad_value1);    //結果を取得

        ADS=2;    //ANI2を指定
        R_ADC_Start();                    //AD変換開始
        for(i=0;i<100;i++);                //ちょっと待機
        R_ADC_Stop();                    //AD変換終了
        R_ADC_Get_Result(&ad_value2);    //結果を取得

        ADS=5;    //ANI5を指定
        R_ADC_Start();                    //AD変換開始
        for(i=0;i<100;i++);                //ちょっと待機
        R_ADC_Stop();                    //AD変換終了
        R_ADC_Get_Result(&ad_value5);    //結果を取得

と列挙してAD変換することになります。
ポート指定~結果取得までを関数化するのが良いでしょう。


<関数化した例>
#include "iodefine.h"    //端子の基本設定読み込み
#include "r_cg_macrodriver.h"    //uint16_tとか読み込み
#include "r_cg_adc.h"    //ADC設定

short get_adc(int port){
    unsigned short ad_value;    //AD値格納先
    int i;
    switch(port){
        case 1:
            ADS=1;    //ANI1
            break;
        case 2:
            ADS=2;    //ANI2
            break;
        case 5:
            ADS=5;    //ANI5
            break;
        default:    //該当なし
            return 0;
    }
    R_ADC_Start();                    //AD変換開始
    for(i=0;i<100;i++);                //ちょっと待機
    R_ADC_Stop();                    //AD変換終了
    R_ADC_Get_Result(&ad_value);    //結果を取得
    return ad_value;                //結果を戻す
}

<実行例>
#include "iodefine.h"    //端子の基本設定読み込み
#include "r_cg_macrodriver.h"    //uint16_tとか読み込み
#include "r_cg_wdt.h"    //ウォッチドッグタイマー

void user_main(void){
    unsigned short duty1,duty2,duty3;    //デューティー比 0-1000
    unsigned short ad_value1,ad_value2,ad_value5; //AD値格納先
    R_TAU0_Channel0_Start();    //PWM開始

    while(1){
        ad_value1=get_adc(1);    //結果を取得
        ad_value2=get_adc(2);    //結果を取得
        ad_value5=get_adc(5);    //結果を取得

        duty1=ad_value1;    //デューティー比を設定
        duty2=ad_value2;    //デューティー比を設定
        duty3=ad_value5;    //デューティー比を設定

        set_pwm(1,duty1);    //TO01へPWM出力
        set_pwm(2,duty2);    //TO02へPWM出力
        set_pwm(3,duty3);    //TO03へPWM出力
        R_WDT_Restart();    //ウォッチドッグタイマーリセット
    }
}
PR

コメント

プロフィール

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

最新コメント