• ベストアンサー

H8/3048マイコンAD/DA変換について

初めて投稿させていただきます。  AKI-H8/3048キットでAD/DA変換をC言語で行いたいの ですがうまくいきません。  C言語ではどうやって記述すればいいのでしょうか? ご助言お待ちしています。  参考までに作成したAD/DA変換ソースコードを記します。 ちなみに入力端子AN0は可変抵抗器、出力端子DA1はLCDに 接続しています。 (可変抵抗器からの電圧増減に従ってLCDの表示を変化 させたい) #include <3048f.h> #include <stdio.h> main(){ int a; while(1){ AD.CSR.BYTE = 0x28; while(AD.CSR.BIT.ADF == 0){} a = AD.DRA; AD.CSR.BIT.ADF = 0; DA.DR1 = (unsigned char)((a >> 8)&0x00ff); } }

質問者が選んだベストアンサー

  • ベストアンサー
  • kaZho_em
  • ベストアンサー率50% (2950/5879)
回答No.3

> AD.CSR.BYTE = 0x28; 確認します。上の設定だと、 ADインタラプトイネーブル(ADIE) : AD変換終了割込(ADI) 常時禁止 ADスタート(ADST) : whileの度スタートを設定 スキャンモード(SCAN) : 単一モード固定 クロックセレクト(CKS) : 変換時間134ステート(Max) チャンネルセレクト(CH0~2) : AN0を選択 で良いですね。であればここには問題無いと思います。 > int a; > while(1){ > > AD.CSR.BYTE = 0x28; は、 int a; AD.CSR.BYTE = 0x08; while(1){ AD.CSR.BIT.ADST = 1; の方がベターかと思いますが(while中ではADスタートのみ設定)、まあ大丈夫でしょう。 > while(AD.CSR.BIT.ADF == 0){} AD変換終了を待つループですね。問題有りません。 次が少し問題です。 > a = AD.DRA; H8/3048でAD変換結果を格納するデータレジスタADDRA~Dは16ビットレジスタでは ありますが、一度に読み出すことはできません。 上位バイト→下位バイトの順で、バイト単位に2回に分けてリードです。 これは、バス幅が8ビットであるための制限です。 下位バイトのデータは、テンポラリレジスタ(TEMP)を介さないとリードできない仕様ですが、 上位バイトのリードを行うと、内部的に下位バイトがTEMPに転送され、次に下位バイトの リード処理を行うと、データがTEMPから引き出される仕組みになっています。 ただし、DA出力処理と思われる箇所で、下位データは捨てられているようなので、それを 見越した処理であるなら良いのかもしれません。 ただ、CHIPの仕様としてはバイト単位の2回リードとなっています。 最後に、 > DA.DR1 = (unsigned char)((a >> 8)&0x00ff); DR1なので、DA1チャンネルを使うのでしょうが、DAコントロールレジスタ(DACR)の DAアウトプットイネーブル1(DAOE1)、DAイネーブル(DAE)は、それぞれどこかで 別途設定されているのでしょうか?漏れているなら設定して下さい。

kohei55_1980
質問者

お礼

回答ありがとうございます。 おかげさまでAD/DA変換が可能になりました! 原因はイネーブルのビットを1にしていない事 でした。 リード処理の仕組みも大変参考になりました。

その他の回答 (2)

  • keikan
  • ベストアンサー率42% (75/176)
回答No.2

#1です。 >AD.CSR.BIT.ADFがループの前に初期化されていないが、AD.CSR.BIT.ADF!=0であった場合、読み取りすることなく内側のループを素通りするがいいのかな? 1回目素通りしても後で初期化してるのでいいのかな^^;;

  • keikan
  • ベストアンサー率42% (75/176)
回答No.1

3048f.hの中身及び関数、構造体等のプロトタイプがわからないのでリストからわかることを、 //↓無限ループの始まり while(1){ //↓AD.CSR.BYTE を 0x28に初期化 きっと何かの命令セットだろう AD.CSR.BYTE = 0x28; //↓何もしないループたぶん入力信号待ちなのだろう while(AD.CSR.BIT.ADF == 0){} //↓ループ後 aに たぶん得られた信号AD.DRAを代入 a = AD.DRA; //↓たぶん入力待ち信号AD.CSR.BIT.ADFを0に初期化 AD.CSR.BIT.ADF = 0; //前回得られたa(すなわちAD.DRA)の上位8BITをDA.DR1に代入 DA.DR1 = (unsigned char)((a >> 8)&0x00ff); }・・を繰り返す。 AD.CSR.BIT.ADFがループの前に初期化されていないが、AD.CSR.BIT.ADF!=0であった場合、読み取りすることなく内側のループを素通りするがいいのかな? 入力側から得られたAD.DRAの上位8ビット抜き取るだけでいいのかな?BITを展開しなくてもいいのかな? ということで、ソースを見た限りのところです、ご参考になれば。

kohei55_1980
質問者

お礼

回答ありがとうございました。 参考になりました。 また、次からはソースコードにはコメントを つけます。読み手側への配慮が欠けていました。

関連するQ&A

  • H8/3048、AD/DA変換プログラムについて。

    H8/3048、AD/DA変換について質問です。 ポート7のAN0・AN1を入力に使い、DA0・DA1で出力される変換プログラムを作成して実験したところ AN0→DA0への変換は出力されたのですが、AN1→DA1への変換が出力できません。なぜ出力されないのかわかりません。 どうしたらいいか教えてください、お願いします。 AN0がDA1でも出力されているかと思いましたが違いました。 #include <no_float.h> #include <stdio.h> #include <machine.h> #include "h8_3048.h" void init (void); double get_ad0 (void); double get_ad1 (void); void out_da0 (double); void out_da1 (double); void wait (void); int main (void) { double ad0,ad1; int d; init(); //初期化 // set_ccr(0x00); //全体の割り込み許可 //AD DA変換----------- while(1){ ad0=get_ad0(); ad1=get_ad1(); for(d=0;d<1000;d++); out_da0(ad0); out_da1(ad1); } return 0; } void init(void) { /* ポートの入出力設定 */ P1DDR = 0xff; P2DDR = 0xff; P3DDR = 0xff; P4DDR = 0xff; P5DDR = 0xff; P6DDR = 0xf0; // CPU基板上のDIP SW P8DDR = 0xff; P9DDR = 0xf7; PADDR = 0xff; // LED基板 PBDDR = 0xff; // A/Dの初期設定(単一モード) AD_CSR = 0x00; // A/Dの初期設定(スキャンモード使用AN0-AN1) // AD_CSR = 0x11; //ITU0 1ms毎の割り込み ITU0_TCR = 0x20; ITU0_GRA = 24575; ITU0_IER = 0x01; ITU_STR = 0x01; // D/Aの初期設定 DA_CR=0xc0; //DA0E1,DA0E0:1 D/Aアウトプットネーブル DAE:0 ch0,1 独立制御 } double get_ad0(void) { int i; double ad; AD_CSR |=0x20; //ADST:1 AD開始 while(!(AD_CSR & 0x80)); //ADF:1 エンドフラグをチェック AD_CSR &=0x7f; i=AD_DRA>>6;// i=0-1023 ad=i*5.0/1024.0; // 0-1024 を 0-5vに変換 return ad; } double get_ad1(void) { int i; double ad; AD_CSR |=0x20; //ADST:1 AD開始 while(!(AD_CSR & 0x80)); //ADF:1 エンドフラグをチェック AD_CSR &=0x7f; i=AD_DRB>>6; //i=0-1024 ad=i*5.0/1024.0; // 0-1024 を 0-5vに変換 return ad; } void out_da0(double d) { DA_DR0=(int)(d*255/5.0); } void out_da1(double d) { DA_DR1=(int)(d*255/5.0); } void wait(void) { long Loop=200000; while(Loop--); }

  • H8/3664FのAD変換について

    初めまして。 現在大学でH8/3664FでのAD変換を行っているのですが、 AD変換とその値に対する出力への動作が上手くいきません。 分かる方、ご教授お願いいたします。 現状は、1.7V程度の信号をADコンバータ端子(AN1)に入力しています。 AD変換を行い、条件として1V以上のときは出力に設定した 端子(P11)から5V出力しダイオードを光らせようと思っています。 プログラムは以下のように組んでいます。 おかしいところがあればご指摘お願いします。 void main(void){ IO.PMR1.BYTE=0x00; /* ポート1入出力ポート*/ IO.PCR1=0xff; /* ポート1出力*/ /*AD変換の初期設定*/ AD.CSR.BIT.ADST=0; /*AD変換機能停止*/ AD.CSR.BIT.SCAN=1; /*スキャンモード*/ AD.CSR.BIT.CKS=1; /*高速変換*/ TW.TCRW.BIT.CCLR=1; /* TCNTがGRAでクリア */ TW.TCRW.BIT.CKS=3; /* クロックφ/8 */ TW.GRA=40000; /* パルスの周期20ミリ秒 */ TW.TMRW.BIT.CTS=1; /* カウントスタート */ while(1){ /* 20ミリ秒間のカウントは約8880となる. */ if(TW.TSRW.BIT.IMFA==1){ TW.TSRW.BIT.IMFA=0; AD.CSR.BIT.ADST=1; /*AD変換機能開始*/ while(AD.CSR.BIT.ADF==0){}; /*AD変換終了待ち*/ AD.CSR.BIT.ADF=0; /*変換終了フラグクリア*/ AD.CSR.BIT.ADST=0; /*AD変換機能停止*/ x0=(int)(AD.DRA>>6); /*x0に値を格納*/ if(x0>100){/*1V以上の場合*/ IO.PDR1.BIT.B2=1; }else{ IO.PDR1.BIT.B2=0; }

  • h8マイコンで AD変換ができなくて困っています

    マイコンでAD変換をしようと思っています>< #include<3048.h> void ioinit(); void adinit(); int i; int ADDRA; main() { ioinit(); adinit(); while(1){ AD.ADCSR.BIT.ADST = 1; // A/D変換スタート while(AD.ADCSR.BIT.ADF==1); // A/D変換終了まで待つ int i = ADDRA; // レジスタに格納された値をiとする if (i>=0xA5){ // 電圧が6.5vより高くなった場合 P5.DR.BYTE = 0x01; } else if (i<=0x19){ // 電圧が1vより小さくなった場合 P5.DR.BYTE = 0x02; } else if (0x19<=i<=0xA5){ // それ以外の電圧だった場合 P5.DR.BYTE = 0x03; } AD.ADCSR.BIT.ADF=0; //フラグクリア } } // I/OポートDDR設定 void ioinit() { P5.DDR=0xff; } // A/D変換設定 void adinit() { AD.ADCSR.BYTE = 0x33; } このプログラムでAD変換がまったくできません><電圧を変えていくことでP5につながっているLEDで変換結果を見たいと思っています。ADDRAのプログラムあたりがおかしいと思っています;;ちなみにポート7に電圧計とつなげています。その電圧値を変えていくことで結果を見ようとしています。0xA5は6.5Vのときの反応だから回路も分圧させたものにして10Vまでの対応にしました><どこがおかしいのか教えていただけるとてもうれしいです><助けてください;;

  • H8/3052について

    こんにちは。 現在秋月書店のH8/3052のマイコンを使ってイエローのC言語で 声の周波数を調べるという卒研をやっています。 声の周波数を調べるためにA/D変換を使ってやろうと思っていますが、 エラーが出ました。その前に周波数を調べられるかそうかはまだわかりませんが・・・。エラーの内容は 未定義のシンボルです DDR でした、 あと、周波数を調べるため、A/D変換するためのポートはP7でよろしいでしょうか? 皆さんのご指摘お願いいたします。 プログラムの一部を載せます。 #include <3048F.H> #define E_SIG 0x20 #define RS_SIG 0x10 void ioinit(void) { P7.DDR = 0xff; //ポート3を全ビット出力に設定 } void adinit(void) { AD.CSR.BIT.ADF = 0; //ADFフラグクリア AD.CSR.BIT.SCAN = 0; //単一モード選択 AD.CSR.BIT.CKS = 1; //クロックセレクト AD.CSR.BIT.CH = 0; //チャネルセレクト AN0単一モード } です。よろしくお願いします。

  • H8/3052 周波数について

    こんにちわ。 大学の研究で声の周波数をH8/3052で 示そうと考えています。周期を使ったプログラムですが、 声をA/D変換された電圧で、電圧が0になった所を0.125秒間で何回かカウントして d = 0.1025 * 2 / count; //一周期分=半周期×2倍÷カウント(0になった数) F=1/d (周波数=1/周期)を使い、ある範囲の周波数内になったらLEDが光るというプログラムを作りたいのですが、何も表示されません。皆様の知識をお借りしたいです。よろしくお願いします。プログラム乗せますのでご指摘お願いします。 //A/Dコンバータテストプログラム //AN0からの入力電圧をLCDに表示 #include <3048F.h> #include <io.h> #define E_SIG 0x20 #define RS_SIG 0x10 void ioinit(void) { P5.DDR = 0xff; } void adinit(void) { AD.CSR.BIT.ADF = 0; //ADFフラグクリア AD.CSR.BIT.SCAN = 0; //単一モード選択 AD.CSR.BIT.CKS = 1; //クロックセレクト AD.CSR.BIT.CH = 0; //チャネルセレクト AN0単一モード } void wait(void) { int t = 1000; while(t--); } int main(void) { int add; //変換された信号を記憶する int i; int t; int b; int d; int f; int v; int count; ioinit(); adinit(); wait(); //電源ONで15ms以上待ち while(1) { AD.CSR.BIT.ADST = 1; //A/D変換スタート while(AD.CSR.BIT.ADF == 0); //変換終了を待つ add = AD.DRA >> 6; //AN0入力、6ビット右にシフト、大切 AD.CSR.BIT.ADF = 0; //フラグクリア add=(int)((add*(5.0/1024.0)*1000.0)+0.5);//入力データを電圧値に換算 v=add; while(b = 8500) //0.125s間 { while(b--); if(0==v) //0Vになったときカウント { count++; } } d = 0.1025 * 2 / count; //半周期×2倍÷カウント(0になった数) f = 1 / d; //F=1/T (周波数= 1 ÷ 周期) } wait(); if(4000<=f<=8000) //周波数Fが4000~8000Hzになったら実行 { lcdxy2(); //2行目指定 dsp1g(" O K "); //2行目クリア wait(); } } }

  • AD変換した結果を出力する方法は?

    H8マイコンを利用してAD変換し、その結果をパソコンの画面に出力したいのですが何をすればいいのかわかりません。出力の形は整理しやすい形で出力したいと考えています。テキスト形式などは可能でしょうか? プログラムは二つの入力(AN0とAN1)をスキャンしながらAD変換します。 最後に AD.CSR.BIT.ADST = 0; /* A/Dコンバータを止める*/ adhenkan[0] = ADDRA; /*AN0の結果をadhenkan[0]に格納する*/ adhenkan[1] = ADDRB; /*AN1の結果をadhenkan[2]に格納する*/ AD.CSR.BIT.ADF = 0; } AD変換したデータをadhenkan[1],adhenkan[2]に格納した後にどうすればいいのかわかりません。

  • H8マイコンのDA変換機能について

    今、H8マイコンの3048Fをつかっています。マイコンを扱うのは全くの初心者で昔、電子工作でラジオを作ったりしたことがある程度です。 そこで、『C言語によるH8マイコンプログラミング入門』という本を参考に一つずつプログラムを打ち込みながら試しているところです。 そこにある、D/A変換を使ってサインカーブを出力する、プログラムを試そうとしてつまづいています。添付データの様な出力になり、期待に反しています。なぜ、こうなるか分からなくて何かアドバイス頂けないでしょうか? 以下、そのプログラムです。 //タイマ割り込みによるD/Aコンバータの出力 //ITU0使用  //200Hzのサインウェーブを出力する //da_3.c #include <3048.h> //3048、3052の内部I/O定義 int c; //1サイクルの出力回数、外部変数とする unsigned int sindata[128] = {127,133,139,146,152,158,164,170, //出力データ 176,181,187,192,198,203,208,212, 217,221,225,229,233,236,239,242, 244,247,249,250,252,253,253,254, 254,254,253,253,252,250,249,247, 244,242,239,236,233,229,225,221, 217,212,208,203,198,192,187,181, 176,170,164,158,152,146,139,133, 127,121,115,108,102,96,90,84, 78,73,67,62,56,51,46,42, 37,33,29,25,21,18,15,12, 10,7,5,4,2,1,1,0, 0,0,1,1,2,4,5,7, 10,12,15,18,21,25,29,33, 37,42,46,51,56,62,67,73, 78,84,90,96,102,108,115,121}; void ituinit(void) //ITUイニシャライズ { ITU0.TCR.BIT.CCLR = 1; //カウンタクリア要因 ITU0.TCR.BIT.TPSC = 0; //16MHz 周期 0.0625μs ITU0.GRA =900; //200Hz 周期 5ms、1サイクルの出力数 128、 周期 5/128=0.0390625ms //0.0390625ms=39.0625μs、39.0625/0.0625=625 ITU0.TIER.BIT.IMIEA = 1; //IMFAフラグによる割り込み許可 } void dainit(void) //D/Aコンバータイニシャライズ { DA.DACR.BIT.DAOE0 = 1; DA.DACR.BIT.DAE = 0; } //ITUインターバルタイマ割り込み void int_imia0 (void) { ITU0.TSR.BIT.IMFA = 0; //割り込みステータスフラグクリア DA.DADR0 = sindata[c]; //サイン波形データ出力 c+=1; if(c>128) c=0; } int main(void) { ituinit(); dainit(); ITU.TSTR.BIT.STR0 = 1; //タイマスタート c=0; //割り込み回数 EI; //割り込み許可 while (1); //何もしない }

  • H8/3048 マイコンボードについて

    初心者の質問ですみません。 今、H8/3048のマイコンを使っていろいろやってみようと思っています。 マザーボードにP1の出力をLEDで表示できるような回路を組み、スイッチを押すとLEDを光らせるようなプログラムを作成し、実際に光らせることはできたのですが、A/D変換機能が使えません。 プログラムはネット上のサンプルプログラムを参考にしたので間違ってはいないと思うのですが、うまく変換されません。 入力電圧はきちんとAN0に入ってますし、ICやソケット部も拡大鏡で確認しましたがショートしている様子もありません。 これは故障してしまったのでしょうか? 何かの拍子に何処かがショートしてAD変換機能のみが壊れるというような事はあるのでしょうか? 非常に困っています。 どなたか回答よろしくお願いいたします。 ちなみにこのようなプログラムです。 #include <3048.h> void main(void){ int ad_data; P1.DDR = 0xff; P4.DDR = 0x00; P4.PCR.BYTE = 0xff; AD.ADDRA = 0; P1.DR.BYTE = 0xff; AD.ADCSR.BYTE = 0x33; while(AD.ADCSR.BIT.ADF == 0){} while(1){ if(P4.DR.BIT.B4 == 0){ ad_data = AD.ADDRA>>8; } P1.DR.BYTE = ad_data & 0xFF; } }

  • H8マイコン(3052)でCdS

    H8マイコン初心者です。 よく参考書に乗っているようなA/D変換で電圧を計って、 それをLCDに表示するプログラムを組みました。 手元に可変抵抗がないためCdSセルを使って 暗くなったらLCDに表示された電圧が変化する というプログラムを作ったんですがうまくいきません。 どなたかCdSをH8マイコンで使用した参考プログラム(C/C++) みたいなものが乗っているサイトを知りませんか? もしくは書籍でもかまいません。 ご返答宜しくお願いします。

  • PIC AD変換

    pic AD変換の仕方。 PIC12F675を使ってLEDの点滅プログラムを作りたいのですが、 そのとき可変抵抗器をつないでAD変換すれば点滅速度を変えられる 用になると思うのですが、AD変換のプログラムがわかりません。 どなたか教えてください。 初心者なのでできるだけ解説付きで、できれば HI-TECH C言語でお願いいたします。

専門家に質問してみよう