合計 昨日 今日

tmr0について

フォーラムルール
フォーラムルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Name: ぱおぱお
[URL]
Date: 2017年8月07日(月) 09:32
No: 1
(OFFLINE)

 tmr0について

初心者です。はじめてタイマーを使ってみました。
2つのLEDを1秒ごとに交互にLチカをさせたかったのですが同時に点滅してしまいます。
質問①
どう記述すれば交互に点滅しますか?
質問②
オシロで測定すると1,060sで60msecほどずれがあります。
タイマーとはこういうものなのですか?
それともCの記述の仕方、または周期の計算がおかしいのでしょうか?
クロック:4MHz
プリスケール:256
質問③
1秒点灯2秒消灯などもひとつのタイマーでできるのでしょうか?
どう記述すればいいのでしょうか?
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
void interrupt InterTimer(void){
    if(T0IF == 1){
        cnt++;
        T0IF = 0;
        if(cnt >= 16){
            cnt = 0;
                PORTAbits.RA1 ^= 0x01;
                PORTAbits.RA0 ^= 0x01;
        }
        return;
    }
}

よろしくおねがいします。

Name: みけCAT
[URL]
伝説なるハッカー(670,973 ポイント)
Date: 2017年8月07日(月) 11:32
No: 2
(ONLINE)

 Re: tmr0について

ぱおぱお さんが書きました:質問①
どう記述すれば交互に点滅しますか?

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で殴ればいい!(死亡フラグ)

Name: maru
[URL]
中級者(11,690 ポイント)
Date: 2017年8月07日(月) 12:15
No: 3
(OFFLINE)

 Re: tmr0について

ぱおぱお さんが書きました:質問①
どう記述すれば交互に点滅しますか?

片方のLEDを反転させればいいわけですから、以下のコードでも可能でしょう。
コード[C++]: 全て選択
1
2
                PORTAbits.RA1 ^= 0x01;
                PORTAbits.RA0 = PORTAbits.RA1 ^ 0x01;


ぱおぱお さんが書きました:質問②
オシロで測定すると1,060sで60msecほどずれがあります。
タイマーとはこういうものなのですか?

タイマそのものの精度はどうなんでしょう?
1,060sで60msecなら57ppmになります。温度補償のない水晶ならそのくらいはあり得ます。
まあ、みけCAT さんが書いている分周比のせいである可能性のほうがおおきいは思いますが。

Name: みけCAT
[URL]
伝説なるハッカー(670,973 ポイント)
Date: 2017年8月07日(月) 18:14
No: 4
(ONLINE)

 Re: tmr0について

みけCAT さんが書きました:ぴったりにするには、クロック周波数と分周比を工夫します。

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

Name: ぱおぱお
[URL]
Date: 2017年8月08日(火) 11:06
No: 5
(OFFLINE)

 Re: tmr0について

ぱおぱお さんが書きました:質問②
オシロで測定すると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]

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

Name: ぱおぱお
[URL]
Date: 2017年8月08日(火) 11:09
No: 6
(OFFLINE)

 Re: tmr0について

maru さんが書きました:
ぱおぱお さんが書きました:質問①
どう記述すれば交互に点滅しますか?

片方のLEDを反転させればいいわけですから、以下のコードでも可能でしょう。
コード[C++]: 全て選択
1
2
                PORTAbits.RA1 ^= 0x01;
                PORTAbits.RA0 = PORTAbits.RA1 ^ 0x01;


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

Name: ぱおぱお
[URL]
Date: 2017年8月08日(火) 11:20
No: 7
(OFFLINE)

 Re: tmr0について

みけ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;
とすればいいのでしょうか?

Name: みけCAT
[URL]
伝説なるハッカー(670,973 ポイント)
Date: 2017年8月08日(火) 11:24
No: 8
(ONLINE)

 Re: tmr0について

ぱおぱお さんが書きました:TMR0に12を加えるとは直接
TMR0 = 0x0C;
とすればいいのでしょうか?

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

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

Name: ぱおぱお
[URL]
Date: 2017年8月08日(火) 14:12
No: 9
(OFFLINE)

 Re: tmr0について

みけCAT さんが書きました:
ぱおぱお さんが書きました:TMR0に12を加えるとは直接
TMR0 = 0x0C;
とすればいいのでしょうか?

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

※試していないので完全に間違っているかもしれません

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

Name: みけCAT
[URL]
伝説なるハッカー(670,973 ポイント)
Date: 2017年8月09日(水) 00:15
No: 10
(ONLINE)

 Re: tmr0について

ぱおぱお さんが書きました:ちなみにTMRが動いてるかどうかの確認方法はありますか?

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

Name: ぱおぱお
[URL]
Date: 2017年8月09日(水) 08:53
No: 11
(OFFLINE)

 Re: tmr0について

[解決!]

みけCAT さんが書きました:
ぱおぱお さんが書きました:ちなみにTMRが動いてるかどうかの確認方法はありますか?

扱っているマイコン(?)がわかりませんが、
TMR0がレジスタとして実装されていて、各レジスタの値が確認できるシミュレータが利用できる機種および環境であれば、シミュレータを利用するのが一つの確認方法でしょう。

MPLAB Xのシミュレータでちゃんと動作していることが確認できました。
さらにTMR0に12を加えたら誤差がなくなりました。
みけCATさんいつもありがとうございます。


Return to C言語何でも質問掲示板

オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[12人]