昨日書いた通り、WinAVR(AVR用GNU Cコンパイラ)やってます。
実はWinAVRには標準でUART関数がありません。多分。
ハードウェアUARTを持っているAVRであればI/Oレジスタ叩くだけでいいのでCでも簡単に実装できそうですが、私が主に使っているTiny系ではハードウェアUARTは無い物がほとんどです。
(AT90S2313やATTiny2313にはハードウェアUARTがありますが、izCORE2.0メインプロセッサとして必須要件として考えているADコンバータがありませんし、UARTも複数系統使いたいですし。)
仕方ないので汎用I/Oポートをソフトウェア制御してシリアル通信をしてやる必要があります。
これまでは主にアセンブラでやっていたので、Atmelが公開しているアプリケーションノート(AVR305: Half Duplex Compact Software UART)を参考にソフトウェアUARTを実装していましたが、高速になればなるほど(115.2kbpsとか)、通信パルス幅が10MHzの1クロック分程度の誤差で通信できなくなってしまいます。
アセンブラであれば、実行命令時間を正確に計算することが出来るので調整がきくのですが、Cだとコンパイラ任せなのでそうもいきません。
数命令程度ならまだしも、全部をインラインアセンブラでやるのはかなり大変そうだと思いましたが、調べてみるとWinAVRにはアセンブラ関数という機能があるようで、アセンブラソースを別に書いといて、それを関数として使用することが出来るようでした。
試してみると、マクロ命令系を除いて、これまで使用していたソースコードをほとんど変えることなく使用することができました。
これでフツーにCの関数としてUART通信を実行出来るようになりました。
確認したところではATTiny26 10MHz駆動時、クロック単位の微調整は要りますが、PCのUSBシリアル変換に対して230.4kbpsまではいけました。
460.8kbpsは駄目でしたが、PC側の規格速度に拘らず、10MHzのAVR同士でこのソフトUART同士なら600kbps~2Mbps位でもいけると思います。
このソフトUARTで出来るのは1バイト送受信ですが、こいつがCの関数と同様に扱えるので、C上で文字列送受信の関数もついでに実装してみました。
なるほど。これはかなり快適です。
アセンブラだとこういうのは苦手だから。
あとはMMCアクセス関連とADC関連を移植すれば要素部品は完了。
でも、やっぱりこうなるとこの構想ではメインプロセッサはATTiny26でしたが、RAM128バイト程度では明らかにメモリが足りなさそうです。
アセンブラだとなんとかやりくりできるかなって感じだったのですが、コンパイラ任せだとスタックや変数領域にどれだけ使うか分からないので、やはりATTiny861(RAM512バイト)かな。
前はどこにも売ってなかった(見つからなかった)けど、最近はこちらで入手可能なようだし。
Mega系を使わない理由は、単に物理的に大きいからです。
DIP品でないと手配線できないし。
ああ、DIPタイプ20ピン以下のMegaがあればいいのに...
(ラインナップ的にそれはTinyだろ!ってのはナシのことで。)
WinAVR(AVR-GCC)におけるアセンブラ関数の作り方は、以下ページを参考にしました。
AVR Wikiのavrgccでアセンブラを使う
ChaNさんのアセンブラ関数の書き方(avr-gcc)
感謝。
最近のコメント