ページ 1 / 1
tmr0について
Posted: 2017年8月07日(月) 09:32
by ぱおぱお
初心者です。はじめてタイマーを使ってみました。
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;
}
}
よろしくおねがいします。
Re: tmr0について
Posted: 2017年8月07日(月) 11:32
by みけCAT
ぱおぱお さんが書きました:質問①
どう記述すれば交互に点滅しますか?
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に、消灯
のようにすればできると思います。
Re: tmr0について
Posted: 2017年8月07日(月) 12:15
by maru
ぱおぱお さんが書きました:
質問①
どう記述すれば交互に点滅しますか?
片方のLEDを反転させればいいわけですから、以下のコードでも可能でしょう。
コード:
PORTAbits.RA1 ^= 0x01;
PORTAbits.RA0 = PORTAbits.RA1 ^ 0x01;
ぱおぱお さんが書きました:
質問②
オシロで測定すると1,060sで60msecほどずれがあります。
タイマーとはこういうものなのですか?
タイマそのものの精度はどうなんでしょう?
1,060sで60msecなら57ppmになります。温度補償のない水晶ならそのくらいはあり得ます。
まあ、みけCAT さんが書いている分周比のせいである可能性のほうがおおきいは思いますが。
Re: tmr0について
Posted: 2017年8月07日(月) 18:14
by みけCAT
みけCAT さんが書きました:ぴったりにするには、クロック周波数と分周比を工夫します。
例えば、
5.1200MHzの水晶の1024クロック(4(クロックに1回インクリメント)×256(回インクリメントされるごとに割り込み))ごとの割り込みは0.2ms間隔になるので、
この割り込み5000回ごとに1回処理をすると、(水晶の誤差や処理にかかる時間を無視すれば)ちょうど1sごとの処理になります。
Re: tmr0について
Posted: 2017年8月08日(火) 11:06
by ぱおぱお
ぱおぱお さんが書きました:質問②
オシロで測定すると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について
Posted: 2017年8月08日(火) 11:09
by ぱおぱお
maru さんが書きました:ぱおぱお さんが書きました:
質問①
どう記述すれば交互に点滅しますか?
片方のLEDを反転させればいいわけですから、以下のコードでも可能でしょう。
コード:
PORTAbits.RA1 ^= 0x01;
PORTAbits.RA0 = PORTAbits.RA1 ^ 0x01;
なるほど!
C言語はきっと下位2ビットをマスク掛けてビットシフトさせて・・・などと難しく考えていました。
ありがとうございます。
Re: tmr0について
Posted: 2017年8月08日(火) 11:20
by ぱおぱお
みけ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;
とすればいいのでしょうか?
Re: tmr0について
Posted: 2017年8月08日(火) 11:24
by みけCAT
ぱおぱお さんが書きました:TMR0に12を加えるとは直接
TMR0 = 0x0C;
とすればいいのでしょうか?
加えるとは加えるであり、TMR0 += 0x0C;のことです。
関数呼び出しや条件分岐などの処理の分クロックが進んでいるので、足したほうがいいと考えました。
もっとも、プリスケールが256なので、256命令は使わないので代入でもいいのかもしれませんが。
※試していないので完全に間違っているかもしれません
Re: tmr0について
Posted: 2017年8月08日(火) 14:12
by ぱおぱお
みけCAT さんが書きました:ぱおぱお さんが書きました:TMR0に12を加えるとは直接
TMR0 = 0x0C;
とすればいいのでしょうか?
加えるとは加えるであり、TMR0 += 0x0C;のことです。
関数呼び出しや条件分岐などの処理の分クロックが進んでいるので、足したほうがいいと考えました。
もっとも、プリスケールが256なので、256命令は使わないので代入でもいいのかもしれませんが。
※試していないので完全に間違っているかもしれません
なるほどです。
ちなみにTMRが動いてるかどうかの確認方法はありますか?
いろいろ触ってたら分周などを変えてもなんの変化もしなくなってしまいました。
Re: tmr0について
Posted: 2017年8月09日(水) 00:15
by みけCAT
ぱおぱお さんが書きました:ちなみにTMRが動いてるかどうかの確認方法はありますか?
扱っているマイコン(?)がわかりませんが、
TMR0がレジスタとして実装されていて、各レジスタの値が確認できるシミュレータが利用できる機種および環境であれば、シミュレータを利用するのが一つの確認方法でしょう。
Re: tmr0について
Posted: 2017年8月09日(水) 08:53
by ぱおぱお
みけCAT さんが書きました:ぱおぱお さんが書きました:ちなみにTMRが動いてるかどうかの確認方法はありますか?
扱っているマイコン(?)がわかりませんが、
TMR0がレジスタとして実装されていて、各レジスタの値が確認できるシミュレータが利用できる機種および環境であれば、シミュレータを利用するのが一つの確認方法でしょう。
MPLAB Xのシミュレータでちゃんと動作していることが確認できました。
さらにTMR0に12を加えたら誤差がなくなりました。
みけCATさんいつもありがとうございます。