0マイコン開発の次のステップとして割り込みを使ってみます。今回はLEDが消灯・点灯・点滅がメインの動作でボタンが押されるとLCDの表示を変え、LEDの動作が変更されるプログラムです。今回もマイコンはATmega88です。プログラムコードが長くなるので前回使用したLCD関連の関数を別のファイルに分けました。こんなのを作ります(^o^)/回路図LCDは前回と同じように接続しPC0にLEDを、PB0にスイッチを取り付けます。このスイッチが押されると割り込みが発生するようにプログラムします。何とか想定した通りに動作させる事は出来ましたが、無駄や間違ったコードが含まれる場合がありますσ(^_^;)メインのソースファイルまずはコードをどうぞ。}}長ったらしいですね。"lcd.h"が今回分けたファイルです。12行目にbool変数を使ってtrueとfalseで判断していますが、普通の変数で1と0を入れても同じ事が出来ると思います。「volatile」と付ける事で意図的に最適化される事を避けています。45行目のcli();は割り込みを禁止するアセンブラ命令を実行するマクロです。割り込み許可のsei()を実行していないので必要ないかもしれません。46〜49行目でポートBを割り込みとして使えるようにしています。今回はピン・チェンジ・インタラプタを使って割り込みを発生させます。avr/interrupt.hをインクルードしておく必要があります。PCIE0);でPCIE0にビットをセットします。PCINT0);でPCINT0(PB0)にビットをセットします。これでピン状態が変更されると割り込みが発生します。前回と同じくLCDモジュールの初期化をlcd_init()で行います。今回の実験中、文字化けするなあと思っていたら初期化関数を忘れていました。55〜58行目でLCDに表示する最初の画面を作っています。1);でカーソルの位置を指定しています。1つ目の値で1行目、2つ目の値で1文字目と指定しています。)を実行しているのは割り込み関数から戻って来た時用です。65行目で変数patternをインクリメントします。-1;としているので0になります。66行目で変数flagをtrueとします。後のwhile文で使用します。今回はswitchi文を無限ループで繰り返します。break;}条件式の値と同じcaseの数値の所へジャンプします。する事で色々なパターンに対応出来ます。最初は変数patternの中は0なので68行目のcase0にジャンプします。1);でカーソルの位置を指定し、lcd_data(0x7E);で「→」を表示します。「0x7E」はLCDモジュールのデータシートに載っています。sei();で割り込みを許可します。ここまで割り込みを禁止していたかと言うと、LCD関数を実行中に割り込みが発生するとLCDとのデータのやり取りが中途半端な状態になり文字化け等を起こすからです。case0はOFF、case1はON、case2は点滅、case3は高速点滅となっています。割り込み発生PB0のスイッチが押されLになると割り込みが発生します。スイッチを押しっぱなしにしていた場合、離すとHになるのでこの場合も割り込みが発生します。false;sei();}ISR(PCINT0_vect)関数はPCINT0〜7(ATmega88の場合PB0〜7)の割り込み設定したピンの変化が発生した際に実行されます。今回はPB0のみ設定されています。_delay_ms(200);はスイッチのチャタリング対策で入れています。外部プルアップにしたりバイパスコンデンサ等を入れたりすればより良いチャタリング対策になるのだと思うのですが、今回は実験なのでシンプルに内部プルアップを使用してスイッチのみとしています。)」で割り込み禁止にしています。lcd_sel_clear();はLCDに表示されている「→」を消す為の関数です。)」で再び割り込みを許可します。これで割り込み関数は終わり割り込みが起きた所に戻ります。割り込み関数が終了するとcaseの中のwhile文の中に戻ってきます。変数flagはfalseになっているのでwhile文から抜け出し次の行のbreak;を実行します。breakを実行するとswitch文から抜け出します。無限ループの頭に戻り、割り込みを禁止し変数patternをインクリメントします。変数flagをtrueに戻します。今度の変数patternは「1」なのでcase1が実行されPC0がHになりLEDが点灯します。一度スイッチを押すと変数patternが「2」になりcase2を、更にもう一度押すとcase3を実行します。一度押すとどうなるでしょうか?変数patternは「4」になります。caseは0〜3までしかありません。その場合default:の部分が実行され変数patternに「-1」を代入します。breakでswitch文から抜け出し無限ループの頭に戻ります。すると再び変数patternが「0」になりcase0が実行されます。ヘッダーファイル今後の練習も兼ねてヘッダーファイルを作ってみました。する事で他のプロジェクトでLCDを使う事になってもコピペで済みます。main.cのファイルもスッキリします。_LCD_H_1行目と最後の行の#ifndef〜#endifはヘッダーファイルの重複インクルードを避ける為のものです。_LCD_H_は適当に付けた名前です。ヘッダーファイル名から取っています。_LCD_H_は_LCD_H_が定義されていない場合という意味なので、一度定義されればヘッダーファイルが再び呼び出されても1回目しかコンパイルされません。4〜20行目まではLCDに使用するポート指定等をしなかった場合、警告と共にデフォルトで定義するようにしました。22行目以降はプロトタイプ宣言です。LCDのソースファイルこちらのソースファイルの中にLCD関数の実体を記述します。lcd.hをインクルードし忘れないように記述します。画面クリア}中身は前回と同じなので説明は省きます。まとめ今回はチャタリングと割り込みのタイミングに苦労しました。ボタンを押しても1つずつ矢印が移動せずに1つ飛ばしに移動したり、ボタンを押す度に文字化けを起こしたりしていました。ファイルを作った場所が違っていて自作のヘッダーファイルが上手く機能しなかったりと遠回りしましたが何とかゴール出来ました。左上のFileからではなく右の所から右クリックしてファイルを作りましょう。この辺の情報が意外と見つからないので載せておきます。他のやり方があるのかもしれませんがまだ見付けていません^^;名前の変更も右の所から出来ます。最後に動画も載せておきます。コメントをキャンセルメールアドレスが公開されることはありません。