CCWO Embedded Space

CCWOの日々の開発を発信するブログ

Renesas RX631 12bitADC

アナログ電圧の計測等で必要不可欠な12bitADCの設定を行います。
12bitADC=12bit Analog Digital Converterの略でアナログ電圧を12bitのディジタル信号に変換することを指します。
これにより、アナログ電圧をディジタル信号つまりビットに変換し、取り扱うことができ、アナログ電圧を出力するセンサー等の値をマイコンにより処理することでき大変便利です。
RX631(R5F5631FDDFP)では12bitAD変換が全14chあるのですべてを動作させたいと思います。
以下の手順で設定していきます。
1.消費電力低減機能の解除
2.ピンの設定
3.S12ADの設定
4.ユーザ関数の定義

はじめに
1.消費電力低減機能の解除
2.ピンの設定
を一度にみていきましょう。
まず、S12AD.cとS12AD.hという名前で次のファイルをプロジェクトに追加します。
e2 stduio左側プロジェクトエクスプローラのプロジェクトフォルダ内のsrcフォルダを右クリックし,
新規→ソース・ファイルからS12AD.c
新規→ヘッダ・ファイルからS12AD.h
を作成します。
ソースコードの追加はプロジェクトファイルのsrcフォルダに直接作成することでも可能です。
つぎに、hardware_setup.cにてS12AD.hをインクルードし、HardwareSetup関数でS12AD.cのS12AD_initialize関数を呼びます。
S12AD.h

#ifndef S12AD_H_
#define S12AD_H_

extern unsigned short ADC12[14];

void S12AD_initialize(void);

#endif /* S12AD_H_ */

S12AD.c

#include "iodefine.h"
#include "machine.h"
#include "vect.h"
#include "S12AD.h"

#pragma interrupt (S12AD_interrupt(vect=VECT(S12AD, S12ADI0)))

unsigned short ADC12[14] = {0};

void s12ad_initialize(void){
	SYSTEM.PRCR.WORD = 0xA502;		// Release Protect
	MSTP(S12AD) = 0;				// Wake up S12AD
	SYSTEM.PRCR.WORD = 0xA500;		// Protect
	// Set MPC
	PORT4.PMR.BIT.B0 = 1;			// Set P40-7: Peripheral
	PORT4.PMR.BIT.B1 = 1;
	PORT4.PMR.BIT.B2 = 1;
	PORT4.PMR.BIT.B3 = 1;
	PORT4.PMR.BIT.B4 = 1;
	PORT4.PMR.BIT.B5 = 1;
	PORT4.PMR.BIT.B6 = 1;
	PORT4.PMR.BIT.B7 = 1;
	PORTD.PMR.BIT.B0 = 1;			// Set PD0-5: Peripheral
	PORTD.PMR.BIT.B1 = 1;
	PORTD.PMR.BIT.B2 = 1;
	PORTD.PMR.BIT.B3 = 1;
	PORTD.PMR.BIT.B4 = 1;
	PORTD.PMR.BIT.B5 = 1;
	MPC.PWPR.BIT.B0WI = 0;			// Release protect
	MPC.PWPR.BIT.PFSWE = 1;
	MPC.P40PFS.BIT.ASEL = 1;		// Set P40-7: Analog Input
	MPC.P41PFS.BIT.ASEL = 1;
	MPC.P42PFS.BIT.ASEL = 1;
	MPC.P43PFS.BIT.ASEL = 1;
	MPC.P44PFS.BIT.ASEL = 1;
	MPC.P45PFS.BIT.ASEL = 1;
	MPC.P46PFS.BIT.ASEL = 1;
	MPC.P47PFS.BIT.ASEL = 1;
	MPC.PD0PFS.BIT.ASEL = 1;		// Set PD0-5: Analog Input
	MPC.PD1PFS.BIT.ASEL = 1;
	MPC.PD2PFS.BIT.ASEL = 1;
	MPC.PD3PFS.BIT.ASEL = 1;
	MPC.PD4PFS.BIT.ASEL = 1;
	MPC.PD5PFS.BIT.ASEL = 1;
	MPC.PWPR.BIT.PFSWE = 0;			// Protect
	MPC.PWPR.BIT.B0WI = 1;
	// S12AD Settings software trigger
	S12AD.ADCSR.BIT.CKS = 0;		// PCLK/8
	S12AD.ADCSR.BIT.ADIE = 1;		// Enable S12ADI0
	S12AD.ADCSR.BIT.ADCS = 1;		// Continuous scanning
	S12AD.ADCSR.BIT.ADST = 0;		// Stop S12AD
	S12AD.ADANS0.WORD = 0xFFFF;		// S12ADC: AN000-015
	S12AD.ADADS0.WORD = 0x0000;		// Disable ADD result Mode
	S12AD.ADCER.BIT.ACE = 1;		// Auto clearing
	S12AD.ADCER.BIT.ADRFMT = 0;		// Right -justified
	S12AD.ADSSTR01.BIT.SST1 = 60;	// 10us
	S12AD.ADCSR.BIT.ADST = 1;		// Enable S12AD

	IEN(S12AD, S12ADI0) = 1;
	IPR(S12AD, S12ADI0) = 8;
}

void S12AD_interrupt(void){
	ADC12[0] = S12AD.ADDR0;
	ADC12[1] = S12AD.ADDR1;
	ADC12[2] = S12AD.ADDR2;
	ADC12[3] = S12AD.ADDR3;
	ADC12[4] = S12AD.ADDR4;
	ADC12[5] = S12AD.ADDR5;
	ADC12[6] = S12AD.ADDR6;
	ADC12[7] = S12AD.ADDR7;
	ADC12[8] = S12AD.ADDR8;
	ADC12[9] = S12AD.ADDR9;
	ADC12[10] = S12AD.ADDR10;
	ADC12[11] = S12AD.ADDR11;
	ADC12[12] = S12AD.ADDR12;
	ADC12[13] = S12AD.ADDR13;
}

まず、消費電力低減機能の解除を見ていきます。

SYSTEM.PRCR.WORD = 0xA502;		// Release Protect
MSTP(S12AD) = 0;				// Wake up S12AD
SYSTEM.PRCR.WORD = 0xA500;		// Protect

これまでと同様に、消費電力低減機能のアクセスロックを解除し、消費電力低減機能を解除し、再度ロックします。
つぎにピンの設定を見てきましょう。

// Set MPC
PORT4.PMR.BIT.B0 = 1;			// Set P40-7: Peripheral
PORT4.PMR.BIT.B1 = 1;
PORT4.PMR.BIT.B2 = 1;
PORT4.PMR.BIT.B3 = 1;
PORT4.PMR.BIT.B4 = 1;
PORT4.PMR.BIT.B5 = 1;
PORT4.PMR.BIT.B6 = 1;
PORT4.PMR.BIT.B7 = 1;
PORTD.PMR.BIT.B0 = 1;			// Set PD0-5: Peripheral
PORTD.PMR.BIT.B1 = 1;
PORTD.PMR.BIT.B2 = 1;
PORTD.PMR.BIT.B3 = 1;
PORTD.PMR.BIT.B4 = 1;
PORTD.PMR.BIT.B5 = 1;
MPC.PWPR.BIT.B0WI = 0;			// Release protect
MPC.PWPR.BIT.PFSWE = 1;
MPC.P40PFS.BIT.ASEL = 1;		// Set P40-7: Analog Input
MPC.P41PFS.BIT.ASEL = 1;
MPC.P42PFS.BIT.ASEL = 1;
MPC.P43PFS.BIT.ASEL = 1;
MPC.P44PFS.BIT.ASEL = 1;
MPC.P45PFS.BIT.ASEL = 1;
MPC.P46PFS.BIT.ASEL = 1;
MPC.P47PFS.BIT.ASEL = 1;
MPC.PD0PFS.BIT.ASEL = 1;		// Set PD0-5: Analog Input
MPC.PD1PFS.BIT.ASEL = 1;
MPC.PD2PFS.BIT.ASEL = 1;
MPC.PD3PFS.BIT.ASEL = 1;
MPC.PD4PFS.BIT.ASEL = 1;
MPC.PD5PFS.BIT.ASEL = 1;
MPC.PWPR.BIT.PFSWE = 0;		// Protect
MPC.PWPR.BIT.B0WI = 1;

SCI同様にMPCのアクセスロックを解除し、ピンに周辺機能を割り当て、再度ロックし、下準備を完了します。
今回は14個のピンを一度に設定するのでかなり長くなっています。個別に設定しているのはあとで変更しやすくするためです。
固定であるならば、一括でレジスタを設定してもよいでしょう。

3.S12ADの設定
S12ADはデータシートに初期化手順が示されているわけではないので、今回は連続スキャンモードを参考に設定していきます。
しかし、ここで余談ですが、RXに限らずマイコンのAD変換の設定はおおまかに
・AD変換クロックの設定(モジュールの動作周波数の設定)
・トリガ、割り込みの設定(AD変換のトリガの設定)
・AD変換chの設定(何個AD変換を使用するの設定)
・加算、フィルタの設定(精度を上げたりするための設定)
・データ型の設定(右詰め、左詰め(Little,Big Endian=Byte-order)の設定)
・サンプリング周期の設定(AD変換には一般的にある程度の時間を要さないと構造的に精度が出ないためサンプリング時間の設定をする。)
RX631もほぼ例に漏れることなく設定していく。

// S12AD Settings software trigger
// AD変換クロックの設定
S12AD.ADCSR.BIT.CKS = 0;		// PCLK/8
// 割り込みの設定
S12AD.ADCSR.BIT.ADIE = 1;		// Enable S12ADI0
S12AD.ADCSR.BIT.ADCS = 1;		// Continuous scanning=連続スキャンモード
S12AD.ADCSR.BIT.ADST = 0;		// Stop S12AD=AD変換の設定をするため一旦モジュールをストップ
// AD変換chの設定
S12AD.ADANS0.WORD = 0xFFFF;		// S12ADC: AN000-015
// 加算、フィルタの設定
S12AD.ADADS0.WORD = 0x0000;		// Disable ADD result Mode
S12AD.ADCER.BIT.ACE = 1;		// Auto clearing
// データ型の設定
S12AD.ADCER.BIT.ADRFMT = 0;		// Right -justified
// サンプリング周期の設定
S12AD.ADSSTR01.BIT.SST1 = 60;	// 10us
S12AD.ADCSR.BIT.ADST = 1;		// Enable S12AD=AD変換開始

このように、一般的なマイコンと同様(かなり高機能な部類)にして設定が可能である。
最後に、タイマー割り込みで設定したときと同様に割り込みの設定をする。

IEN(S12AD, S12ADI0) = 1;
IPR(S12AD, S12ADI0) = 8;

同様にvect.hの

// S12AD S12ADI0
#pragma interrupt (Excep_S12AD_S12ADI0(vect=102))
void Excep_S12AD_S12ADI0(void);

をすべてコメントアウトします。
これでAD変換の設定は完了しました。

4.ユーザ関数の定義
割り込みベクタテーブルの設定と関数の設定をします。

#include "vect.h"

#pragma interrupt (S12AD_interrupt(vect=VECT(S12AD, S12ADI0)))

void S12AD_interrupt(void){
	ADC12[0] = S12AD.ADDR0;
	ADC12[1] = S12AD.ADDR1;
	ADC12[2] = S12AD.ADDR2;
	ADC12[3] = S12AD.ADDR3;
	ADC12[4] = S12AD.ADDR4;
	ADC12[5] = S12AD.ADDR5;
	ADC12[6] = S12AD.ADDR6;
	ADC12[7] = S12AD.ADDR7;
	ADC12[8] = S12AD.ADDR8;
	ADC12[9] = S12AD.ADDR9;
	ADC12[10] = S12AD.ADDR10;
	ADC12[11] = S12AD.ADDR11;
	ADC12[12] = S12AD.ADDR12;
	ADC12[13] = S12AD.ADDR13;
}

上記はタイマー割り込みと設定したときと同様で、S12AD_interrupt関数をベクタテーブル番号VECT(S12AD,S12ADI0)で呼ばれるようにpragmaにて定義し、
割り込み処理関数ではグローバル変数で用意したADC12配列にひとつずつ収納していく形になっています。

これで設定は完了しました。
最後にmain文にて

#include <stdio.h>
#include "iodefine.h"
#include "machine.h"
#include "S12AD.h"

void main(void)
{
	int i;
	while(1){
		for(i = 0; i < 14; i++){
			printf("S12AD[%d]:%4d\n", i, ADC12[i]);
		};
	}
}

という感じでデバッグしてみましょう。TeraTerm等ではおそらくランダムな値が出てくると思います。(Hi-Z状態のため、値が震えてる。)
これで12bitADCは完了です!

20160818の記事