現在h8/3052でITUタイマを利用して1msecごとに割り込みがかかるようにしてそのときにセンサで測定した値をA/D変換させるプログラムを作成しました。モニタプログラムのGDB-STUBをROM領域に書き込んでおりますので、GDBで実際にデバッグを行ってみました。
その結果、毎回の割り込みごとのA/D変換終了時のタイマカウントの値をその時の時間としてみているのですが、その時間間隔が正確に1msecではなく、タイマのカウントが最大で3クロック分くらいずれが生じてしまう結果になってしまいました。
タイマカウンタには、誤差は全くないと思いますので、他の原因として考えられるのはプログラムの部分でしょうか?A/D変換の変換開始のタイミングや、終了待ちの関係でしょうか。
その誤差の部分についてわかることがありましたら、ご回答よろしくお願いします。
必要であれば、プログラム内容も載せたほうがよろしいでしょうか。
No.4ベストアンサー
- 回答日時:
そうでした。
TCRのCCLR0,1がゼロなので、クリアしないので、GRAのセットタイミングを
変えてもタイミングはかわりませんね。
いわゆるクロック時間で0.04usの1~4クロックぐらいはソフトで処理するとどうしても
ずれるんじゃないでしょうか?
割込み処理についても、応答時間にぶれがあります。
[ハードウエアマニュアル5.4.3 割り込み応答時間 参照]
特に最終的には、内蔵メモリで実行されると思いますが
外部メモリと実行速度に差がでると思います。
<特に最終的には、内蔵メモリで実行されると思いますが
<外部メモリと実行速度に差がでると思います。
実際に速度の違いが出てしまうと、最初のGRAの設定の部分でAD変換が終了した時点のTCNTカウンタの値が1msになるようにしているのでまずいかもしれません。その場合は設定しなおすしかないですね。
割り込み処理についての応答時間は確認していませんでした。かなりステート数に差がありますね。これも完全にぶれに含まれていますね。
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;
そうですね。
と思ったのですが、自分のやり方が、1ms分のカウンタ値をGRAに割り込みごとに足していく方法ですので、1回目はそれで計測できるのですが、2回目の割り込み以降AD変換時間影響がtime1_Mae[c]に入ってしまいます。
素直にAD変換の部分を抜かして測定してみましたが、誤差の範囲はあまり変化しませんでした。割り込みの部分にもそういったタイミングの問題がありそうです。
No.2
- 回答日時:
毎度です。
3クロックのずれぐらいなら、問題になるのもヘンな気がしますが?
タイマはそうずれませんが、AD変換時間は、ステート数は常にづれる
のではないでしょうか? マニュアルにも
変換時間 266ステート(max) 134ステート(max)とあるようにきっちり
した時間ではできないようです。
さすれば、
1)タイマーの再設定をAD変換前にする。
(従来の1ms待って、ではなく、1ms周期になります)
2)スキャンモード
それから、スキャンモードにして、常時AD値を変換させて
おいて、1ms毎に最新データを読むだけ というやりかたも
ありかと思いますが。
毎度の回答ありがとうございます。
そうですね3クロックのずれくらいならば、問題にならないとは感じています。
ただ
・その誤差が自分の作成したプログラムの方法によって生じてしまう問題(誤差を減らせる)
・クロックの関係よりくる、タイミングのずれ(誤差は少なくともこれだけ発生してしまう)
のどちらに原因があるのか、知りたかったので。。。
タイマーの再設定をAD変換前にする方法の方が周期的にはよいみたいですね。やってみます。
スキャンモードについては、考慮していましたが、最新のデータがちゃんと1ms(誤差の範囲内)のデータであるのか少し微妙な気がします。常時AD変換を行うサイクルとかのタイミングというのも関係してくると思いますが。
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変換の完了を割り込みで処理する実装と比較することで、原因の特定が容易になることもありますね。
以上、参考になれば、、、。
この回答への補足
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];
}
}
}
回答本当にありがとうございます。
やはり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関数は、補足に記載します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Mac 乗数の入力方法
-
VC++2005で、CString型に16進...
-
IEEE754 の binary32形式を10進...
-
分を時間に変換するプログラム
-
緯度、経度の 10進法と 60進法...
-
シーケンサ 数字の変換
-
変換ソフトについて
-
マンセル⇔XYZ,RGB変換式或いは...
-
ハフ変換の原理をわかりやすく...
-
日本語をUnicodeに変換したい
-
SJIS⇔UTF-8の文字コード...
-
VB6からVB2010への変換
-
H8/3664FのAD変換について
-
PIC AD変換
-
excel vba 複数行が選択でき...
-
エクセルのVBAで、複数ファイル...
-
画像の平面射影変換について。
-
携帯電話メーカーの大まかな特...
-
家電製品の電力周波数を変える機械
-
isoをimgに変換したいのですが...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
緯度、経度の 10進法と 60進法...
-
家電製品の電力周波数を変える機械
-
3のつく数字と3の倍数のみを表...
-
エクセルVBAの自動変換機能?
-
10進数をBCDに変換する方法
-
Mac 乗数の入力方法
-
なぜ通信には16進数文字列が使...
-
VB6からVB2010への変換について
-
VB.NETからJavaに変換するツー...
-
C/C++→JAVAに変換するツール
-
【EXCEL】カナ、ひらがなを英字...
-
VB6で10進数を32進数に変換する...
-
逆コンパイルと逆アセンブルの...
-
分を時間に変換するプログラム
-
php
-
VB.NETをJavaに変換するツール...
-
C#でのpngからbmpへの変換について
-
C++からCへのソース変換について
-
マンセル⇔XYZ,RGB変換式或いは...
-
画像ファイル変換(Tiff→PDF)
おすすめ情報