超☆ゆとり的電子工作 その2!
第二回だぜ!続きだぜ!
というわけで今回は、LED工作の定番!ナイトライダー!
あれよあれ、光が横に流れていくやつ
前回で作ったハードウェアがあるので、今回はプログラムのみ!手抜き!
というわけで続きでかいせつー!
//ATTINY2313Vtest
//2010927
//C言語によるATTYNY2313Vマイコン動作テスト
//試しながら学ぶAVRマイコンp43
//2010929
//p61割り込みプログラム追加のナイトライダー
#include <avr/interrupt.h>
#include <avr/io.h>
unsigned char x;
int q;
ISR ( TIMER0_COMPA_vect )
{
PORTB = q;
q=q+q;
if(q>=16)
{
q=1;
}
}
int main ( void )
{
q = 1;
x = 1;
DDRB = 0b00001111;
TCCR0A = 0b00000010;
TCCR0B = 0b00000101;
OCR0A = 64;
TIMSK = 0b00000001;
sei();
while(1)
{
}
}
終り
…
……
キング・クリムゾン!しすぎて内容が何も無い!
これでは寂しいのでちょっとだけかいせつー
今回の目玉はタイマ割り込み!
タイマを使用しないと、LEDを光らすにも、ただ光るだけ。になってしまい動きを出すことが出来ません
うそです出来ます でも面どくさいんです!タイマを使うんです!使うべきだ!
そしてまずはじめに知っておくことは、マイコンの現在のクロックである
現在と言っても、いじらなければ変わることはないし、まだなんもいじっていないので、設定はデフォルトのまま
今回使っているAVRマイコンの初期設定は、「クロック8MHzの8分周」ですってよ
8MHzは、PCのCPUのクロックと同じだから大体わかるよね。わからない人はググれ。と言いたいところだけど、超大雑把に説明すると、「一秒間に8メガ回行動することができるよ」ということです。マイコンはターン制RPGなのだ。ターンごとに行動するのだ。
ヘルツの次の問題「8分周」つまり一秒間に8メガ回行動するとか言ってもめんどくさいよねってことで、8回のうち1回だけ行動すればいいやってことです。
クロックは早けりゃいいってもんでもない。一秒間に8メガ回スクワットしろって言われたらそれは大変である。一秒間に1メガ回スクワットなら比べるとちょっと楽そうでしょ
マイコンさんも大変なのよ。電力消費とか、熱とか…
というわけで「クロック8MHzの8分周」とはつまり、「クロック1MHz」であり、1クロック動くのに1/1000000秒必要ということである。
これでやっとプログラムの解説へ
まず見るべきは、メインの中のタイマ割り込み設定部分である
DDRB = 0b00001111;
これはまぁどうでもいい 前回も見た、ポート出力設定である。
ここで設定されたポートはには、「LEDを光らせる許可を与えます!」ってことです。許可が降りないと何も出来ません。世知辛い世の中です。
TCCR0A = 0b00000010;
TCCR0B = 0b00000101;
ここからが問題だ。しかし全てはデータシートの48ページからを見ろ!で終わってしまう…
のは寂しいので少し解説
詳しく知りたい人はデータシートをみてください
TCCR0AとTCCR0Bは、タイマカウンタの設定をするレジスタ。レジスタとは箱のようなものとかよく言われるけど、めんどくさいので解説しない。
まずTCCR0Aのなかで、右から二桁目のところだけ1になっています。データシートを見ると、この、右から2番目ってやつはWGM01という名前が付いているらしい。
ほかにもWGM02ってやつとWGM00っていう仲間がいて、こいつら三人あわせては形成正種別ってやつを設定しているらしいよ。
今回の設定はWGM02、WGM01、WGM00がそれぞれ0,1,0になっているので、データシートによると「比較一致タイマ/カウンタ解除(CTC)動作」というせっていらしいよ。
次に、TCCR0Bの一桁目と三桁目がそれぞれ1になってます。
ここでは、「入力クロック選択」とか言うことをしているらしい
データシートによると「1024分周」と書いてある。分周。さっきも出てきた。
つまり8MHzを8分周して、それを1024分周しているのである。ヤヤコシイ。
円周率が3になるゆとり界では、1024が1000になってしまうことなど朝飯前なのでそれを踏まえて計算すると、8MHz÷8÷1000=1kHzなのだ!つまり1秒に1000回動作、つまりカウントアップするってことだね。わーいおうざっぱ。
もういい。次。
OCR0A = 64;
これは、カウンタがここで指定した値になったら動作するってことだ。ついでに、上で設定した「比較一致タイマ/カウンタ解除(CTC)動作」とやらによって、「カウンタがここと同じ値(今回は64)になったらカウンタを0に戻す」という仕事もしてくれるらしいよ。多分。(嘘かもしれない)
1/1000秒に一回カウントアップするものが64個集まったら動作する。つまり0.064秒に一回動作するってことだね!うーんめんどくさい。回りくどい。
TIMSK = 0b00000001;
sei();
最後の設定、TIMSKとseiだ!これはデータシートを見なくても覚えてる。割り込みを許可するレジスタだ。
いくら設定をしたところで、許可をしないとマイコンさんは働いてくれない。しかも今回はTIMSKとseiという二つの許可が必要。
TIMSK = 0b00000001;では、「タイマ割り込みの中の、タイマ/カウンタ0比較A割り込み許可」とよばれる許可を出しています。1のあるところをずらしたり、増やしたりすることで、ほかの割り込みを出来るようにもできます。
seiでは、割り込み全体の許可を出しています。すべての割り込みの上司。この人が許可を出さないと、ほかの誰がいくらいいよと言ったところで割り込みは実行できないのです。
ここまでで設定は終わり。
で、結局割り込みが出来るようになったはいいけど、割り込んで何をするのよ?
っていうのがここ
ISR ( TIMER0_COMPA_vect )
{
PORTB = q;
q=q+q;
if(q>=16)
{
q=1;
}
}
ISR ( TIMER0_COMPA_vect )
というのが、「タイマ0の比較A割り込みが発生したら、この中身を実行しますよ」ということを言っています。
そしてその中身…の説明は二進数とか入ってくるとめんどくさいな…
まぁ、コレによって、4個あるLEDのうちどこを光らせるかを決定して光らせているわけです。ここから先はC言語のお話になってしまう…
一回の割り込みでLED一つ分。一回の割り込みにかかる時間は0.064秒で、今回は4個のLEDを光らせているので、光が右から左に流れる一周に0.256秒かかっております。
一秒間に約4回光が流れる。目で追えないスピードでは無いですね。
逆に遅くしすぎたりするとかっこ悪いので、このくらいがいい感じでしょうなー
というわけで解説はいじょー!
…人に見せる文章ではないな…
ずっとこの、光が流れるやつのことをナイトライダーだと思ってたんだけど、本物は光が左右に往復するのね…
そうなるよう改造してみようかしら。
ここから先はAVRではなくC言語の領域だし…ちゃっちゃっと出来そう
それにしても5V電源回路とフルカラーLED回路を同じブレッドボード上で作ってしまったのでいちいち明るくて邪魔w余裕ができたらブレッドボード買い足してきて分けよう…