- ベストアンサー
H83052 ITUタイマ機能 時間の測定について
現在h8/3052でITUタイマを利用して1msecごとに割り込みがかかるようにしてそのときにセンサで測定した値をA/D変換させるプログラムを作成しました。モニタプログラムのGDB-STUBをROM領域に書き込んでおりますので、GDBで実際にデバッグを行ってみました。 その結果、毎回の割り込みごとのA/D変換終了時のタイマカウントの値をその時の時間としてみているのですが、その時間間隔が正確に1msecではなく、タイマのカウントが最大で3クロック分くらいずれが生じてしまう結果になってしまいました。 タイマカウンタには、誤差は全くないと思いますので、他の原因として考えられるのはプログラムの部分でしょうか?A/D変換の変換開始のタイミングや、終了待ちの関係でしょうか。 その誤差の部分についてわかることがありましたら、ご回答よろしくお願いします。 必要であれば、プログラム内容も載せたほうがよろしいでしょうか。
- みんなの回答 (4)
- 専門家の回答
関連するQ&A
- h8/3052 GDB-stub上でのプログラムの実行 ITUタイマ割込みの使用について
現在h8/3052でITUタイマを利用して20msecごとに割り込みがかかるようにするプログラムを作成していますが、割り込みに関して動作が確認できません。デバッグ環境を整えるためにターゲットにはあらかじめGDB-stubを書き込んであります。 実際に作成しているプログラムの割込みの部分は、 //割込み処理関数 pragma interrupt void int_imia0(void) //割り込み関数 { extern volatile unsigned int count; count ++; ITU0.TSR.BIT.IMFA = 0; } で割り込みが行われたときの処理を行い。 //メイン関数内 EnableInterrupt(); //割り込み許可 StartITU0(); //タイマスタート while (1){ AD.CSR.BIT.ADST = 1; /*変換スタート*/ while (AD.CSR.BIT.ADF == 0); /*変換終了待ち*/ data[c] = AD.DRA >> 6; /*下位へ6ビット分ずらす*/ data[c] = data[c] & 0x3ff; /*上位6ビットクリア*/ time[c] =(count * 2000000) + (ITU0.TCNT * 32); /*A/D変換処理時間の算出*/ if(time[c]>20000000) { bleak; } } のようにして、ここで20msecごとに割り込みがかかるように設定しています。 で、出力ファイルの //MAPファイル Name Origin Length Attributes vectors 0x00220000 0x00000100 r rom 0x00220100 0x00007f00 xr ram 0x00228000 0x00007000 xrw stack 0x0022f000 0x00001000 rw vectorアドレス ITU0割込みベクタアドレス(0x220060) 0x00220060 0x4 LONG 0x22020a DEFINED (_int_imia0)?<code 340> (_int_imia0):<code 340> (_start) として、外部RAM領域に設定したvectors領域のベクタ領域に割込み関数のアドレスが入るようにしています。 実際に動かすと、割込み関数でブレークポイントを設定しても割り込みがかからずにプログラムが動かなくなってしまいます。(どこかに飛んでいってしまっている。) ここで質問なのですが、GDB-stub上でプログラムを動かす場合に、 ・割り込みがかかった場合のベクタアドレスはGDB-stub側で設定しているベクタアドレス(内部ROM0x000060)に飛ぶようになってしまっているのか。 が、気になっています。
- 締切済み
- その他(プログラミング・開発)
- H8のITUトグル出力で 0出力で停止したい
ルネサス製H8/3052Fを使用しています。ITUを通常動作で使用して、GRAコンペアマッチでTIOAC端子からトグル出力を行う際にタイマを停止するとTIOACの出力レベルが 0 で停止してほしいのですが、停止した際に 0/1 どちらの状態になるかコントロールできずに困っています。 試しに、「タイマを停止するときにコンペアマッチで0出力を一度させてから停止する」という方法を使ってみたのですが、結果は変わりませんでした。以下、そのソースコードを記載します。どうやったらタイマ停止後に TIOCAの出力レベルを 0 にできるかアドバイスをいただけますようお願いします。 -------------------------------------------- #define ITU4_setBRA(val) ITU4.BRA = val // コンペアマッチによりBRAの値をGRAに自動転送 void ITU4_init(void){ ITU4.TCR.BIT.CCLR = 1; // GRAのコンペアマッチでTCNTをクリア ITU4.TCR.BIT.CKEG = 0; // 立ち上がりエッジでカウント ITU4.TCR.BIT.TPSC = 3; // φ/8 ITU4.TIOR.BIT.IOA = 3; // GRAコンペアマッチでトグル出力 ITU.TFCR.BIT.BFA4 = 1; // BRA4をGRAのバッファレジスタとして使用 ITU4.TCNT = 0; } void ITU4_start(void) { ITU4.TCNT = 0; ITU.TSTR.BIT.STR4 = 1; } void ITU4_stop(void) { int i; // 一度 GRAコンペアマッチで 0 を出力させてから、トグル出力に戻す。 ITU.TSTR.BIT.STR4 = 0; // カウント停止 ITU4.TIOR.BIT.IOA = 1; // GRAコンペアマッチで0出力 ITU4.GRA = 1; ITU4.BRA = 1; ITU.TSTR.BIT.STR4 = 1; // カウント開始 for(i=0; i<32; i++) ; // 無駄時間ループ ITU.TSTR.BIT.STR4 = 0; // カウント停止 ITU4.TIOR.BIT.IOA = 3; // GRAコンペアマッチでトグル出力 }
- 締切済み
- その他(プログラミング・開発)
- AKI-H8/3048Fでのタイマ割り込み
秋月電子で http://akizukidenshi.com/catalog/items2.php?p=1&q="K-00004" を買いマイコンの勉強をしています。 コンパイル等はGCC Developer Lite、モニタプログラムを使いRAM上で 動作確認をしています。 タイマによる割り込みをしたいと思い、参考書のプログラムを参考に マザーボード上の2つのLEDが交互に光るようにしたいのですが、 肝心のint_imaia0()が全く実行されていません。 #include <3048.h> int c; void int_imia0( void ) { ITU0.TSR.BIT.IMFA = 0; c -= 1; if( c == 0 ){ P5.DR.BYTE = ~ P5.DR.BYTE; c = 10; } } int main( void ) { c = 10; P5.DDR = 0x03; ITU0.TCR.BIT.CCLR = 1; ITU0.TCR.BIT.TPSC = 3; ITU0.GRA = 39999; ITU.TSTR.BIT.STR0 = 1; P5.DR.BYTE = 0x01; EI; while( 1 ){ } } また、割り込みを使わない方法ということで #include <3048.h> int main( void ) { int c = 10; P5.DDR = 0x03; ITU0.TCR.BIT.CCLR = 1; ITU0.TCR.BIT.TPSC = 3; ITU0.GRA = 39999; ITU.TSTR.BIT.STR0 = 1; P5.DR.BYTE = 0x01; while( 1 ){ while( !ITU0.TSR.BIT.IMFA ); c -= 1; if( c == 0 ){ P5.DR.BYTE = ~ P5.DR.BYTE; c = 10; } ITU0.TSR.BIT.IMFA = 0; } } を試したのですが、こちらはLEDが交互に点滅して成功しています。 なのでタイマ自体は動作していると思うのでですが、上のプログラムだと int_imaia0()動作しません。 何がいけないのでしょうか?よろしくお願いします。
- ベストアンサー
- C・C++・C#
- 【H8-3052F】タイマ割り込み
C言語もマイコンも初心者ですので情報が不足していたら笑って指摘してください。 今はルネサスのHigh-performance Embedded Workshop(Version 4.04.01.001)を使用してタイマ割り込みを実現しようとしてますが、タイマが動作しません。 出力結果も繰り返し処理が正常に動いてないように見えます。 原因等わかる方いらっしゃいましたら教えていただけますでしょうか。 可能でしたらソースコードもつけていただけると幸いです。 ---出力結果--- H8/3052F Monitor v1.12 Copyright (C) 1999-2004 CSE Tomakomai NCT 1:ld 1:go 00ffe000 change job wooooooooo! w ---ソースコード--- #include "3052f.h" #include "utility.h" #pragma interrupt ( aaa ) int cnt; extern void initITU( void ); void aaa() { debugString( "aaa!" ); cnt++; } void main(void) { InitializeSCI(); setDebugMode( true ); initITU(); // タイマーを初期化 ITU0.GRA = 20000; // タイマでカウントする値の設定 ITU0.TCNT = 0; // Reset ITU0.TCNT ITU.TSTR.BIT.STR0 = 1; // タイマ スタート debugString( "change job" ); while( 1 ){ if(cnt == 50){ debugString( "here we go!" ); cnt = 0; } else { debugString( "wooooooooo!" ); } } } void initITU() { ITU.TSNC.BIT.SYNC0 = 0; // 他チャンネルとの同期無し(独立動作) ITU.TSNC.BIT.SYNC1 = 0; // 他チャンネルとの同期無し(独立動作) ITU.TSNC.BIT.SYNC2 = 0; // 他チャンネルとの同期無し(独立動作) ITU.TSNC.BIT.SYNC3 = 0; // 他チャンネルとの同期無し(独立動作) ITU.TSNC.BIT.SYNC4 = 0; // 他チャンネルとの同期無し(独立動作) ITU0.TCR.BYTE = 0x03; // クロックの1/8で動作。TCNTのクリア禁止 ITU1.TCR.BYTE = 0x03; // クロックの1/8で動作。TCNTのクリア禁止 ITU2.TCR.BYTE = 0x03; // クロックの1/8で動作。TCNTのクリア禁止 ITU3.TCR.BYTE = 0x03; // クロックの1/8で動作。TCNTのクリア禁止 ITU4.TCR.BYTE = 0x03; // クロックの1/8で動作。TCNTのクリア禁止 ITU0.TIOR.BYTE = 0; // GRの制御。0x00でよい。 ITU1.TIOR.BYTE = 0; // GRの制御。0x00でよい。 ITU2.TIOR.BYTE = 0; // GRの制御。0x00でよい。 ITU3.TIOR.BYTE = 0; // GRの制御。0x00でよい。 ITU4.TIOR.BYTE = 0; // GRの制御。0x00でよい。 ITU0.TIER.BIT.IMIEA = 1; // 全割り込み許可(オーバーフロー/IMFA/IMFB) ITU1.TIER.BIT.IMIEA = 0; // 全割り込み禁止(オーバーフロー/IMFA/IMFB) ITU2.TIER.BIT.IMIEA = 0; // 全割り込み禁止(オーバーフロー/IMFA/IMFB) ITU3.TIER.BIT.IMIEA = 0; // 全割り込み禁止(オーバーフロー/IMFA/IMFB) ITU4.TIER.BIT.IMIEA = 0; // 全割り込み許可(オーバーフロー/IMFA/IMFB) }
- 締切済み
- C・C++・C#
- 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 3052について
マイコン、電気回路初心者です。 h8 3052で回転計を作製をしたいのですが・・・知識を貸していただきたいです マイコン初心者です。。。 h8 3052で回転計を作製をしたいのですが・・・知識を貸していただけたら幸いです。 回転数を算出の式として次を用いたいと思います(精度はあまり気にしないでください。。。) 回転数[rpm]=60[sec]/1回転に要する時間[sec] リードスイッチとマグネット4つを使い回転数を算出したいと思っています。 リードスイッチが4つカウントしたときの時間(1回転に要する時間)を上の式の分母(t)に入れ演算させたいです。 ITUのタイマー割り込みを使い分母の時間をカウントをしカウントが4のときt=0と考えてました。 しかし、カウントを迎えてもtは永遠に1ずつ足され続け0に戻りません。 プログラムの考え方が違うのでしょうか? 使用環境からロータリーエンコーダ、フォトトランジスタなどが使えません。 チャタリングについては、本からRC積分回路(0.1μFとVccに10KΩ)使い、そこからさらに74HC04通してつかっているのですが・・・見よう見まね状態です。 開発環境はHEWを使っています。 勉強不足だと思いますが、10日くらい悩んでいます。力を貸してください。よろしくお願いします。 僕が立てたプログラムは次の通りです。 vector 12 IRQ0 (リードスイッチ 立下りエッジで割り込み要求) __interrupt(vect=12) void INT_IRQ0(void) { count++; INTC.ISR.BIT.IRQ0F=0; } vector 28 IMIA1 __interrupt(vect=28) void INT_IMIA1(void) { ITU1.TSR.BIT.IMFA = 0; taco_interrput-=1; if(taco_interrput==0) { t++; } taco_interrput=1; } void main() { set_imask_ccr(1); //割り込み禁止 INTC.ISCR.BIT.IRQ0SC=1; //タコメータ 入力立下りエッジで割り込み発生 INTC.IER.BIT.IRQ0E=1; //IRQ0割り込み許可(タコメータ) ITU1.TCR.BIT.CCLR=1; //ITU1カウンタクリア要因 ITU1.TCR.BIT.TPSC=3; //ITU1 3.125MHz ITU1.GRA=3125-1; //ITU1 3.125MHz/3125=1000Hz、周期1ms(0からカウントされるため必ず-1) ITU1.TIER.BIT.IMIEA = 1; //ITU1 IMFAフラグによる割り込み許可 ITU.TSTR.BIT.STR1=1; //ITU1タイマスタート taco_interpput=1; //ITU(imia)割り込み回数1 割り込み先で1に戻るので無限 while(1) { if(count==4) { time=t; t=0; count=0; n=60[sec]/time; } if(count>4) //カウントが4より大きくなってしまったとき { t=0; count=0; } } } (LCDのプログラムは長いので省きました) LCDの液晶を使い以下のことは確認をしています。 ・カウントが4を迎えたときカウントは0に戻っています。(IRQのカウントのことです) ・カウントを何回与えてもtが0に戻りません。なので演算されてないです。(tは永遠に1ずつ足され続けてます) 回転数の使う範囲は50~200rpmです。 tのカウントを0に戻す記述をどうしたいいのかよろしくお願いします。
- 締切済み
- C・C++・C#
- H8を利用したPWMのパルス生成について
最近H8のマイコンを使い始めた者です。 PWMモードの波形を出力するプログラムを作っているのですが、出力波形が出ない事に困っています。 自分が作成したプログラムを以下に示しますので、 詳しい方いましたら、アドバイス頂けたらと思います。 よろしくお願いします。 #include <tlib.h> #include "3069S.h" const unsigned ptn[] = {4000, 16000, 2000, 10000}; unsigned long pos; unsigned long x; int main() { int i=1; pos=0; ITU.TSTR.BIT.STR0=0; //タイマのカウントを停止。 ITU0.TCR.BYTE=0x43; //GRBのコンペアマッチでクリア。1/8クロック ITU0.GRA=10000; //パルス幅を入力(5ms) ITU0.GRB=20000; //周期を入力(10ms) ITU.TMDR.BIT.PWM0=1; //ITU0をPWMモードに設定。 ITU.TSTR.BIT.STR0=1; //タイマのカウントをスタート while(1){ if(ITU.TISRB.BIT.IMFB0){ x=ITU.TISRB.BIT.IMFB0; ITU.TISRB.BIT.IMFB0=0; ITU0.GRA=ptn[pos]; pos++; pos &= 0x03; } } }
- ベストアンサー
- その他(プログラミング・開発)
- タイマーが動作しません
H8/3052を使っていろいろ動作させようと考えてます、 タイマー割り込みのところで詰まっていますが、タイマー割り込みを使ってLEDを反転するというプログラムです。 結果、LEDが反転しないつまり、タイマー割り込みが動作してないのではないかと考えています。 うちが使いたいタイマーはウオッチドッグタイマです。イエローで、C言語を使っています。 皆様の知識をお借りしたいです。 //20msごとに割り込み、50回の割り込みでLED点灯反転 #include <3048.h> //3048、3052の内部I/O定義 #include <sysio.h> int c; //割り込み回数、外部変数とする //ITUインターバルタイマ割り込み void int_imia0(void) { ITU0.TSR.BIT.IMFA = 0; //割り込みステータスフラグクリア c-=1; if(c==0){ P5.DR.BYTE = ~P5.DR.BYTE; //LED出力データを反転 c=50; } } int main(void) { P5.DDR = 0xff; ITU0.TCR.BIT.CCLR = 1; //カウンタクリア要因 ITU0.TCR.BIT.TPSC = 3; //タイマプリスケーラ25MHz/8=3.125MHz ITU0.GRA =62499; //3.125MHz/62,500=50Hz、周期20ms ITU0.TIER.BIT.IMIEA = 1; //IMFAフラグによる割り込み許可 ITU.TSTR.BIT.STR0 = 1; //タイマスタート P5.DR.BYTE = 0xff; //LED出力データ初期値 c=50; //割り込み回数 _ei(); //割り込み許可 while (1); //何もしない } 動作できない為、ご指摘よろしくお願いします。
- 締切済み
- C・C++・C#
- H83052 シリアル通信 A/D変換データ送信 について
毎回の質問失礼します。 現在H83052マイコンを使用して、センサで得た電圧値を1ms間隔でA/D変換させるプログラムを作成しています。 マイコンのA/D変換機能と、ITUタイマ機能を用いて測定を行うまでのプログラムの作成は何とか完了しました。 ここで、測定終了後データをどのようにして表示したらいいのかというところでとまっています。 データはA/D変換データ(data[]←int型)、A/D変換時の時間データ(time[]←long型)が、測定プログラム実行時に200個ずつ配列に保存されています。 これをそのままシリアル通信機能を用いてPC側に表示させるようにしたいのです。シリアル通信のH8側からPCへの送信の場合TDRにデータを書き込みそれをTxDより送信すると思うのですが、実際にTDRのアドレスは1バイトですので、データとしては入りません。1バイトごと分けて送信するという方法になってくるのではないかと考えていますが・・・ また、送信する時のコードとしては、数字データもアスキーコードとして送信されてしまうことになるのでしょうか? どなたか、わかることやアドバイスがあれば、回答よろしくお願いします。
- ベストアンサー
- その他(プログラミング・開発)
- H8を使ってモータを、正逆回転するプログラムについてです。 よろしくお
H8を使ってモータを、正逆回転するプログラムについてです。 よろしくお願いします。 H8(3067F.h)を使って2.5Vを基準として、2.5Vより上5.0まで正転し、2.5V以下0Vなら逆転、2.5Vなら静止するプログラムを作成したいのですが正逆回転のところで困っています。 #include <3067F.h> #pragma interrupt(adi) void initITU(void); void initITU1(void); void initAD(void); void initPA(void); main() { initPA(); initAD(); initITU(); initITU1(); /* Initalize ITU ch1 */ ITU.TSTR.BIT.STR1 = 1; /* Start ITU ch1 */ AD.CSR.BIT.ADST = 1; /* A/D変換 start */ while(1){ ; } } void initPA(void){ PADDR = 0xff; /* PortA 出力モード */ PADR.BYTE = 0x00; /* PA Clear */ } void initAD(void){ AD.CR.BIT.TRGE = 0; /* AD変換外部トリガ開始禁止 */ AD.CSR.BYTE = 0x00; /* ADCSR初期化, ch0のみ */ AD.CSR.BIT.ADIE = 1; /* AD変換終了後割り込み */ AD.CSR.BIT.CKS = 0; /* AD変換時間 : 135ステート */ AD.CSR.BIT.SCAN = 0; /* 単一モード */ } void initITU(void) { ITU.TSTR.BYTE = 0x00; ITU.TSNC.BYTE = 0x00; ITU.TISRA.BYTE = 0x00; /* Disable Interruption */ ITU.TISRB.BYTE = 0x00; /* Disable Interruption */ ITU.TISRC.BYTE = 0x00; /* Disable Interruption */ } void initITU1(void) { ITU.TMDR.BIT.PWM1 = 1; /* CH1 PWM mode */ ITU1.TCR.BYTE = 0x20; /* clear GRA comparematch,1/clock */ ITU1.GRA = 0; /* A/D変換器の保証bitは上位8bit */ ITU1.GRB = 0; ITU1.TIOR.BYTE = 0X00; /* prohibit GRA&GRB'output of comparematch */ } void adi(void) { AD.CSR.BIT.ADST = 0; /* A/D変換停止 */ if(AD.DRA && 0x80) /* open */ { PADR.BIT.B1 = 1; PADR.BIT.B2 = 0; ITU1.GRB = (AD.DRA >> 8); } else{ (AD.DRA - 0x80) = 0 /* close */ PADR.BIT.B1 = 1; PADR.BIT.B2 = 0; ITU1.GRB = (AD.DRA >> 8); } AD.CSR.BIT.ADF = 0; AD.CSR.BIT.ADST = 1; /* A/D変換開始 */ } プログラムは、このようになっています。 AD変換停止後のif文のあたりでコンパイルできなくなるのですがどうしたらいいでしょうか? お願いします。
- 締切済み
- C・C++・C#
お礼
<特に最終的には、内蔵メモリで実行されると思いますが <外部メモリと実行速度に差がでると思います。 実際に速度の違いが出てしまうと、最初のGRAの設定の部分でAD変換が終了した時点のTCNTカウンタの値が1msになるようにしているのでまずいかもしれません。その場合は設定しなおすしかないですね。 割り込み処理についての応答時間は確認していませんでした。かなりステート数に差がありますね。これも完全にぶれに含まれていますね。