AVRの最小Hello Word制限は2バイトです

今週、ハブには2つの記事が、ブログには1つの記事が同時に掲載されました。著者は、AVRマイクロコントローラー用の最小のLED点滅プログラムの作成で競いました。

最新の記事で、著者は長さわずか4バイト(!)のプログラムを提案しました。

さて、どのように挑戦に抵抗できますか?!

そして、この記事では、目に見える周波数で、サイズが2バイトしかないLEDを点滅させるプログラムを提案します。



AVRマイクロコントローラーのアドレス可能なプログラムメモリセルのサイズは16ビットまたは2バイトであるため、2バイトは可能な限り最小のプログラム長です。 したがって、プログラム、または1つの命令(絶対に任意のアドレスに配置できます)は、プログラムメモリの1つのセルを占有します。



しかし、残念ながら、私が提案したプログラムはすべてのAVRマイクロコントローラーでは機能せず、TinyおよびMegaファミリーの一部のモデルでのみ機能します。



プログラムの秘密は、TinyおよびMegaファミリの一部のマイクロコントローラには、1つのコマンドでレジスタPORTA、PORTB、およびPORTDのビットのステータスを反転できる優れた機能があることです。 sbi A、bチームは、このような興味深い機能を実装しています。



sbi A、bコマンドは、0〜31のアドレスを持つI / Oレジスタのビットを設定するために使用されます。

このバイナリコマンドは次のようになります。



1001 1010 AAAA Abbb



最初の8ビット1001 1010はオペレーションコードです。これはコマンドの定数コンポーネントです。

ビットAAAAAには、I / Oアドレス空間内のI / Oレジスタのアドレスが記録されます。 5ビットがアドレスに割り当てられているため、コマンドでアドレスに制限があります(0..31)。

bbbの下位3ビットには、変更されたビットの番号(0..7)があります。



レジスタPORTBおよびPORTDのビットのステータスを反転できる非常に注目すべき機能に戻ります。



ATtiny2313マイクロコントローラのデータシートを見てみましょう:



画像






この機能は、 ATtiny2313、ATtiny13、ATtiny24 / 44/84マイクロコントローラーに確実に存在します。

メガマイクロコントローラでは、このような便利な機能はATmega48A / PA / 88A / PA / 168A / PA / 328 / Pにあります。 しかし、ATmega8A / 16A / 32Aでは、この機能はありません。

そして、他のマイクロコントローラーについて自信を持って言うことはできません。

そのような機能がマイクロコントローラに存在するかどうかを調べるために、 Toggling the Pinというフレーズをデータセットで検索できます。



したがって、たとえば、コマンドsbi PINB、0を書き込むことにより、PORTBレジスタのゼロビットの状態を反転させることができます。



そして、それは私たちに何を与えますか?



これにより、ポートBのゼロ放電でプルアップ抵抗をオン/オフできます(リセット後、すべてのI / Oレジスタがリセットされるため、ポートBおよびDは入力用に構成されていることを忘れないでください)。 内蔵抵抗器の抵抗は30..50 kOhmです。 ただし、このような抵抗でも、低消費の青、赤、白のLEDを点灯するには十分です。 しかし、緑色のLEDにはすでに電流が流れていません。

個人的に、私はこの方法をLEDに頻繁に使用しています。 サイズ0805と0603の赤と青のLEDは、5 Vの供給電圧でかなり許容範囲内で点灯します。



つまり、LEDを点灯するには、ポートピンと共通ワイヤの間でLEDをオンにする必要があり(外部電流制限抵抗なし!)、内部プルアップ抵抗をオンにします。 このようなスイッチング回路では、外部の電流制限抵抗も節約されます。



画像








そこで、1つのコマンドでLEDを制御する方法を学びました。

このコマンドがマイクロコントローラーのプログラムメモリ(0x0000など)に書き込まれると、マイクロコントローラーは次のように動作します。

ゼロアドレスでsbi PINBコマンドが満たされ、0になり、実行後にPORTBゼロビット単位に設定され、プルアップ抵抗がオンになり、LEDが点灯します。 そして、プログラムメモリの最後まで、マイクロコントローラは0xFFFFのみを満たします。 このような命令はマイクロコントローラーに認識されないため、マイクロコントローラーは単にそれらをスキップし、1クロックサイクルごとに費やし、プログラムカウンターを1つ増やします。

プログラムカウンタがメモリの最後までカウントすると、オーバーフローしてゼロにリセットされます。つまり、アドレス0x0000に移動し、sbi PINB、0コマンドが再度実行されます。 コマンドが実行されると、PORTBのゼロビットがゼロにリセットされ、プルアップ抵抗がオフになり、LEDがオフになります。



次に、LEDが点滅する速度を計算してみましょう。 マイクロコントローラとして、たとえばATtiny2313を選択します。 このマイクロコントローラでは、プログラムメモリは2048バイトです。 プログラムメモリの各セルは2バイトを占有します。 プログラムメモリのアドレス空間は、0〜1023のアドレスで表されます。つまり、合計1024個のアドレスです。 電源投入後、マイクロコントローラーはアドレス0x0000からプログラムを開始します。 マイクロコントローラがアドレス1023に達すると、次の手段でソフトウェアカウンタがリセットされます。 つまり、アドレス0x0000への移行があります。



プログラムのすべてのコマンドは1クロックサイクルで実行されます。 したがって、1024サイクルに1回、LEDが反対の状態に切り替わります。 マイクロコントローラが1 MHzの周波数で動作するとします。 この周波数では、1クロックサイクルは1μsです。 したがって、LEDスイッチングは1024μsごとに発生します。 ご存じのとおり、頻度は期間の逆数です。 そして、1回の点滅の周期は、LEDを切り替える間隔の1024μs* 2 = 2048μsです。 LED 1 /(2048μs)= 488 Hzの点滅周波数はどこで取得できますか。



あまりにも多くが起こった。 人間の目は、このような点滅頻度では気づきません。 点滅周波数を目に見えるようにするには、周波数を下げる必要があります。 これを行うには、周波数が約128 kHzのクロックジェネレーターウォッチドッグタイマーからマイクロコントローラーを接続します。 しかし実際には、タイマーは正確なタイミング用に設計されていないため、周波数は3..4 kHz異なる場合があります。



128 kHzは1 MHzの8分の1です。 したがって、点滅周波数は488 Hz / 8 = 61 Hzの8倍低くなります。 同じことがたくさんあります。 目の点滅は目立ちません。



周波数をさらに下げるには、周波数を8で割るヒューズビットCKDIV8を有効にする必要があります。クロック周波数は128 kHz / 8 = 16 kHzになり、点滅周波数はさらに8倍に減少し、61 Hz / 8 = 7.6 Hzになります。 しかし、そのような頻度は、目ですでにかなり顕著です。



しかし、そのような値に周波数を下げるときは非常に注意してください!



重要なルールを覚えておいてください:シリアルインサーキットプログラマーでマイクロコントローラーをプログラムする場合(SPIを介してプログラミングする場合)、マイクロコントローラーのクロック周波数はプログラミング周波数の少なくとも4倍でなければなりません。

つまり、128 kHzのマイクロコントローラーのクロック周波数では、プログラマーの周波数(SPI周波数)を低くする必要があります。



128 kHz / 4 = 32 kHz。



また、16 kHzのクロック周波数では、プログラミング周波数を低くする必要があります



16 kHz / 4 = 4 kHz。



クロック周波数を16 kHzに下げる前に、シリアルプログラマが4 kHz未満の周波数でプログラミングできることを確認してください。

そうしないと、マイクロコントローラを「ブロック」する危険があります!

この制限は、並列プログラマには適用されません。



最後にプログラムを作成しましょう。

プログラムをノートブックに書き、すぐにマシンコードで書きます。



sbi A、bがどのように見えるかはすでにわかっています



1001 1010 AAAA Abbb



必要なビットを置き換えるために残っています。



ポートBのゼロ放電に接続されているLEDに点火します。マイクロコントローラーATtiny2313では、アドレスはPINB = 0x16です。 バイナリでは、0x16 = 0b10110。

ゼロビットを変更するため、bbb = 000です。



ビットを置き換えて取得: 1001 1010 1011 0000または0x9AB0



次に、マイクロコントローラーファームウェア用のHEXファイルを作成します。



HEXファイルの構成は次のとおりです。



画像








HEXファイルは2行で構成されます。最初の行には2バイトの命令0x9AB0が含まれ、2行目にはHEXファイルの終わりが示されます。

チームの住所として、ゼロの住所を選択します。 ただし、アドレス空間全体から絶対に任意のアドレスを選択できます。

チェックサムは、ゼロから文字列のすべてのバイトを引くことで計算されます。 結果の値の下位バイトは正確にチェックサムです。

つまり、この場合、0x00-0x02-0xB0-0x9Aです。 下位バイトは0xB4です。 行の最後に入力します。



最後の行は、HEXファイルの終わりを示し、次のようになります。



:00000001FF



また、HEXファイルではコマンドバイトが逆になっていることを覚えておく必要があります。 つまり、最初に下位バイト0xB0を書き込み、次に上位バイト0x9Aを書き込みます。



結果のHEXファイルは次のようになります。



:02000000B09AB4

:00000001FF



結果の行をノートブックに書き込み、拡張子.hexで保存します(ただし、任意の拡張子で保存できます)。



このファームウェアをマイクロコントローラーに縫い付け、ウォッチドッグタイマージェネレーターからクロックを設定し、8での除算を有効にします。



Atmel Studio 6でヒューズビットを設定する例を次に示します



画像








結果は点滅するLEDの形で得られます。 鉄でチェックインされています。 正しく点滅します。



したがって、最も単純なプログラムは2バイトで構成され、最も単純な回路はバッテリー、マイクロコントローラー、およびLEDで構成されます。



点滅するLEDプログラムをさらに短く書く人はいますか?



All Articles