tmr0について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ぱおぱお

tmr0について

#1

投稿記事 by ぱおぱお » 10ヶ月前

初心者です。はじめてタイマーを使ってみました。
2つのLEDを1秒ごとに交互にLチカをさせたかったのですが同時に点滅してしまいます。
質問①
どう記述すれば交互に点滅しますか?
質問②
オシロで測定すると1,060sで60msecほどずれがあります。
タイマーとはこういうものなのですか?
それともCの記述の仕方、または周期の計算がおかしいのでしょうか?
クロック:4MHz
プリスケール:256
質問③
1秒点灯2秒消灯などもひとつのタイマーでできるのでしょうか?
どう記述すればいいのでしょうか?

コード:

void interrupt InterTimer(void){
    if(T0IF == 1){
        cnt++;
        T0IF = 0;
        if(cnt >= 16){
            cnt = 0;
                PORTAbits.RA1 ^= 0x01;
                PORTAbits.RA0 ^= 0x01;
        }
        return;
    }
}
よろしくおねがいします。

アバター
みけCAT
記事: 6013
登録日時: 7年前
住所: 千葉県
連絡を取る:

Re: tmr0について

#2

投稿記事 by みけCAT » 10ヶ月前

ぱおぱお さんが書きました:質問①
どう記述すれば交互に点滅しますか?
PORTAbits.RA1とPORTAbits.RA0を最初に別の値(例えば1と0)で初期化しておけば、両方とも反転するプログラムなので「交互に点滅」になると思います。
ぱおぱお さんが書きました:質問②
オシロで測定すると1,060sで60msecほどずれがあります。
タイマーとはこういうものなのですか?
それともCの記述の仕方、または周期の計算がおかしいのでしょうか?
クロック:4MHz
プリスケール:256
(1÷(4MHz÷4(何クロックで1回タイマーが動くか)))×256(プリスケール)×256(タイマーの最大値+1)×16(ソフトウェアでの分周) = 1.048576秒
となるので、こういうものでしょう。
試していませんが、1,000,000÷(256×16)=244.140625なので、
割り込み処理にTMR0に(256-244=)12を加える処理を追加すると、ぴったりにはならないが改善するかもしれません。
ぴったりにするには、クロック周波数と分周比を工夫します。
ぱおぱお さんが書きました:質問③
1秒点灯2秒消灯などもひとつのタイマーでできるのでしょうか?
どう記述すればいいのでしょうか?
例えば変数stateを用意して0で初期化し、1秒ごとに
stateが0 → stateを1に、点灯
stateが1 → stateを2に、消灯
stateが2 → stateを0に、消灯
のようにすればできると思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

maru
記事: 145
登録日時: 7年前

Re: tmr0について

#3

投稿記事 by maru » 10ヶ月前

ぱおぱお さんが書きました: 質問①
どう記述すれば交互に点滅しますか?
片方のLEDを反転させればいいわけですから、以下のコードでも可能でしょう。

コード:

                PORTAbits.RA1 ^= 0x01;
                PORTAbits.RA0 = PORTAbits.RA1 ^ 0x01;
ぱおぱお さんが書きました: 質問②
オシロで測定すると1,060sで60msecほどずれがあります。
タイマーとはこういうものなのですか?
タイマそのものの精度はどうなんでしょう?
1,060sで60msecなら57ppmになります。温度補償のない水晶ならそのくらいはあり得ます。
まあ、みけCAT さんが書いている分周比のせいである可能性のほうがおおきいは思いますが。

アバター
みけCAT
記事: 6013
登録日時: 7年前
住所: 千葉県
連絡を取る:

Re: tmr0について

#4

投稿記事 by みけCAT » 10ヶ月前

みけCAT さんが書きました:ぴったりにするには、クロック周波数と分周比を工夫します。
例えば、5.1200MHzの水晶の1024クロック(4(クロックに1回インクリメント)×256(回インクリメントされるごとに割り込み))ごとの割り込みは0.2ms間隔になるので、
この割り込み5000回ごとに1回処理をすると、(水晶の誤差や処理にかかる時間を無視すれば)ちょうど1sごとの処理になります。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ぱおぱお

Re: tmr0について

#5

投稿記事 by ぱおぱお » 10ヶ月前

ぱおぱお さんが書きました:質問②
オシロで測定すると1,060sで60msecほどずれがあります。
タイマーとはこういうものなのですか?
それともCの記述の仕方、または周期の計算がおかしいのでしょうか?
クロック:4MHz
プリスケール:256
(1÷(4MHz÷4(何クロックで1回タイマーが動くか)))×256(プリスケール)×256(タイマーの最大値+1)×16(ソフトウェアでの分周) = 1.048576秒
となるので、こういうものでしょう。
試していませんが、1,000,000÷(256×16)=244.140625なので、
割り込み処理にTMR0に(256-244=)12を加える処理を追加すると、ぴったりにはならないが改善するかもしれません。
ぴったりにするには、クロック周波数と分周比を工夫します。

クロック周波数の工夫?の仕方がわからなかったので
プリスケールを16、分周を245にして誤差を少なくする方法にしてみました。
ぱおぱお さんが書きました:質問③
1秒点灯2秒消灯などもひとつのタイマーでできるのでしょうか?
どう記述すればいいのでしょうか?
例えば変数stateを用意して0で初期化し、1秒ごとに
stateが0 → stateを1に、点灯
stateが1 → stateを2に、消灯
stateが2 → stateを0に、消灯
のようにすればできると思います。[/quote]

実現(記述)できるかはわかりませんがイメージはわかりました。
挑戦してみます。ありがとうございます。

ぱおぱお

Re: tmr0について

#6

投稿記事 by ぱおぱお » 10ヶ月前

maru さんが書きました:
ぱおぱお さんが書きました: 質問①
どう記述すれば交互に点滅しますか?
片方のLEDを反転させればいいわけですから、以下のコードでも可能でしょう。

コード:

                PORTAbits.RA1 ^= 0x01;
                PORTAbits.RA0 = PORTAbits.RA1 ^ 0x01;
なるほど!
C言語はきっと下位2ビットをマスク掛けてビットシフトさせて・・・などと難しく考えていました。
ありがとうございます。

ぱおぱお

Re: tmr0について

#7

投稿記事 by ぱおぱお » 10ヶ月前

みけCAT さんが書きました:
ぱおぱお さんが書きました:質問②
オシロで測定すると1,060sで60msecほどずれがあります。
タイマーとはこういうものなのですか?
それともCの記述の仕方、または周期の計算がおかしいのでしょうか?
クロック:4MHz
プリスケール:256
(1÷(4MHz÷4(何クロックで1回タイマーが動くか)))×256(プリスケール)×256(タイマーの最大値+1)×16(ソフトウェアでの分周) = 1.048576秒
となるので、こういうものでしょう。
試していませんが、1,000,000÷(256×16)=244.140625なので、
割り込み処理にTMR0に(256-244=)12を加える処理を追加すると、ぴったりにはならないが改善するかもしれません。
ぴったりにするには、クロック周波数と分周比を工夫します。
連投で申し訳ありません。
TMR0に12を加えるとは直接
TMR0 = 0x0C;
とすればいいのでしょうか?

アバター
みけCAT
記事: 6013
登録日時: 7年前
住所: 千葉県
連絡を取る:

Re: tmr0について

#8

投稿記事 by みけCAT » 10ヶ月前

ぱおぱお さんが書きました:TMR0に12を加えるとは直接
TMR0 = 0x0C;
とすればいいのでしょうか?
加えるとは加えるであり、TMR0 += 0x0C;のことです。
関数呼び出しや条件分岐などの処理の分クロックが進んでいるので、足したほうがいいと考えました。
もっとも、プリスケールが256なので、256命令は使わないので代入でもいいのかもしれませんが。

※試していないので完全に間違っているかもしれません
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ぱおぱお

Re: tmr0について

#9

投稿記事 by ぱおぱお » 10ヶ月前

みけCAT さんが書きました:
ぱおぱお さんが書きました:TMR0に12を加えるとは直接
TMR0 = 0x0C;
とすればいいのでしょうか?
加えるとは加えるであり、TMR0 += 0x0C;のことです。
関数呼び出しや条件分岐などの処理の分クロックが進んでいるので、足したほうがいいと考えました。
もっとも、プリスケールが256なので、256命令は使わないので代入でもいいのかもしれませんが。

※試していないので完全に間違っているかもしれません
なるほどです。
ちなみにTMRが動いてるかどうかの確認方法はありますか?
いろいろ触ってたら分周などを変えてもなんの変化もしなくなってしまいました。

アバター
みけCAT
記事: 6013
登録日時: 7年前
住所: 千葉県
連絡を取る:

Re: tmr0について

#10

投稿記事 by みけCAT » 10ヶ月前

ぱおぱお さんが書きました:ちなみにTMRが動いてるかどうかの確認方法はありますか?
扱っているマイコン(?)がわかりませんが、
TMR0がレジスタとして実装されていて、各レジスタの値が確認できるシミュレータが利用できる機種および環境であれば、シミュレータを利用するのが一つの確認方法でしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ぱおぱお

Re: tmr0について

#11

投稿記事 by ぱおぱお » 10ヶ月前

みけCAT さんが書きました:
ぱおぱお さんが書きました:ちなみにTMRが動いてるかどうかの確認方法はありますか?
扱っているマイコン(?)がわかりませんが、
TMR0がレジスタとして実装されていて、各レジスタの値が確認できるシミュレータが利用できる機種および環境であれば、シミュレータを利用するのが一つの確認方法でしょう。
MPLAB Xのシミュレータでちゃんと動作していることが確認できました。
さらにTMR0に12を加えたら誤差がなくなりました。
みけCATさんいつもありがとうございます。

返信

“C言語何でも質問掲示板” へ戻る