H8マイコンで割り込みが任意の周期で設定できない

このQ&Aのポイント
  • H8マイコンで割り込みの任意の周期を設定する方法がわかりません。
  • タイマーVを使用して割り込み周期を設定しようとしましたが、うまくいきません。
  • H8の3694マイコンを使用しています。
回答を見る
  • ベストアンサー

H8マイコンで割り込みが任意の周期で設定できない

タイマーVで主にTV.TCRV0.BIT.CKS, TV.TCRV1.BIT.ICKS,TV.TCORAで設定すると思うのですが任意の周期になりません。 特に~~~に入る文がタイマーVによって設定した割り込み周期ごとに処理するように作成したのですが,うまくいきません。使用しているマイコンはH8の3694です。 作成したプログラムは以下の通りです。お気付きの点がございましたらご教授お願いいたします。 #include <3694.h> // H8 Tinyの内部I/O定義 #include <stdio.h> #define TCNT 400 // TCNT = 20MHz / (PWM周期=50kHz) #define Ref 240 #define pai 3.141519 unsigned int AdcResult1; // 出力電圧のAD変換出力の16bit変数 void InitH8(void) { //----------------------- // A/Dコンバータ設定 //----------------------- AD.ADCSR.BYTE = 0; // A/D変換停止 AD.ADCSR.BIT.ADIE = 1; // A/D変換割り込み許可 AD.ADCSR.BIT.SCAN =1; // スキャンモード AD.ADCSR.BIT.CKS = 1; // 高速変換 AD.ADCSR.BIT.CH = 001; // AN0-1 //タイマV設定 TV.TCRV0.BIT.CCLR = 1; // コンペアマッチAでTCNクリア TV.TCRV0.BIT.CKS = 3;   //20GHz/128=15.6KHz TV.TCRV1.BIT.ICKS =1; // TV.TCRV0.BIT.CMIEA = 1; // タイマVのコンペアAによる割り込み許可 TV.TCNTV = 0; // タイマカウンタクリア TV.TCORA =156 - 1; // タイムコンスタントレジスタA設定 15.6kHz / 156= 1kHz // タイマW 設定 TW.TMRW.BIT.CTS = 0; // TCNTカウント停止 TW.TCRW.BIT.CCLR = 1; // コンペアマッチAによりTCNTをクリア TW.TIOR0.BIT.IOB = 1; // コンペアマッチBによりFTIOB端子へ0出力 TW.TCRW.BIT.CKS = 0; // 内部クロックφ/1 = 20MHzでカウント } void int_ad (void) { ~~~ } void int_timerv(void) { TV.TCSRV.BIT.CMFA = 0; // タイマV割込みフラグクリア AD.ADCSR.BIT.ADST = 1; // AD変換開始 } void main(void) { DI; InitH8(); // H8_3694設定 EI; // 割込み許可 while(1); // 割込み待ち }

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

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

こんにちは。 PWMの動作につきましては、近いですが違います。 キャリアとコンペア(と呼んでいるのですね)が直接比較されるわけではありません。 が、PWMの話はスレ違いなので置いておきまして。 本題の、なぜ1KHzにならないかについては、申し訳ないですが正直わかりません。 設定値を見る限り、正しいように思います。 PWMで確認するのがまずい、と書きましたが、それが1250Hzになる理由かどうかはわかりません。 I/Oにしても直らなかった場合、私が考え付く可能性としては、 ・設定抜け(データシートの読み落とし) ・挙げられているソース部分以外で何かしている ・ハードウェアが変(25MHzのクリスタルが付いている?) ・その他、初歩的ミスの見落とし といったところでしょうか。 長々と引っ張ったのにすみません。 I/Oにしてみて、何かわかったら補足なりに挙げていただければ幸いです。。。

その他の回答 (8)

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

こんにちは。 逆にお聞きしたいのですが、PWMを使った現在のプログラムで、なぜ出力が変化するのか、理解されていますか? 周波数を確認する方法としては、全く適さないと思いますが・・・。 I/Oポートの操作は、PWM出力よりはるかに基礎的な事ですので、データシートを調べて、頑張ってみてください。 あと、前の方に書きました、「25MHzでブン回す」とは、プログラムは20MHzのクロックを想定して書かれていますが、実際には25MHzの水晶発振子が基板に実装されていたりしませんか?という事です。 まさかそんな事はないと思いますが、もしそうなら、プログラムの設定で1250Hzになるのも合点がいくのです。 念のためハード担当者にご確認されてみてはいかがでしょうか。 また、万一そうだとすると、オーバークロックってことでもありますし。

ash719
質問者

お礼

ありがとうございます。 TCNT 400でタイマーwのキャリアの周期を決定しています。400がキャリアのピーク値です。 割り込みが入るごとにcountを1つずつ増やし,コンペア値を0か400しています。 そしてコンペア値とキャリアを比較させてパルスを生成しています。この際0か400にしているのでキャリアの周期に依存せずに割り込み周期毎にHi,Lowが出力すると考えて作成しました。 I/Oポートの操作,また基本的なことから勉強してみます。

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

こんばんは。 ありがとうございます。 あまり深くは解析しておりませんが、確認の仕方に問題がある事は間違いなさそうです。 タイマーWのPWM出力ではなく、空いているポートを出力ポートにし、それをint_ad()内でパタパタさせるなどするように変更してみて下さい。 多分、タイマーv自体はちゃんと動いているんじゃないかなぁ、と思います。

ash719
質問者

お礼

ありがとうございます。 なぜダメなのか分りません... 今までPWM出力しか行っていない物で, 確認するプログラムも書いていただけたら幸いです。

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

こんにちは。 ありがとうございます。 1250Hz、つまり1.25KHzという事ですね? まず考えられるのは、ひょっとして25MHzのクロックでブン回していませんか? という事ですが。。。 ただ、先の補足にありましたが、タイマの設定を変えても周期が変化しなかった、というのがすごく引っかかります。普通に考えて、絶対変化するはずです。 ここはひとつ、『~~~』の部分もドドンと公開してもらえませんか? もちろん、本番用ではなく、現在確認用にポート出力している分です。 できればノーカットで、int_timerv()とかmain()とかもそのままつけてもらえるとありがたいです。

ash719
質問者

お礼

ありがとうございます。 25MHzのクロックでブン回すとはどうゆうことですか? ざっとこんな感じです。根本的に間違っているかも知れませんがよろしくお願いします。 #include <3694.h> #include <stdio.h> #define TCNT 400 //(PWM周期=50kHz) unsigned int AdcResult1; // 出力電圧のAD変換出力の16bit変数 int Vc0, Vc1; // 制御信号 int count = 0; void InitH8(void) { // A/Dコンバータ設定 AD.ADCSR.BYTE = 0; // A/D変換停止 AD.ADCSR.BIT.ADIE = 1; // A/D変換割り込み許可 AD.ADCSR.BIT.SCAN =1; // スキャンモード AD.ADCSR.BIT.CKS = 1; // 高速変換 AD.ADCSR.BIT.CH = 0; // AN0-1 //タイマV設定 TV.TCRV0.BIT.CCLR = 0; // コンペアマッチAでTCNクリア TV.TCRV0.BIT.CKS = 3; TV.TCRV1.BIT.ICKS =1; // 上記CKS = 2 と併用 20MHz / 128 = 1.25MHz TV.TCRV0.BIT.CMIEA = 1; // タイマVのコンペアAによる割り込み許可 TV.TCNTV = 0; // タイマカウンタクリア TV.TCORA =156; // タイムコンスタントレジスタA設定 250 / 1.25MHz = 200us // タイマW 設定 TW.TMRW.BIT.CTS = 0; // TCNTカウント停止 TW.TCRW.BIT.CCLR = 1; // コンペアマッチAによりTCNTをクリア TW.TIOR0.BIT.IOB = 1; // コンペアマッチBによりFTIOB端子へ0出力 TW.TCRW.BIT.CKS = 0; // 内部クロックφ/1 = 20MHzでカウント TW.TMRW.BIT.PWMB = 1; // FTIOB端子の出力モード = PWM TW.TCRW.BIT.TOB =1; // 最初のコンペアマッチAが発生するまでの端子出力値 = Low // PWM周期決定 PWM1デューティ初期化 TW.GRA = TCNT - 1; // PWMの周期 20MHz / TCNT TW.GRB = 0; // PWM1出力設定 デューティー0% TW.TMRW.BIT.CTS = 1; // Wタイマ TCNTカウント開始 } void int_ad (void) { AD.ADCSR.BIT.ADST = 0; // AD変換停止 AdcResult1 = AD.ADDRA; // 出力電圧のAD変換出力レジスタ値をRAMにコピー AdcResult1 = AdcResult1 >> 6;// 10bit結果を右に6bitシフトして16bit値に変換 count++; if (count <= 1) Vc1 = 0; if (1< count && count <=2 ) Vc1 = 400; if (count >= 2)count =0; TW.GRB =Vc1; void int_timerv(void) { TV.TCSRV.BIT.CMFA = 0; // タイマV割込みフラグクリア AD.ADCSR.BIT.ADST = 1; // AD変換開始 } void main(void) { DI; InitH8(); // H8_3694設定 EI; while(1); // 割込み待ち }

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

こんにちは。 えー何度もすみません。 状況は何となくわかってきました。 それで、現状の周期は、1KHzにならず、何Hzになっているのでしょうか?

ash719
質問者

お礼

TV.TCRV0.BIT.CKS = 3; TV.TCRV1.BIT.ICKS = 1 ; TV.TCORA =156-1 の設定で1250Hzになっています。

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

こんにちは。 ちょっとやりたい事と問題点を整理させてもらいたいのですが、 やりたい事は、次のような感じでしょうか。 ・1msごとにADコンバータを起動し、AD変換を行い、結果を取得。 ・現在はデバッグのため、チャネルAのみリードし、取得した値は捨てている。 これで正しいですか? 次に、問題点は、どっちですか? 1) ADコンバータ自体が動いていない 2) AD変換は行われるが、周期が期待通りでない。 1だとすると、挙げられたソース以外の部分が重要です。 2だとすると、どのくらいずれているのかという事が問題です。 計算上、タイマの周期は1001.6Hzとなりますが、まさかこれの事では、ないですよね・・・? そもそも、「任意の周期にならない」というのは、どうやって確認されているのでしょうか?

ash719
質問者

お礼

回答ありがとうございます。 問題は2番の周期が期待通りでないです。AD変換はできています。 今の現状として TV.TCRV0.BIT.CKS =3; → TV.TCRV0.BIT.CKS =1 TV.TCRV1.BIT.ICKS =1; TV.TCORA =156; に変更しても変化がありません。また1msにもなりません。 確認のためAD変換は行わずに以下のことをしております。 ~~~の部分にカウントを設けて1回読み込んだらPWM出力をHiに,2回読み込んだらPWM出力をLowにしてパルス時間を見て確認しています。

回答No.3

ここに掲載されたコードは、自分で書いたものですか? 理解されていないのなら、よく調べることをお薦めします。 H8は使ったことがないので、完全に説明することはできませんが、一般にAD変換をするシステムは、次のようになっているはずです。 main()  CPU全体の割り込みを禁止する。  AD変換の設定をする。  割り込みの設定をする。(割り込みベクトルなどの設定)  CPU全体の割り込みを許可する。  AD変換をスタートする。  while(1)  表示など。 int_ad() //これは、割り込みベクトルか、そこから呼ばれる。  ADを読む。  mainで表示したりする為のAD値を橋渡しする。  AD変換を再スタート // 今回はスキャンモードなので、不要のはず。 掲載のコードでは、AD変換をスタートする処理が、int_timerv(void)に書かれていますが、 何処からも呼ばれていません。あと、int_adは、明示的に割り込みベクトルに設定するようなことをしていませんが、名前が決められている関数とか、これは処理系がやってくれるとかいうことでいいんですかね?

ash719
質問者

お礼

細かな説明ありがとうございます。 コードは先輩のプログラム参考にして自分で作成したものです。 何分初心者なものですみません。 指摘して頂いたint_timerv(void)を重点的に プログラムの流れ,関数を見直してみます。

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

こんにちは。 『~~~』の中に、ADSTをクリアするコードは含まれていますでしょうか。 スキャンモードでADコンバータを一度スタートさせると、ソフトでADSTをクリアしない限りAD変換を実行し続けるようですが。。。

ash719
質問者

お礼

回答ありがとうございます。 『~~~』の中に以下のコードを書いています。 AD.ADCSR.BIT.ADF = 0;// AD変換後割込みフラグクリア AdcResult = AD.ADDRA;// AD変換出力レジスタ値をRAMにコピー AdcResult = AdcResult >> 6;// 10bit結果を右に6bitシフトして16bit値に変換 でADコンバータを停止させて書き込んでいます。

回答No.1

int_timerv()が呼ばれてないのでは?

ash719
質問者

お礼

回答ありがとうございます。 int_timerv()が呼ばれてないとはどうゆうことですか? またどう設定せればいいのですか? すみません。

関連するQ&A

  • 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/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/36064を使ったシリアル通信について

    今学校のほうでH8/36064をつかってA/D変換したデータをPCに送るためのプログラムを作っているのですが、取り込んだデータをシリアル通信を使ってPCに送るとどうしても文字化けしてしまいます。 だめな原因などを教えていただけないでしょうか。 /*プログラム*/ #include "iodefine.h" #include <machine.h> //割り込みマスクビット変更関数set_imask_ccr()を              //使用するためのインクルードファイル #include <stdio.h> void main(void) { 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 Sci3() //シリアル通信設定 { 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 sendCharSCI(char data) //データ送信設定 { while(SCI3.SSR.BIT.TDRE==0); //トランスミットデータレジスタエンプティが真になるまで待機 SCI3.TDR = data; //トランスミットデータレジスタに送信データ(8bit)をセット SCI3.SSR.BIT.TDRE = 0; //「送信中」フラグを立てる return; } void print(char *str) { while(*str !='\0') { sendCharSCI(*str); str++; } return; } Getad() { volatile unsigned int *data = (unsigned int *)0xfa00; volatile unsigned int *data2 = (unsigned int *)0xfa10; *data =AD.ADDRA; *data = *data >> 6; //右に6bitシフト *data2 =AD.ADDRB; *data2 = *data2 >> 6; //右に6bitシフト AD.ADCSR.BIT.ADF = 0; AD.ADCSR.BIT.ADST = 0; Sci3(); // SCI3初期化 sendCharSCI(*data); sendCharSCI(*data2); } #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変換開始 } }

  • 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/3694Fのマイコンを使っていてKXM52-1050という加

    現在H8/3694Fのマイコンを使っていてKXM52-1050という加速度センサから 加速度の電圧値を読み取ろうとしているんですがどうしてもX、Y、Z軸の値が 正常に出ません誰か助けてください。製作環境Gccで製作しています。 ソースはメインプログラムだけですが載せておきます。 void main(void) // メインルーチン { int sw; // swの状態を格納するための変数定義 long k; // A/D変換の変数定義 long ad,sei,syou; // A/D変換の値(整数部,小数部)を格納する変数の定義 long ad1,sei1,syou1; long ad2,sei2,syou2; unsigned long ad_data[3]; // A/D変換結果を格納する配列変数を定義 sw = 0; // swの初期化 set_adc(); // H8 A/Dコンバータを設定する init_lcd(); // LCDをイニシャライズする AD.ADCSR.BIT.ADST = 1; // A/D変換開始 //タクトスイッチが押されるまで、待機 while(1){ while(!AD.ADCSR.BIT.ADF); // 変換終了待ち ad_data[0] = (unsigned long)AD.ADDRA >> 6; // AN0 A/D変換結果を変数(ad_data[0])に格納 ad_data[1] = (unsigned long)AD.ADDRB >> 6; // AN1 A/D変換結果を変数(ad_data[1])に格納 ad_data[2] = (unsigned long)AD.ADDRC >> 6; // AN2 A/D変換結果を変数(ad_data[2])に格納 AD.ADCSR.BIT.ADF = 0; // 変換終了フラグをクリア for( k=0; k<=1; k++){ sw = IO.PDRB.BIT.B7; // swにsw14の状態を格納する ad = (unsigned long) ad_data[0]; // 0~5[V]=0~1023でA/D変換値を取得 sei = ad * 5 / 1023; // 電圧値の整数部1桁 syou = (ad * 5 - sei * 1023) * 100L / 1023; // 電圧値の小数部2桁 for( k=1; k<=2; k++){ ad1 = (unsigned long) ad_data[1]; // 0~5[V]=0~1023でA/D変換値を取得 sei1 = ad1 * 5 / 1023; // 電圧値の整数部1桁 syou1 = (ad1 * 5 - sei1 * 1023) * 100L / 1023; // 電圧値の小数部2桁 for( k=2; k<=3; k++){ ad2 = (unsigned long) ad_data[2]; // 0~5[V]=0~1023でA/D変換値を取得 sei2 = ad2 * 5

  • 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を使ってモータを、正逆回転するプログラムについてです。 よろしくお

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

  • (H8マイコン)タイマ割込で変更したグローバル変数がメインループ内で認識されない

    H8マイコンの学習をしています。 LEDを一定時間ごとに点滅させるためにタイマ割込を使用して時間稼ぎ処理を行おうとしました。 1ms毎の割込でグローバル変数をインクリメントし、メインループ内でグローバル変数が一定値以上になるまで無限ループする処理を作成しました。 しかし、メインループの数値チェックの無限ループが終了せずLEDが点滅しません。 原因についてお知恵を拝借できないでしょうか。 何卒よろしくお願いいたします。 以下は環境およびコードです。 マイコン:H8/36109(H8/H300 Tinyシリーズ) 使用ツール:HEW4, E8a (main.c) #include "iodefine.h" volatile unsigned int cnt; //グローバル変数 void main(void) {   cnt = 0;   while(cnt < 1000); //ここで無限ループのまま(補足も参照)   IO.PDR2.BIT.B0 = IO.PDR2.BIT.B0; //ここにブレークをかけても引っ掛らない } (intprg.c) #include <machine.h> #include "iodefine.h" extern volatile unsigned int cnt; #pragma section IntPRG  (略) // vector 22 Timer V __interrupt(vect=22) void INT_TimerV(void) {   cnt++; //(補足参照)   TV.TCSRV.BIT.CMFA = 0; //コンペアマッチフラグクリア } (hwsetup.c) void HardwareSetup(void) {   IO.PCR2 = 0xff; //出力ポート      //タイマVの設定   TV.TCRV0.BYTE = 0x4b; /* CMFA有効, コンペアマッチAでクリア, φ/128 = 125kHz */   TV.TCRV1.BYTE = 0x01; /* 外部入力禁止 */   TV.TCORA = 125; /* 1ms */   TV.TCSRV.BYTE = 0x00; /* フラグクリア, 出力禁止 */ } (補足) 割込動作内でブレークをかけるとブレークがかかり、そこからステップ実行するとグローバル変数が変化していることを確認しました。 同様に、メインループの数値チェック無限ループでブレークをかけ、条件を満たすようにグローバル変数を手動で書き換えステップ実行すると無限ループを脱出しました。

  • H8を使って、モータの正逆回転を制御するプログラムを作成したいのですが

    H8を使って、モータの正逆回転を制御するプログラムを作成したいのですがうまくいきません。よろしくお願いします。  h8 <3067F.h>を使ってDC電圧を入力してモータを制御するプログラムなのですが、入力電圧が2.5V(0x80)時は静止、2.5V(0x80)以上なら正回転、2.5V(0x80)以下なら逆回転するようにしたいのですがうまくいきません。プログラムはこんな感じです。 #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(ITU1.GRB > 0x80)            2.5v以上かの場合分け { ITU1.GRB = (AD.DRA - 0x80 >> 8); ここで正回転の方向と速度を決める。 PADR.BIT.B1 = 1; PADR.BIT.B2 = 0; } else                    その他 { ITU1.GRB = (0x80 - AD.DRA >> 8); ここで逆回転の方向と速度を決める。 PADR.BIT.B1 = 0;               PADR.BIT.B2 = 1; } AD.CSR.BIT.ADF = 0; AD.CSR.BIT.ADST = 1; /* A/D変換開始 */ }  if文のところで、減算を行い正なら正回転、elseは減算したら負になり逆回転する命令にしたいのですがどうしたらいいでしょうか。 よろしくお願いします。

  • 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変換開始 } }

専門家に質問してみよう