はじめに

UARTで通信する際,クロックの周波数が安定していることが大前提です.これまで水晶発振子を用いているとき,周波数のずれで動作がおかしくなったことは一度もなかったのですが,今回そのような事態に陥ったので備忘録代わりに書き残しておきます.

環境

  • MCU: PIC18F16Q41
  • IDE: MPLAB X 6.00
  • 発振子: ECS-36-20-4DN (3.6864 MHz)

経緯

最近のPICにはOSCTUNEレジスタがあり,これによって周波数の微調整が行えることは知っていました.しかしこれを使うのは,水晶発振子とかではなくてRC発振器とかのように誤差が大きいもので使うという理解でした.しかし今回,UARTにて115200bpsの通信をしようとしたところ,動きがおかしいことに気が付きました.最初,MCUと発振子の距離がちょっと会ったり,発振子の下の面にベタのGNDとVCCがあったりしたので下の図のように配線を見直してみました.

 01

 

しかし,これでも正しくUARTの通信ができません.仕方なくオシロスコープで信号を計測してみました.まずはOSCTUNEを最大値の0x1f(=+15),つまり最速にしてみました.そして,115200bpsにて8ビットの信号を送信してみたところです.下の図はオシロスコープで撮影された信号です.左端にある立下りがスタートビットの開始,右側にある立ち上がりがストップビットの開始を表します.その間の時間は63.20usのようです.この間にスタートビットを含めて9ビット分の時間があるはずです.従いまして,先ほどの時間を9で割った時間が1ビットを送った時間となります.その結果,7.02usとなります.一方,115200bpsにおける適切な1ビット送信するときの時間は1000000/115200=8.68usのはずです.その差は+1.66usとなり,かなりの誤差があります.

F0001TEK

 

次にOSCTUNEを最小値の0x20(=-16),つまり最遅にしてみます.その時のオシロスコープの画像を示します.スタートビット開始からストップビット開始までの時間は79.20us,したがって1ビット送信するのに8.8usということになります.最適な時間と比べ,-0.12usとなります.先ほどOSCTUNEを最速とした時と比べると明らかに誤差が少ないことが分かります.OSCTUNEはデフォルトでは0ですので,そのままではかなりの誤差があるということが分かります.

 F0000TEK

適切なOSCTUNEを求めるようなアプリを作成してみました.今頃な感じですがJavaFXで作ってみました.周波数115200と,OSCTUNEを最大にした時に得られるスタートビット開始からストップビット開始の時間を63.20,OSCTUNEを最小にしたときの値を79.20を入力すると,適切なOSCTUNEを求めてくれます.今後はこれを使って周波数の調整をしていきます.

02