H8CPUのADC・ DACのサンプルプログラム
Copyright(C) 13May2002
coskx
はじめに
この文書はAKI-H8にて,ADC,DACのサンプルプログラムを提示するものである。
DAC
DAC(DAコンバータ,ディジタルアナログ変換)とは,コンピュータの取り扱うことのできる数値を,アナログ量すなわち
電圧に変換する機能をもったデバイスである。より大きな数値を与えるとより高い電圧が出力されるようになっており,与える数値と出力される電
圧は比例関係になる。マイコンの場合は出力電圧は0Vから5Vである場合が多く,0を与えると0Vが出力され,1023を与えると5Vが出力
され,512を与えると2.5Vが出力される。
DACの応用
1秒間に8000回でDACで音響信号バイト列を出力し,アンプ・スピーカを接続すると,電話音質の音声データを再生す
ることができる。
ADC
ADC(ADコンバータ,アナログディジタル変換)とは,アナログ量すなわち電圧を,コンピュータの取り扱うことのできる数値に変換する機能
をもったデバイスである。デジタル電圧計だと思えばよい。ただし,数値で表した時の単位はボルトではなくて,コンピュータに都合のよいように
できている。入力電圧と変換結果の値は比例関係にあり,マイコンの場合は入力電圧は0Vから5Vである場合が多く,0Vを入力すると0
に,5Vを入力すると1023に,2.5Vを入力すると512になる。
ADCの応用
回転式の可変抵抗やポテンショメータと呼ばれる精密可変抵抗は,軸の回転角を電圧に変換できる。これの出力をADCで捉
えると,角度センサが作れる。その他,温度センサや湿度センサ,光度センサ,圧力センサなどは電圧出力のものが多いのでADCを用いるとマイ
コンがさまざまな物理量を知ることができる。
【1】 AKI-H8のDAコンバータ出力
H8CPUはDAコンバータ(CPU内のレジスタの値を,値に比例した電圧に変換して出力する機能,Digital Analogue Converter)を2チャンネル持っている。
DAコンバータの分解能は8ビットなので,この比例関係は理論的には表1.1のようになる。H8CPUでは,DAC0チャンネル出力は
CN2-18ピンに出力される。図1.1はDACチャンネル0を引き出している回路例である。
プログラムでは,RS232Cに接続されたパソコンのターミナルソフト(例えばハイパーターミナル)を用い,キーボードからDAコンバータへ
の出力値を設定するものとし,設定値は0から255までの値とする。
表1.1 8ビットDAコンバータの入力値と出力電圧の関係 | |
入力値 |
出力電圧 |
0 |
0.00V |
64 |
1.25V |
128 |
2.50V |
192 |
3.75V |
255 |
4.98V |
図1.1 DAコンバータチャンネル0の出力回路例 |
DACへの出力 |
/********************************************************** DACへの出力 **********************************************************/ #include <3048fone.h> #include "h8_3048fone.h" /* DACは2チャンネル存在する*/ void initDAC() { DA.DACR.BYTE |= 0xc0; } /* ------------------------------------------------- DA CONVERT data 出力電圧 0 → 0V 255 → 5V ------------------------------------------------- */ void outputDAC(unsigned char ch, unsigned char data) { if(ch==0) DA.DADR0 = data; else if(ch==1) DA.DADR1 = data; } main() { int x; initSCI1(); initDAC(); while(1) { x=SCI1_getInt("DA value(0..255) ="); outputDAC(0,x&0xff); } } /* 実行時の測定結果 入力値 出力値 0 0.08V 64 1.27V 128 2.53V 192 3.78V 255 5.02V */ |
課題 |
【2】 AKI-H8のADコンバータ入力(単一モード)
H8CPUはADコンバータ(入力された電圧を,その電圧に比例した値としてCPU内のレジスタに取り込む機能,Analogue Digital Converter)を8チャンネル持ってい る。ADコンバータの分解能は10ビットなので,この比例関係は理論的には表2.1のようになる。図2.1はH8CPUのAD0チャンネ ルのピンはCN2-12であることを示している。
図2.1 DAコンバータチャンネル0の出力 |
表2.1 10ビットADコンバータの入力電圧と出力値の関係 | |
入力電圧 |
出力値 |
0.00V |
0 |
1.25V |
256 |
2.50V |
512 |
3.75V |
768 |
4.99V |
1023 |
次のプログラムはCN2-12に電圧を与えて,ADCの結果を表示するプログラムである。
ADCの入力のテスト |
/********************************************************** /*
------------------------------------------------- */ |
課題
実際にこのプログラムを動作させて,入力ピン(CN2-12)に電圧を与えて読み取りなさい。
注意 ADCは破壊しやすい。
絶対に5Vを超えた電圧は与えないこと。最初は2.5Vから始
めるとよい。
図2.2はテストのためにADCチャンネル0を引き出して,再びDACチャンネル0に戻している回路例である。
プログラムでは,RS232Cに接続されたパソコンのターミナルソフト(例えばハイパーターミナル)を用い,キーボードからDAコンバー
タへの出力値を設定するものとし,設定値は0から255までの値とする。DAコンバータチャンネル0から出力された電圧は外部で直結され
たADコンバータチャンネル0へ再入力され,得られたAD変換値をパソコンのターミナルソフト上に表示する。
このプログラムで使用している関数inputADC()はADコンバータのチャンネル0から3のみを扱うものである。
図2.2 DAコンバータチャンネル0の出力をADコンバータチャンネル0に直結した
回路例 |
DACからの出力をADCの入力へつなげてのテスト |
/********************************************************** /*
------------------------------------------------- */ |
課題 |
【3】 AKI-H8のADコンバータ入力(スキャンモード)
H8-CPUは全部で8チャンネルのADコンバータ(Analogue Digital Converter)があるが,そのうち4個を
利用し,タイマー割り込み(一定時間ごとの割り込み)を利用し,4つの時系列データを取り込むプログラム例の一部を提示する。
4つの時系列データは
unsigned char ad_result0[SIZE];
unsigned char ad_result1[SIZE];
unsigned char ad_result2[SIZE];
unsigned char ad_result3[SIZE];
に保存されることとし,変数counterは0からSIZE-1の範囲になるようにうまく制御されているものとする。
タイマー割り込みを利用した4つの時系列データの取込 #include
<3048fone.h> #define SIZE 256 unsigned char
ad_result0[SIZE]; /* ADC
INITIALIZATION */ /*
GET ADC RESULT */ volatile int
counter=SIZE; /*
割り込み関数 */ #pragma
interrupt (TimerIntFunc) clearTimer1Flag();
/*タイマステータスフラグのクリア 忘れないこと*/ main()
initADC_L4();
/*ここで何かの作業*/
counter=0; /*counterに0を代入することでADC変換要求*/
/*ここで何かの作業*/
} }
#include "h8_3048fone.h"
#define clearTimer1Flag() (ITU1.TSR.BIT.IMFA=0)
unsigned char ad_result1[SIZE];
unsigned char ad_result2[SIZE];
unsigned char ad_result3[SIZE];
void initADC_L4()
{
AD.ADCSR.BIT.ADF=0;
/*エンドフラグをクリア*/
AD.ADCSR.BIT.ADIE=0;
/*インタラプト禁止*/
AD.ADCSR.BIT.ADST=0;
/*スタート停止*/
AD.ADCSR.BIT.SCAN=1;
/*スキャンモード*/
AD.ADCSR.BIT.CKS=1;
/*変換時間=134ステート*/
AD.ADCSR.BIT.CH=3;
/*AN0〜AN3(スキャンモード)*/
}
void getADC_L4(unsigned char adc[]) /*ad*/
{
AD.ADCSR.BIT.ADST =
1;
/* AD設定SCANモード 4チャンネル同時使用 ADスタート */
while(AD.ADCSR.BIT.ADF ==
0); /*変換終了まで待つ*/
AD.ADCSR.BYTE &= 0x5f
;
/*ADFとADSTクリア*/
adc[0]=(AD.ADDRA>>8); /*AD.DRAは
unsigned int */
adc[1]=(AD.ADDRB>>8);
adc[2]=(AD.ADDRC>>8);
adc[3]=(AD.ADDRD>>8);
}
#pragma asm
.SECTION MYVEC,
DATA, LOCATE=H'000070
.ORG
H'000070 ;IMIA1
.DATA.L
_TimerIntFunc
.SECTION
P,CODE,ALIGN=2 ;これを忘れてはいけない
#pragma endasm
void TimerIntFunc() /*タイマ割り込みルーチン*/
{
static unsigned char adc[4];
if (counter<=SIZE) {
getADC_L4(adc);
ad_result0[counter]=adc[0];
ad_result1[counter]=adc[1];
ad_result2[counter]=adc[2];
ad_result3[counter]=adc[3];
counter++;
}
}
{
/*関連部分のみ抜粋*/
initTimer01Int(500);
/*時間割り込み500msec ch0,ch1使用*/
E_INT();
/*CPU割り込み許可*/
startTimer01();
/*時間割り込みタイマスタートch0,ch1*/
while (1) {
while
(counter<SIZE);
/*counter=SIZEになることでSIZE個のデータ取得完了*/