ちょっと大きい発見だったので書いときます。
と言ってもデータシートに明記されてたんですけど。
PICのメインクロックに4MHzの水晶発振子を使って動かしています。
この状況で、TMR1を使ってぴったり10msごとに割り込みを掛けたい。です。
とりあえずプリスケーラなし(1:1)と仮定すると、fosc/4=1MHzなのでTMR1のカウントアップ周期は 1/1MHz=1μs になります。
TMR1は16ビットカウンタなのでオーバーフローするには65,536μs(65.536ms)掛かります。
10msでオーバーフローさせるには、TMR1の初期値を55,536にすればちょうど10000カウント(=10,000μs=10ms)でオーバーフローするのでばっちりです。
で す が 、
TMR1割り込みが掛かってアドレス4番に飛んできてレジスタの待避をして…とかやってるうちにTMR1が進んでしまうので、その分TMR1の初期値を増やさないといけません。
ここで、それがめんどくさいのでプリスケーラを使って初期値を設定するまでの間TMR1が進まないようにしとこう、というのが私の今までの考え方でした。
(TMR1はプリスケーラが1:8までしかないのでちょっと進んじゃうんですけどね)
しかし今回あらためてシミュレータで試してみたところ、どうしてもぴったり10msになりません。
(シミュレータにストップウォッチ機能が付いてるので数字で確認できるんです)
で、まあ思い当たるところを調べたらずばり正解で、
TMR1H/TMR1Lに書き込みを行うとプリスケーラがクリアされる
というのが真相でした!
データシートにも明記されていました…。
要するにTMR1が進んじゃってめんどいからプリスケーラで押さえとく、というのがまったく意味を成していませんでした。
それどころかプリスケーラには書き込みが行えないので一度ずれたら修正不能。なんということだ…。
仕方ないのでプリスケーラなしにして、割り込み前処理のオーバーヘッドも含めたTMR1初期値を設定する、という方法しかないようです。
まあ、シミュレータのストップウォッチ機能があるからPC上で数字書き換えてシミュレーション、を何度か繰り返せば良いだけですから楽なもんです。
ぴったり10msになりました…。
って、今思ったんだけどTMR1に初期値を設定するんじゃなくて割り込みハンドラでTMR1H/Lから10000を減算すれば良いんじゃないかな。
誰か試してみてくださいw
21:24追記
他の割り込みハンドラ、たとえばTMR0とかの処理中にTMR1がオーバーフローした場合を考えると、やはりTMR1H/Lから経過時間分を減算するのが良い気がしてきました…。
と言ってもデータシートに明記されてたんですけど。
PICのメインクロックに4MHzの水晶発振子を使って動かしています。
この状況で、TMR1を使ってぴったり10msごとに割り込みを掛けたい。です。
とりあえずプリスケーラなし(1:1)と仮定すると、fosc/4=1MHzなのでTMR1のカウントアップ周期は 1/1MHz=1μs になります。
TMR1は16ビットカウンタなのでオーバーフローするには65,536μs(65.536ms)掛かります。
10msでオーバーフローさせるには、TMR1の初期値を55,536にすればちょうど10000カウント(=10,000μs=10ms)でオーバーフローするのでばっちりです。
で す が 、
TMR1割り込みが掛かってアドレス4番に飛んできてレジスタの待避をして…とかやってるうちにTMR1が進んでしまうので、その分TMR1の初期値を増やさないといけません。
ここで、それがめんどくさいのでプリスケーラを使って初期値を設定するまでの間TMR1が進まないようにしとこう、というのが私の今までの考え方でした。
(TMR1はプリスケーラが1:8までしかないのでちょっと進んじゃうんですけどね)
しかし今回あらためてシミュレータで試してみたところ、どうしてもぴったり10msになりません。
(シミュレータにストップウォッチ機能が付いてるので数字で確認できるんです)
で、まあ思い当たるところを調べたらずばり正解で、
TMR1H/TMR1Lに書き込みを行うとプリスケーラがクリアされる
というのが真相でした!
データシートにも明記されていました…。
要するにTMR1が進んじゃってめんどいからプリスケーラで押さえとく、というのがまったく意味を成していませんでした。
それどころかプリスケーラには書き込みが行えないので一度ずれたら修正不能。なんということだ…。
仕方ないのでプリスケーラなしにして、割り込み前処理のオーバーヘッドも含めたTMR1初期値を設定する、という方法しかないようです。
まあ、シミュレータのストップウォッチ機能があるからPC上で数字書き換えてシミュレーション、を何度か繰り返せば良いだけですから楽なもんです。
ぴったり10msになりました…。
って、今思ったんだけどTMR1に初期値を設定するんじゃなくて割り込みハンドラでTMR1H/Lから10000を減算すれば良いんじゃないかな。
誰か試してみてくださいw
21:24追記
他の割り込みハンドラ、たとえばTMR0とかの処理中にTMR1がオーバーフローした場合を考えると、やはりTMR1H/Lから経過時間分を減算するのが良い気がしてきました…。