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();
//ウォッチドッグタイマーリセット }
}