• ベストアンサー

H83052 ITUタイマ機能 時間の測定について

現在h8/3052でITUタイマを利用して1msecごとに割り込みがかかるようにしてそのときにセンサで測定した値をA/D変換させるプログラムを作成しました。モニタプログラムのGDB-STUBをROM領域に書き込んでおりますので、GDBで実際にデバッグを行ってみました。 その結果、毎回の割り込みごとのA/D変換終了時のタイマカウントの値をその時の時間としてみているのですが、その時間間隔が正確に1msecではなく、タイマのカウントが最大で3クロック分くらいずれが生じてしまう結果になってしまいました。 タイマカウンタには、誤差は全くないと思いますので、他の原因として考えられるのはプログラムの部分でしょうか?A/D変換の変換開始のタイミングや、終了待ちの関係でしょうか。 その誤差の部分についてわかることがありましたら、ご回答よろしくお願いします。 必要であれば、プログラム内容も載せたほうがよろしいでしょうか。

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

  • ベストアンサー
  • R32C
  • ベストアンサー率39% (115/290)
回答No.4

そうでした。 TCRのCCLR0,1がゼロなので、クリアしないので、GRAのセットタイミングを 変えてもタイミングはかわりませんね。 いわゆるクロック時間で0.04usの1~4クロックぐらいはソフトで処理するとどうしても ずれるんじゃないでしょうか? 割込み処理についても、応答時間にぶれがあります。 [ハードウエアマニュアル5.4.3 割り込み応答時間 参照] 特に最終的には、内蔵メモリで実行されると思いますが 外部メモリと実行速度に差がでると思います。

utaibito33
質問者

お礼

<特に最終的には、内蔵メモリで実行されると思いますが <外部メモリと実行速度に差がでると思います。 実際に速度の違いが出てしまうと、最初のGRAの設定の部分でAD変換が終了した時点のTCNTカウンタの値が1msになるようにしているのでまずいかもしれません。その場合は設定しなおすしかないですね。 割り込み処理についての応答時間は確認していませんでした。かなりステート数に差がありますね。これも完全にぶれに含まれていますね。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

  • R32C
  • ベストアンサー率39% (115/290)
回答No.3

誤差が、AD変換時間であるかどうかは、変換前に時間計測して 変換後の時間と比べればよいかと思います。 ---------------------------------追加---- time1_Mae[c] = ITU0.TCNT; ---------------------------------追加---- ITU0.TSR.BIT.IMFA =0; AD.CSR.BIT.ADST=1; while (AD.CSR.BIT.ADF ==0); time1[c]=ITU0.TCNT;

utaibito33
質問者

お礼

そうですね。 と思ったのですが、自分のやり方が、1ms分のカウンタ値をGRAに割り込みごとに足していく方法ですので、1回目はそれで計測できるのですが、2回目の割り込み以降AD変換時間影響がtime1_Mae[c]に入ってしまいます。 素直にAD変換の部分を抜かして測定してみましたが、誤差の範囲はあまり変化しませんでした。割り込みの部分にもそういったタイミングの問題がありそうです。

全文を見る
すると、全ての回答が全文表示されます。
  • R32C
  • ベストアンサー率39% (115/290)
回答No.2

毎度です。 3クロックのずれぐらいなら、問題になるのもヘンな気がしますが? タイマはそうずれませんが、AD変換時間は、ステート数は常にづれる のではないでしょうか? マニュアルにも 変換時間 266ステート(max) 134ステート(max)とあるようにきっちり した時間ではできないようです。 さすれば、 1)タイマーの再設定をAD変換前にする。  (従来の1ms待って、ではなく、1ms周期になります) 2)スキャンモード それから、スキャンモードにして、常時AD値を変換させて おいて、1ms毎に最新データを読むだけ というやりかたも ありかと思いますが。

utaibito33
質問者

お礼

毎度の回答ありがとうございます。 そうですね3クロックのずれくらいならば、問題にならないとは感じています。 ただ ・その誤差が自分の作成したプログラムの方法によって生じてしまう問題(誤差を減らせる) ・クロックの関係よりくる、タイミングのずれ(誤差は少なくともこれだけ発生してしまう) のどちらに原因があるのか、知りたかったので。。。 タイマーの再設定をAD変換前にする方法の方が周期的にはよいみたいですね。やってみます。 スキャンモードについては、考慮していましたが、最新のデータがちゃんと1ms(誤差の範囲内)のデータであるのか少し微妙な気がします。常時AD変換を行うサイクルとかのタイミングというのも関係してくると思いますが。

全文を見る
すると、全ての回答が全文表示されます。
  • bug_bug
  • ベストアンサー率78% (36/46)
回答No.1

プログラム設計の仕様が見えないと誤差の原因特定は難しいですね。 タイマ割り込み処理、A/D変換完了割り込み処理、メインループ、各割り込みの優先度辺りの内容が把握できると動作がイメージできますが。 以下、駄文。 例えば前回提示いただいたサンプルの様な実装の場合、タイマ割り込みはカウンターのインクリメントのみ行い、メインループにてA/D変換の完了をポーリングする実装になっています。 while (AD.CSR.BIT.ADF == 0); といった待ち方をした場合、 ポーリングでA/Dの完了フラグをリードする以上、内部レジスタのリードアクセスはクロック同期である為、毎回の完了確認に誤差が発生します。(ポーリングによる誤差) さらにタイマカウンタはφで指定した間隔でインクリメントされますが、A/D変換は同期していませんので、誤差の算出を前回のA/D変換が終了した際取得したTCNT値からの差分で算出しているのであれば、前回のTCNT値取得がインクリメント寸前で取得され、今回のTCNT取得がインクリメント直後で取得されることが原因で1,2クロックズレることも考えられます。(時間の取得方法による誤差) また、A/D変換の完了とタイマのコンペアマッチがほぼ同時に発生した場合、割り込み処理が完了するまでメインのループはCPUを使用できません。 A/D変換完了フラグをリードする処理が待たされ、結果TCNT値の取得も遅延して取得する結果となります。 (優先度による誤差) ぱっと思いつく要因3点ですが、タイマの取得のたびに「揺れ」が発生するのであればここらが原因でしょうか。 逆にA/D変換の完了を割り込みで処理する実装と比較することで、原因の特定が容易になることもありますね。 以上、参考になれば、、、。

utaibito33
質問者

お礼

回答本当にありがとうございます。 やはりwhile文で待った時に誤差が生じる原因になっているとは思いました。現在のプログラムは以下になっており、タイムの取得のたびに微妙にずれが生じています。 やはりwhile文を何回も使用しているのが原因になっているのでしょうか。 #include "H83052-itu.H" int n,c,t; unsigned long time1[201]; unsigned long time2[201]; unsigned long time3[201]; unsigned long time4[201]; unsigned int data[201]; void initITU0(void) { ITU0.TCR.BIT.CCLR0 = 0; //カウンタのクリア要因 TCNTカウンタのクリア禁止 ITU0.TCR.BIT.TPSC = 3; // クロックのφ/8で動作(25MHz=1クロック0.04[μsec] ITU0.TIOR = 0; // コンペアマッチによるITU端子出力の禁止 ITU0.TIER.BIT.IMIEA=1; ITU0.GRA = 3064; //1msecごとの測定が可能になるように調整 1000[usec]/0.32[usec]=3124[クロック]-A/D変換に必要なクロック数 ITU.TSTR.BIT.STR0 = 0; //チャネル0のTCNTの停止を選択 ITU0.TCNT = 0; //タイマカウント値クリア } #pragma interrupt void int_imia0(void) { ITU0.TSR.BIT.IMFA =0; AD.CSR.BIT.ADST=1; while (AD.CSR.BIT.ADF ==0); time1[c]=ITU0.TCNT; data[c] = AD.DRA >> 6; /*下位へ6ビット分ずらす*/ data[c] = data[c] & 0x3ff; /*上位6ビットクリア*/ AD.CSR.BIT.ADF = 0; /*変換終了*/ c++; ITU0.GRA = ITU0.GRA + 3124; if(c==201){ t=0; } } 字数が足りないのでmain関数は、補足に記載します。

utaibito33
質問者

補足

int main(void) { while(1){ PA.DDR = 0x00; Init_AD(); //A/Dconverter初期化 c=1; t=1; initITU0(); //タイマITU0の初期化 EnableInterrupt(); while(PA.DR.BIT.DR0=0); //信号待ち(SW0:PA-0) for(n=0;n<201;n++){ data[n]=0; time1[n]=0; time2[n]=0; time3[n]=0; time4[n]=0; } ITU.TSTR.BIT.STR0 = 1; //TCNTの動作を選択=タイマスタート while (t); ITU.TSTR.BIT.STR0 = 0; //チャネル0のTCNTの停止を選択 for(c=1;c<201;c++){ if(time1[c]>time1[c-1]){ time2[c] = time1[c] - time1[c-1]; } else{ time2[c] = 65535 + time1[c] - time1[c-1]; } time3[c] = (time2[c]+1) * 32; time4[c] = time4[c-1] + time3[c]; } } }

全文を見る
すると、全ての回答が全文表示されます。

関連する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()動作しません。 何がいけないのでしょうか?よろしくお願いします。

  • 【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) }

  • 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に戻す記述をどうしたいいのかよろしくお願いします。

  • 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); //何もしない } 動作できない為、ご指摘よろしくお願いします。

  • 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文のあたりでコンパイルできなくなるのですがどうしたらいいでしょうか? お願いします。