スイッチによるLEDの点灯と消灯
これまでにスイッチを操作するとレジスタの値が変化することをモニタプログラム上で確認してきた. ここでは,スイッチの操作を監視して,スイッチの状態でLEDを点灯させたり消灯させたりするプログラムを作ることを目的とする. まず,ハードウェアとレジスタの関係から復習する.
図1:スイッチ周辺の回路
スイッチは,SW4からSW6までの3つのSWがMEMEsには搭載されている.スイッチの変化は,インバータを介してSH7085へ伝えられる. スイッチが離されているときは,Low レベルとなり,スイッチが押されているときはHighレベルとなる. 最低限この程度の情報は回路図から読み取れなければプログラムを作成することはできない. スイッチからの信号は,PD16,PD17,PD18 へ入力される.すなわち,ポートDのビット16からビット18は,入力端子として設定する必要があり,PDDRレジスタのビット16からビット18の値がスイッチの状態を示すこととなり,ビット16 が 0 の場合は,SW4は押されていない状態である.仮に,PDDRのビット18 が1 の場合は,SW6が押されていることを示すことになる. 下記のプログラムリスト1は,SW6を押すとLED6が点灯し,SW6を離すとLED6も消灯するプログラムリストである.
#include "iodefine.h" void main(void) { PFC.PEIORL.WORD |= 0x0800; PFC.PDIORH.WORD &= 0xfffB; PE.DR.WORD.L |= 0x0800; while (1) { if (PD.DR.WORD.H & 0x0004 == 0x0004) { PE.DR.WORD.L &= 0xf7ff; } else { PE.DR.WORD.L |= 0x0800; } } }
プログラムリスト1:SW6と連動して点滅するLED6
プログラムリスト1は,直感的に読みにくいと感じる人も多い.そこで,下記のように記述することで直感的にわかりやすくなる.
#include "iodefine.h" #define LED6 (PE.DR.BIT.B11) #define SW6 (PD.DR.BIT.B18) #define LED_ON (0) #define LED_OFF (1) #define SW_ON (1) #define SW_OFF (0) void main(void) { PFC.PEIORL.BIT.B11 = 1; PFC.PDIORH.BIT.B18 = 0; LED6 = LED_OFF; while(1) { if(SW6 == SW_ON) { LED6 = LED_ON; } else { LED6 = LED_OFF; } } }
実行すると,動画1のような動作を行う.右下のSW6に連動して,右上のLED6が点滅する.
動画1:SW6に連動してLED6が点滅
#include "iodefine.h" void main(void) { PFC.PEIORL.WORD |= 0x0800; PFC.PDIORH.WORD &= 0xfffB; PE.DR.BIT.B11 = 1; while (1) { if(PD.DR.BIT.B18) { while(PD.DR.BIT.B18); if (PE.DR.BIT.B11) { PE.DR.BIT.B11 = 0; } else { PE.DR.BIT.B11 = 1; } } } }
プログラムリスト2:SW6を押して離したときにLED6が点滅
上記のプログラムも可読性を高める上で,下記のように書くと読みやすくなる.
#include "iodefine.h" #define LED6 (PE.DR.BIT.B11) #define SW6 (PD.DR.BIT.B18) #define LED_ON (0) #define LED_OFF (1) void main(void) { PFC.PEIORL.BIT.B11 = 1; PFC.PDIORH.BIT.B18 = 0; LED6 = LED_OFF; while (1) { if(SW6) { while(SW6); if (LED6 == LED_ON) { LED6 = LED_OFF; } else { LED6 = LED_ON; } } } }
上記のプログラムを実行すると,動画2のような動作をする.右下のSW6を押して離したとき,右上のLED6が点灯していれば消灯し,消灯していれば点灯する.
動画2:SW6を押して離したときにLED6が点灯と消灯を行う
上記のプログラム1およびプログラム2を含んだワークスペースを下記よりダウンロードし,ビルドし,実行して動作を確認せよ.
演習問題
- 2進数 8桁で,01100010 のビット1 を 0 にするために必要な 2進数のビット列と論理演算名を答えよ.(但し,一番左が最上位ビット,一番右が最下位ビットである)
- 16進数 4桁で,0xFC87 のビット9 を 1 にするために必要な16進数の値を論理演算名を答えよ.
- プログラムリスト1を参考にして,動画3の動画のようにSW6に連動してLED6が点滅し,SW5に連動してLED5が点滅するプログラムを作成せよ.ただし,SW4を押してもLEDへの影響はないものとする.
- 上記のプログラムに次の機能を付け加えよ.「SW4に連動して,LED5とLED6が同時に点滅する機能」を付け加え,動画4の動作をするプログラムを作成せよ.
- プログラムリスト2を参考にして,SW6を押してから離したときにLED6の点灯を反転させ,SW5を押して離したときにLED5の点灯を反転させる動画5のような動作をするプログラムを作成せよ.
- 上記のプログラムに次の機能を付け加えよ.「SW4を押して離したときに,LED5およびLED6の点灯を同時に反転させる機能」これを付加し,動画6のような動作をするプログラムを作成せよ.
実践問題に挑戦
【問題】SW4 〜 SW6 を何回押したかをプログラムで記憶して,動画7のように指定された回数が押されたらLED が点灯または消灯するプログラムを作成せよ.下記の注1および注2を参考にすること.これは,スイッチによる誤動作を防ぐためにコマンドのように一定の規則を設けてスイッチを操作しない限り動作しない技術である.
注1)スイッチの順番は関係なく,押されたか回数のみを判定している
注2)スイッチを誤って押しすぎた場合は全て0回に戻るようになっている.
- LED5 を操作するためには,SW4を3回,SW5を2回,SW6を1回押してから離す.
- LED6を操作するためには,SW4を2回,SW5を2回,SW6を2回押してから離す.
- LED5とLED6を同時に操作するためには,SW4を1回,SW5を2回,SW6を3回押してから離す.
動画7:スイッチによるコマンド入力