ATTiny10とATTiny13の違い
- 2022/12/09 10:27
- カテゴリー:make:
電子工作を共に楽しむある友人と久々に話をしたのですが,彼はすでにKiCadを使ってパターンを作り,中国の基板メーカーに発注するという,まさに電子工作の王道を驀進していました。
翻って私はというと,未だに万能基板とポリウレタン線でコツコツと作っています。この半年は特に規模の大きな回路の配線をやったのですが,私はこの作業が楽しく(おそらく写経というのはこういうものだろう),苦にならないので基板メーカーに作ってもらうようなことはあまり考えていませんでした。
しかし,彼の作品を見ていると刺激を受けます。私もCADを使って基板を発注してみようと思いました。
手配線では,小型の部品の配線にどうしても限界があります。0.4mmピッチのQFPでさえも手ハンダでは無理でしょう。QFNなんかは最初からやろうとも思いません。
アマチュアの電子部品がプロのおこぼれであるという状況が変わらない限り,基板無しで工作が可能な時間はそんなに長くはないでしょう。すでに多くのアマチュアが高度な基板を作っていることを考えると,私もやっておかないとまずいと思います。
しかし,私の工作はまさに自分のためだけに行っているものです。それも目的があって,そのために工作がベストと判断されたときに行うもので,工作そのものが目的ではありません。
目的がないのに基板を作る今回の話に私は頭を抱えました。なにか目的をでっち上げないといけないのですが,ふと思いついたのは随分前に夢中になったSi5351Aとtiny13の組み合わせで任意の周波数を作る回路です。これをモジュールにしてしまうような基板なら面白そうです。フットプリントは14ピンのDIPでいきましょう。
好きな周波数が選べないTCXOの精度で,欲しい周波数が手に入るという長年の夢が,Si5351で実現することに興奮して検討していたのが6年前,I2Cで100ほどのパラメータを設定するのは手作業では無理でどうしてもマイコンが必要ですが,一度設定すれば変更しないものでもあり,高価で規模の大きなマイコンは使いたくありません。
I2Cが搭載されるようなマイコンはそれなりの価格ですので,私は当時50円だったATTony13にソフトウェアでI2Cを実装して,Si5351Aの設定をさせようとしました。
ところがAVRはハーバードアーキテクチャで,100ほどのパラメータを定数として配列に取ると,RAMにも確保されてしまいATTiny13のRAMではあふれてしまいます。結果正しい設定値が書き込まれず動作しなかったのです。
そこで定数を配列に取るとき,プログラム用のフラッシュもしくは内蔵EEPROMから値を参照する仕組みがライブラリに用意されていて,これを使って完成したのでした。
今回の基板作成で小型のモジュールを作るとなれば,ATtiny13では大きすぎます。なら米粒AVRことATTiny10を使いましょう。
ATtiny10は秋月で45円時代に10個ほど買ってありましたが,書き込みがTPIであることもあり,買ってすぐには手を出しませんでした。PICKIT4を手に入れてからもGPIOの少なさから使うきっかけがなく,放置していました。
しかしI2Cならたった2本。まさに米粒AVRに相応しい仕事です。
早速MicrochipStudioを立ち上げ,ATTiny13のコードをコピペしてビルドします。ATTiny13にはEEPROMがありますが,ATTiny10にはありません。そこでプログラム用のフラッシュに設定値を持たせる事にしました。
エラーがボロボロ出たので修正してビルドが通るようにしてから書き込んで実行しますが,やっぱり上手くいかず,Si5351はなにも出力していません。
SI5351が壊れているかもとATTiny13で試すと綺麗に周波数が出てくれたので原因はATTiny10にあることがはっきりしました。I2Cのコードが問題なのかもと,I2CのLCDを繋いで見たところ,これは一発で正しい表示が行われました。
本来の目的とはズレていますが,米粒AVRでLCDが動いているのはちょっと感激です。
SI5351は正常,ソフトI2Cも問題ないという事なら,あとはもう設定値が正しく用意されていないということになりそうです。
怪しいのは,やはり設定値を書き込んである定数の配列です。配列の宣言でPROGMEMを宣言し,参照はpgm_read_byteという関数で行っていますが,ここがどうも怪しいです。
google先生に尋ねてみると,まずATtiny10はこれまでのAVRとは少々毛色が異なるものであることがわかってきました。まず大きいのはハーバードアーキテクチャではなくなったこと。コードとデータが別のメモリに置かれるというのはAVRの特徴だったのですが,小さい事を目指したATTiny10では採用されなかったみたいです。
AVRの個性としてもう1つあったヒューズですが,これも少し格落ちしていました。これまでのAVRではクロックの設定がヒューズで行えたのですが,ATTiny10ではレジスタを叩くことになっています。しかもそのレジスタは保護対象になっていて,ロックを外すレジスタを先に叩いて,4クロック以内に設定を終えないといけないという面倒臭さです。
ヒューズはリセット解除後すぐに設定が反映されることがメリットだったのですが,ATtiny10が持つヒューズはクロック出力のON/OFFとWDTの設定,そしてリセット端子をGPIOにする設定の3つになっていました。
また,GPIOのプルアップは専用のレジスタが用意されました。これまでのAVRでは入出力方向の設定レジスタがプルアップも兼用していたのですが,専用レジスタを使わないとプルアップされません。
そうそう,レジスタが16本に減りました。これもAVRらしさが減ったと感じさせますね。(それでも16本もあるわけですが)
話を戻すと,ハーバードアーキテクチャをやめたことで,PROGMEM宣言の扱いが変わってしまうというのは事実のようでした。しかしその結果,コンパイラが未対応なのでPROGMEMは使用出来ないとか,逆にこれまで通りpgm_read_byteで参照できるとか,そうした記述のコードが実際に動いたとか,国内外でいろいろなコメントが見つかりました。
半ばあきらめ書けていたときに見つけたあるコメントに興味を惹かれたのですが,これはPROGMEMでフラッシュに配列で定数を置いた場合,参照はpgm_read_byteではなく,普通にその配列を参照するだけでOKだというものでした。
なるほど,ハーバードアーキテクチャのAVRなら,データを置けないエリアであるプログラム用フラッシュにデータを置いてその値をポインタで参照することは出来ず,一度1バイト分だけRAMにコピーしてこれを参照するような関数を用意する必要がありますが,ハーバードアーキテクチャをやめたATTiny10なら,ポインタでフラッシュメモリも参照できそうです。
試しにpgm_byte_readをただの配列の参照にしたところ,あっけなく動いてしまいました。念のためATTiny13でも試しましたが,こちらは動作しなくなりました。やはりアーキテクチャの違いが原因だったようです。
まとめます。
まずお約束のprgspace.hをインクルードします。
#include <avr/pgmspace.h>
定数の定義はこれまで通りです。
const PROGMEM unsigned char hoge[14] = {
86, 85, 84, 83, 82, 80, 81, 1, 0, 6, 5, 4, 3, 2};
しかし,参照するときはこれまでとは違います。これまでは,
data = pgm_read_byte(&hoge[i]);
としてアドレスを専用の関数に渡していましたが,ATTiny10では,
data = hoge[i];
でOKです。なんとシンプルな。
海外では,AVRのこうした変更を好ましいと考える人もいるようで,うちの嫁さんも「これが自然。元のAVRがおかしい」とまで言い切っていました。AVRが好きな私としては,ちょっと残念ですが。
ATTiny10はRAMが32バイトと強烈に少ないですし,レジスタも半減しているので,設定値を1KBのフラッシュメモリから直接参照できるかどうかは,まさに死活問題です。今回,ATTiny10でこの問題を解決出来たことは,ATTiny10の応用範囲を拡大出来ると思います。