• 締切済み

AD変換

H8/3664でのAD変換についての質問なのですが、このマイコンだと通常8つあるAD変換をスキャンモードで1度で4つまでしか処理できないのですが グループ0のAN0とグループ1のAN4が同一レジスタで結果が格納されていると思われますが この二つを1度に処理したいのですが、どのようなプログラムにすればいいのですか? AD変換あたりのプログラムを抜粋したので、後半のAD.ADDRB をAN4のAD.ADDRAに変えた場合のプログラムを教えて下さい char aflag=0; //割り込みフラグ void main(void) { char carray0[20],carray1[20],carray2[20]; long ad_data_0,ad_data_1,arrey0,arrey1,ad0,ad1,t,G_data,A_data,hensa_now,hensa_mae,A_out_put; int i; timervset(); timeraset(); IO.PDR5.BYTE = 0xff; // ポート7の出力設定をあらかじめ1に設定 IO.PCR7 = 0x00; // ポート7を全て入力ポートに設定(タクトSW1,SW2,SW3) IO.PCR5 = 0xff; // ポート5を全て出力ポートに設定 IO.PCR1 = 0xa0; // ポート1のP15,P17を出力ポートに Init_rs(); //通信の初期化 AD.ADDRA=0; AD.ADDRB=0; AD.ADDRC=0; AD.ADDRD=0; //AD変換設定 //A/Dコンバータ設定 AD.ADCSR.BYTE = 0x33; // (0011 0011)*/ // スキャンモード,高速変換(70ステート),入力端子:AN0~AN3 set_imask_ccr(0); //割り込み可 while(1) { if(aflag==1){ aflag=0; ad_data_0=AD.ADDRA >> 6; // 「>>」:シフト演算子(ビットを右に6ずらす) ad0=ad_data_0*5000/1024; LToStr(G_data,carray0);//グローブ角度表示 rs_puts("ch.0="); rs_puts(carray0); rs_crlf(); wait(1); G_data=(ad0-2333)*(-0.0426);//グローブ角度 ad_data_1=AD.ADDRB >> 6; // 「>>」:シフト演算子(ビットを右に6ずらす) ad1=ad_data_1*5000/1024; LToStr(A_data,carray1);//アーム角度表示 rs_puts("ch.1="); rs_puts(carray1); rs_crlf(); wait(1);

みんなの回答

  • pyonmae
  • ベストアンサー率64% (40/62)
回答No.2

こんにちは。 8つあるAD変換をすべて使用=グループをまたいだAD変換 という事なのです。 つまり、レジスタが4つしかない以上、8つのAD変換を同時に使うという事がもう無理なのです。 挙げられたサイトのプログラムは、確かにスキャンモードを使用していますが、グループ毎の変換終了割り込みでグループを切り替えて再スタートをかけています。 グループ0→グループ1→グループ0→・・・とすごい勢いで「グループをまたいだ変換」を行っています。 もちろん、これでも目的の動作は行えますが、気になる点もあります。 ・割り込みが頻繁にかかって、多くのCPU処理をADのグループ切替えに持っていかれる。 ・AD変換動作中にもかかわらず強引に再スタートをかけるので、せっかくやりかかったAD変換が無駄になる。処理的にもスマートでない。 そもそも、そこまでスキャンモードにこだわらなければならないほど、リアルタイムにセンサを読まなければならないのか、ご検討下さい。 私なら、次の2案で検討します。 1. 先の回答に書いたように、都度都度AD変換をスタートする。 2. AD変換専用のタスクを立ち上げる。

  • pyonmae
  • ベストアンサー率64% (40/62)
回答No.1

こんにちは。 いきなりですが、結論から言いますと「できません」。 「グローブ角度」センサと、「アーム角度」センサを同一グループのアナログ入力端子に割り振るか、それが無理なら都度都度チャンネルを指定してAD変換を起動するようなソフトを実装する必要があると思います。 グループをまたいでしまうと、スキャンモードは全くといっていいほどメリットは無いでしょう。 蛇足ながら、業務で使用するシステムならば、スキャンモードで回しておいて不定なタイミングでレジスタ直値を測定値として採用する、といったようなルーズな仕様はあまり感心しないところです。 平均化するなどノイズ対策が必要でしょうし、アプリ中でハードウェアを直接叩くというのも見た感じあまりよろしくありません。 今一度設計から見直される事を、望むところであります。 もう一つ蛇足ながら、このご質問ですと、「C C++」カテゴリには相応しくないと思われます。

foxhound33
質問者

補足

回答ありがとうございました。 ご指摘いただいた点は検討してみます。 私の質問で至らない点があったので補足しますと 同一レジスタを1度に処理するということではなくただ単に8つあるAD変換をすべて使用したいという意図でした。 グループをまたいでAD変換したいというわけではなく、1度に4つまでしかAD変換ができないのでそれ以上使用したいので、そのようなときにはどういったようにプログラムすればよいかという質問内容のほうが正しかったです。すみませんでした。「グローブ角度1」センサをグループ0のAN0、「アーム角度1」センサをグループ0のAN1で1セットとしていった時に、「グローブ角度3」センサをグループ1のAN4、「アーム角度3」センサをグループ1のAN5という様にしたいので教えて下さい。 出来るようなサイトも載ってました http://rur.mech.tuat.ac.jp/~h8_tech/a-d.htm

関連するQ&A

  • 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/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--); }

  • 3048fマイコンでのA/D変換について

    マイコン初心者ですが今3048fマイコンを使ってA/D変換をしようとしているんですが、うまくいかないので教えて頂きたいです。 プログラムは下の通りです。 #include <3048.h> /* メイン関数 *****************************************/ void main(void){ int ad_data; P1.DDR = 0xff; /*port1出力に設定 表示LED */ P4.DDR = 0x00; /*port4入力に設定 操作用sw1~4 */ P4.PCR.BYTE = 0xff; /*port4プルアップon */ AD.ADCSR.BYTE = 0x33; /* SCAN MODE / CH0~3  */ while(AD.ADCSR.BIT.ADF == 0){} /* 4CH分の変換終了を待つ */ while(1){ if(P4.DR.BIT.B4 == 0){ /* sw1の時 */ ad_data = AD.ADDRA>>8; } else if(P4.DR.BIT.B5 == 0){ /* sw2の時 */ ad_data = AD.ADDRB>>8; } else if(P4.DR.BIT.B6 == 0){ /* sw3の時 */ ad_data = AD.ADDRC>>8; } else if(P4.DR.BIT.B7 == 0){ /* sw4の時 */ ad_data = AD.ADDRD>>8; } P1.DR.BYTE = ad_data & 0xFF; /*上位8bit分だけ表示させる */ } } このように4チャンネル分の0~5vのアナログ信号をスキャンモードでA/D変換し、それぞれ対応したスイッチを押すことによって現在どのくらいの電圧が来ているかLEDに2進数で表示させようとしています。しかしsw1とsw2、sw3とsw4がそれぞれ同じ値を表示しています。例えば、sw1を押したらADDRAの値が表示されますが、sw2を押しても同じADDRAの値が表示されます。またsw3とsw4も同じでどちらを押してもADDRCの値が表示されます。 4チャンネル分を同時にA/D変換することは元々出来ないのでしょうか?いろいろ調べてはいますが理由が分かりせん・・・ADDRA=ADDRB、でADDRC=ADDRDなのでしょうか?分かりにくいとは思いますが教えて頂けると幸いです。よろしくお願いいたします。

  • 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]に格納した後にどうすればいいのかわかりません。

  • PIC16F877を用いたC言語でのAD変換について

    PICを用いてAD変換をしようとしていますが,思うように出力が出ず困っています. 可変抵抗を用いて0-5V間を調整可能な入力をAN0ピンに接続し,AD変換の結果をBポートに出力しようとしています. 使用条件は,mikroC使用,PIC16F877使用,C言語使用,水晶20MHz,Aポート入力(AN0ピンアナログ入力),Bポート出力,Tad=1.6μsです. 以下のプログラムで間違っている点をご指摘いただきたいと考えています. unsigned int out_b; void port_initialize() { INTCON=0; //割り込みなし ADCON0=0x81; ADCON1=0x8E; //AD変換中の入力範囲設定は電源と共有 TRISA = 0x3f; //AD変換用ポート(1で入力) TRISB = 0; //出力用ポート(0で出力) PORTB = 0; } void value_initialize() { out_b=0; PORTB=out_b; } void main() { port_initialize(); value_initialize(); while(1){ //endless ADCON0=0x81; //AD変換bitを選択 Delay_us(24); //アクィジション時間+AD変換後の待ち時間 ADCON0=0x85; //AD変換開始 Delay_us(20); //AD変換待ち時間 out_b=ADC_Read(0); PORTB=out_b; } }

  • AD変換

    温度センサーからのデータを4-20mA又は0-10Vのアナログデータに変換する機器が既にあります。このアナログデータをパソコンに取り込んでデータ解析する方法を模索しております。そこで、前記の4-20mA又は0-10Vのアナログデータをデジタル変換し、パソコンのシリアルポート(RS232CやUSB)と繋げるた為の変換インタフェース機器を探しております。安価で信頼性の高い機器をご存じの方、アドバイスをお願い致します。

  • 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マイコンで 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までの対応にしました><どこがおかしいのか教えていただけるとてもうれしいです><助けてください;;

  • A/D変換について

    こんにちは。 卒業研究でH8/3052(秋月書店)のマイコンボートを使って実験しています。 ファックションジュネレータを使って周波数の様子をA/D変換で調べたいです。その結果をLCDで表示出すという流れでプログラム作っていましたが以下のようなエラーが出ました。 これは未定義のシンボルですADCSR、 これは未定義のシンボルですADDRA、 がたくさんでました。 これはプログラムが間違ってるのか、ヘッダファイルが間違ってるのか自分の実力では判断できないので皆さんの意見をお願いいたします。 一応プログラムを載せます。 長いので一部だけのせたいと思います。 #include <3048.H> #define E_SIG 0x20 #define RS_SIG 0x10 void ioinit(void) { P3.DDR = 0xff; //ポート3を全ビット出力に設定 } void adinit(void) { AD.ADCSR.BIT.ADF = 0; //ADFフラグクリア AD.ADCSR.BIT.SCAN = 0; //単一モード選択 AD.ADCSR.BIT.CKS = 1; //クロックセレクト AD.ADCSR.BIT.CH = 0; //チャネルセレクト AN0単一モード } ・ ・ ・ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・ ヘッダファイルはマイコンを買ったときに付属していたCDからコピーしたものです。 皆さんのご指摘よろしくお願いいたします。

  • H8/36064のAD変換データの文字列化について

    たびたびの質問失礼いたします。 前回シリアル通信によって文字化けがおきることについて質問させていただいたものです。 前回の質問後、10ビットのA/D変換データを文字列に置き換える方法を調べstatic void uint2Hex()によって文字列に置き換えを行っているのですがまだうまく解消できませんでした。 申し訳ないのですが再び助言をいただけないでしょうか。 H8/36064を使用しTera Termに取り込むことで確認を行っています。 ボーレートなどのシリアル通信の設定はマイコン側、Tera Term側であわせてあります。 #include "iodefine.h" #include <machine.h> //割り込みマスクビット変更関数set_imask_ccr() を使用するためのインクルードファイル #include <stdio.h> void main(void) { init(); while(1){ if(AD.ADCSR.BIT.ADF == 1) Getad(); } } init() //A/D変換およびタイマV初期設定用関数 { set_imask_ccr(1); //割り込み禁止設定 AD.ADCSR.BIT.SCAN = 1; AD.ADCSR.BIT.CH = 101; TV.TCRV1.BIT.ICKS = 0; TV.TCRV0.BIT.CKS = 3; //Φ/128 TV.TCORA = 115-1; //コンペアマッチAの値 TV.TCRV0.BIT.CCLR = 1; //タイマカウンタクリア TV.TCRV0.BIT.CMIEA = 1; //割り込み発生フラグ設定 set_imask_ccr(0); //割り込み禁止解除 } void initSCI3(void) //シリアル通信設定 { unsigned int dmy; IO.PMR1.BIT.TXD = 1; //TXD端子使用設定 SCI3.SCR3.BYTE = 0; //SCR3クリア SCI3.SMR.BYTE = 0; //SMRフォーマット設定 SCI3.BRR = 47; //9600bps for(dmy = 280;dmy > 0;dmy--); SCI3.SCR3.BIT.TE = 1; //送信動作許可 } void rs_putc(char c) //1文字送信 { while(SCI3.SSR.BIT.TDRE == 0); //トランスミットデータレジスタエンプティが真になるまで待機 SCI3.TDR = c; //トランスミットデータレジスタに送信データ(8bit)をセット SCI3.SSR.BIT.TDRE = 0; //「送信中」フラグを立てる } void rs_puts(char *st) //文字列送信 { while(*st != 0){ rs_putc(*st); st++; } } static void uint2Hex(unsigned long n, short upper, char *buf) { char c; char a = 'a'; short len = 0; short i, half; if(upper) a = 'A'; // 大文字/小文字の設定 // 16進文字列へ変換し文字数をカウント do{ i = n & 0x0F; if(i > 9) buf[len] = (unsigned char)(i + a - 10); else buf[len] = (unsigned char)(i + '0'); len++; n >>= 4; }while(n != 0); half = len >> 1; // 文字の並び順を直す for(i=0; i < half; i++){ c = buf[i]; buf[i] = buf[(len-1)-i]; buf[(len-1)-i] = c; } buf[len]='\0'; // 終端コードの挿入 } Getad() { volatile unsigned int *data = (unsigned int *)0xfa00; volatile unsigned int *data2 = (unsigned int *)0xfa10; initSCI3(); // SCI3初期化 *data =AD.ADDRA; *data = *data >> 6;//右に6bitシフト *data2 =AD.ADDRB; *data2 = *data2 >> 6;//右に6bitシフト rs_putc(*data); rs_putc(*data2); AD.ADCSR.BIT.ADF = 0; AD.ADCSR.BIT.ADST = 0; } #pragma interrupt (TimerV(vect=22)) //割り込み処理関数としてTimerVを宣言 void TimerV(void) { static int count; //20000回(0.1秒)ごとにGetad // コンペアマッチフラグを0に戻し、次のコンペアマッチに備える。 TV.TCSRV.BIT.CMFA = 0; if(count<100) count++; else { count = 0; AD.ADCSR.BIT.ADST = 1; //AD変換開始 } }

専門家に質問してみよう