AVRによるシリアル通信の基本(2)


昨日の記事の続き。


■ 知っておいたほうがいいこと その1


PCからFT232RLへのデータ送受信は、一定の間隔でしか行なわれない。


バイスマネージャでCOMポートを開き、FT232RLのドライバのところをクリックしてプロパティを出して、「Advanced」のタブに「Latency Time (msec) 」の設定がある。最小値は1msで、ここに1ms(ms = ミリ秒)を指定するとFT232RLのドライバは1msごとにFT232RLとやりとりをする。


つまり、それ以上の細かいタイミングではデータはやりとりされない。 1秒間にやりとりされる回数は理論上、最大1000回。(実測では800回ぐらい) 1回のやりとりでたまっているデータをある程度まとめてやりとりする。この時の転送速度はドライバ依存なので実際のところよくわからない。


FT232RLとAVR側は、シリアルポートをOpenした時に指定した転送速度で行なわれる。(デバイスマネージャのところの設定は無視される) 57600bpsを指定すれば、1秒間に最大で7200バイト。(実際はstart bitやstop bit、時にはparity bitもあるのでもう少し遅い) よって、57600bpsでやりとりするなら、1秒/7200 ≒ 138 us(us = マイクロ秒)に1回データがやってくるペースなので、割り込み処理をこの時間内に完了することを保証してやらなければならない。


例えば、省電力化のために1MHzで動作させているとしよう。このとき、1秒間に1M個の命令が実行出来る。1命令の実行にかかる時間は、1秒/1M = 1 us。AVRは大きな配列のアクセスには平気で30命令ぐらい食うことがあるので、大きな配列へのアクセスを2回やると 60 usぐらい消費するかも知れない。あと条件分岐やらなんやかやで30 usぐらいで、トータル 90 usぐらいになるかも知れない。


そう考えると 138 usという時間はそれほど余裕のある時間でもないことがわかる。


■ 知っておいたほうがいいこと その2


USART = Universal Synchronous Asynchronous Receiver Transmitter
の略で、SはSynchronous(同期)の意味。非同期通信に限定する時は、このSは省略され、UARTと呼ばれる。同期通信はAVRのデバイスによっては搭載されていない場合がある。


UARTの場合、1バイトずつ送るのでstart bit , stop bitを含めて10数bitなので、送信側と受信側のタイミングのずれが5%程度であれば、5%程度×10数bit < 1bit なので、送信エラーは起きない。


昨日のサンプルソースで、(動作周波数/16/ボーレート - 1) を UBRRレジスタに設定しているが、このソースはよく見られる書き方だが、丸めを考慮していないのであまり良くないと思う。


具体的に言うと、20MHzの動作周波数で115200bpsで通信する時のことを考えると「動作周波数/16/ボーレート」≒ 10.85069 になる。これの小数部を切り落とすと10であり、本来設定したい値との差は 0.85069。この時の誤差率は 0.85069 / 10.85069 ≒ 7.84% である。5%を超えてしまっている。(正常に通信できる範囲ではあると思うがケーブル長によってはエラーになると思う)


言うまでもなく、10.85069は丸め処理をして11とみなすべきである。ここで言う丸め処理とは四捨五入だが、浮動小数を持ち出すとその計算のために浮動小数の計算ルーチン一式が実行ファイルに含まれてしまうとたまらないので、整数のまま丸め処理を行なう。


x / y を四捨五入ありで結果を得るには、x / y に 0.5 を足したもの = (x + y/2) / y = (x + (y >> 1)) /y のようにすれば良い。


UBRR = (動作周波数/16 + (ボーレート >> 1))/ボーレート - 1


でいいと思う。10.85069は11に丸められて、(1-0.85069) / 10.85069 ≒ 1.376%。これなら安定して通信できるだろう。


■ ATtiny2313による通信速度


ATtiny2313だとどれくらいの通信速度が出せるだろうか。


この石は、秋月で100円で売られている20pinのAVRマイコンである。100円という安さ(18個以上なら、@90円)と、そのピン数が魅力である。


ATtiny2313では、GNDとVcc以外すべてをI/Oに用いることも出来る。ISP書き込みのためRESETは残しておいて、UARTのためにRxDも残しておくとしても16本もI/Oが使える。


秋月のFT232RLモジュール(950円)と組み合わせれば、あっと言う間にUSB-IOが完成だ。


しかし100円の石に水晶やセラロックを付けたくない。そこで内蔵RC発振回路で発振させ、通信速度のテストをしてみたところ、まず、38600bpsまではいけることを確認した。


57600bpsでの通信は不安定と書いてあるサイトがいくつかあって、私もそれを鵜呑みにしていたのだが、57600の時の UBRRの値は7.68になる。これを切り捨てて7だとみなしてしまうと0.68/8.68(8.68はUBRRには1引いた値を設定しているので1引く前の値) ≒ 7.84%の誤差率となる。これではRC発振ということもあって通信が不安定になりそうだ。


これをUBRRに設定するときにきちんと丸めてやれば、0.319 / 8.681 ≒ 3.68% の誤差で済むので、安定して通信が行える。


ちなみに、115200bpsでは 0.34 / 4.34 = 7.84%。これはさきほどの57600bpsの時の値と同じなので通信できなくはない。ただ、RCなので経年変化したときに通信できることを保証するのは難しいのでやめたほうがいいのでは?とは思う。無理にでもやるなら、データのbit長を5か7bitに減らしてstop bitを1bit , parityなしでやれば、多少は安定するとは思う。


(明日の記事に続く)