AVR/ペリフェラル/外部割り込み - プロえく http://bit.ly/11L2QXi
INT0を使ったものは便利なのですが、PB1しか使えず、今回既にLEDのための出力に使ってしまっているので、PCINTによる割り込みを使ってみることにしました。
回路図は以下のような感じです。
fig.1 schematic |
割り込みのためにプッシュスイッチを使ったのですが、チャタリングが発生してしまうため、防止のために
チャタリング防止回路のCR時定数 http://bit.ly/ZL38Nx
基板を作ってて、最初はやっぱり動きませんでした。バグの原因は多分、
1)スルーホールだから裏側に配線あたってれば大丈夫だろうと思ってた(スイッチがGND落ちてなかった)
2)入力を見るレジスタを間違えていた(PORTBではなくPINB)
3)見るポートを間違えてた(2ではなく4)
だと思われます…今後のために置いておきます…
コードはこんな感じです。
#include <avr/io.h> #include <avr/interrupt.h> //外部ピン変化の割り込み ISR(PCINT0_vect){ //自分でピンが立ってるかどうかチェックしなければいけない if(bit_is_set(PINB, PORTB4)){ PORTB ^= (1 << PORTB2); //PB2を反転 } } //ピンの変化による割り込みを許可する void initIOInterrupt(){ //割り込みを有効にする GIMSK |= (1 << PCIE); //割り込み許可するポートを選ぶ PCMSK = 0b00010000; //PB4 //全割り込みを許可 sei(); } void main(){ //PORTBの入出力の方向を設定(PB4が入力、PB2が出力) DDRB |= (0 << DDB4) | (1 << DDB2); //PORTBの出力値を設定 PORTB = 0b00010100; initIOInterrupt(); while(true) { //TODO:: Please write your application code } }
ISR(PCINT0_vect)が、割り込んだ時に呼ばれる関数です。設定はinitIOInterrut()で設定しています。といってもやることは少なく、
1)GIMSKレジスタのPCIEにフラグ(1)を立て、PCINT割り込みを許可すること
2)PCMSKレジスタで割り込みに使うピンのところにフラグを立てること
の2つだけです。
PCINTでは、割り込みが立ち上がりによるものなのか、立下りによるものなのかはユーザーが調べないといけません。なので、PINBを見ることで入力値を求めています。bit_is_set(A, B)は<avr/io.h>で読み込まれる?<avr/str_defs.h>でdefineされたマクロで、AのBビット目が1ならtrueになる…のかな。
また、PCINT割り込みはポート変化が出力でも割り込みは発生するらしい(有志の方による日本語翻訳版データシートならp.31)。なので、関係ないポートは出力値を変えてもいいように、PCMSKを0にしておきます。
INT0を使った割り込みは、次のBlogさんがとてもわかりやすい解説を書いてくださっているので、ぜひそちらを…
AVR入門(3) ピン入力と割り込み | stastaka's Blog http://bit.ly/11L86dz
さて、AVRをちょっとは便利な道具として扱えるようになって来ました。後はADCとシリアル通信、RESETピンのI/Oポートとしての使用、が課題です…