入力スイッチを使うプログラムをいろいろ試してみました。押しボタンスイッチを押すとLEDの点灯状態が変化するプログラムです。マイコン回路は「入力スイッチテスト用回路」を使用します。
まず最初に、出力端子を入力端子と同じ状態にするプログラムを作りました。入力スイッチはマイコンICのPB0〜GND間に接続されています。入力スイッチを押すと接点が閉じてPB0はGNDと同電位すなわち「0」になります。スイッチが押されていないときはPB0が「1」になっています。このプログラムは、入力(PB0)が「1」のときは出力(PA0)も「1」となってLED0が点灯、入力が「0」のときは出力も「0」になってLED0が消灯するものです。つまりスイッチが押されている間だけLEDが消灯することになります。動作の様子を図に書くと下のようになります。
プログラムは下記の通りです。BASCOM-AVRがインストールされたパソコンで下記リンクをクリックしてファイルをダウンロードすると、BASCOM-AVR IDEが自動的に立ち上がって画面内にプログラムが表示されます。
プログラムファイル input1a.bas
1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
2 | $crystal = 1000000 | クロック周波数を1MHzに設定。 | |
3 | Config Porta.0 = Output | PA0を出力に設定する。 | |
4 | Config Portb.0 = Input | PB0を入力に設定する。 | |
5 | Portb.0 = 1 | PB0をプルアップする。 | |
6 | Do | Doループの範囲ここから。 | |
7 | Porta.0 = Pinb.0 | PA0の出力をPB0と同じ状態にする。 | |
8 | Loop | Doループの範囲ここまで。6行目へ戻る | |
9 | End | 終わり。 |
3行目でPA0を出力端子に、4行目でPB0を入力端子に設定します。5行目「Portb.0 = 1」は、PB0を「1」にするという意味ですが、これによりPB0はIC内部でプルアップされます。つまりスイッチが押されていないとき(接点が開いているとき)は常に入力端子が「1」の状態に保たれます。スイッチが押されたとき(接点が閉じたとき)だけ「0」になります。
7行目「Porta.0 = Pinb.0」はPA0の状態をPB0と同じにするという命令です。右辺は「Portb.0」ではなく「Pinb.0」であることに注意してください。入力端子の状態を表わすときはこのように記述します。「Portb.0」と書いてコンパイルしてもエラーにはなりませんが、プログラムは正しく動作しません。「Pin」は「ピン」ではなく「Port input」の意味ではないかと思います。また「=」は数学の等号とは違うので、左辺と右辺を入れ替えることはできません。
7行目が「Do〜Loop」で挟まれているのは、こうしないとスイッチを押す間もなくあっという間にプログラムが終わってしまうからです。入力スイッチが押されればいつでも反応するようにするためには、メインプログラム全体を「Do〜Loop」で挟む必要があります。
入力端子をプログラム中でプルアップしない場合は、下図のように10kΩ程度のプルアップ抵抗を接続する必要があります。
上記のプログラムではPA0及びPB0を個別に入出力端子として設定しましたが、これまでのプログラムと同様、ポート全体を入力あるいは出力に設定したほうが書式が簡単になります。PB0のプルアップは「Portb = 1」と書けばOKです。
プログラムファイル input1b.bas
1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
2 | $crystal = 1000000 | クロック周波数を1MHzに設定。 | |
3 | Config Porta = Output | ポートAを出力に設定する。 | |
4 | Config Portb = Input | ポートBを入力に設定する。 | |
5 | Portb = 1 | PB0をプルアップする。 | |
6 | Do | Doループの範囲ここから。 | |
7 | Porta.0 = Pinb.0 | PA0の出力をPB0と同じ状態にする。 | |
8 | Loop | Doループの範囲ここまで。6行目へ戻る | |
9 | End | 終わり。 |
上記と逆の動作、つまり入力スイッチを押している間だけLEDを点灯させるにはどうしたらよいでしょうか。下記のような動作です。
ひとつには入力回路を下の回路図のように変更する方法が考えられます。下図左はプッシュオフ型の押しボタンスイッチを使うものです。ボタンを押すと接点が離れて入力端子が「1」になるので、出力も「1」になってLEDが点灯します。右は入力端子とGND間に抵抗をつないでプルダウンする方法です。これもスイッチを押すと入力端子が「1」になるのでLEDが点灯します。この場合はプログラム5行目の「Portb = 1」は削除します。
マイコン回路を変更することなく、スイッチを押している間だけLEDが点灯するようなプログラムができないか考えてみました。たぶん何通りもあるのでしょうが、下記のように条件分岐「If」を用いて入力端子の状態を判断する形にしたらうまくいきました。
プログラムファイル input1c.bas
1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
2 | $crystal = 1000000 | クロック周波数を1MHzに設定。 | |
3 | Config Porta = Output | ポートAを出力に設定する。 | |
4 | Config Portb = Input | ポートBを入力に設定する。 | |
5 | Portb = 1 | PB0をプルアップする。 | |
6 | Do | Doループの範囲ここから。 | |
7 | If Pinb.0 = 0 Then | 条件分岐のプログラムここから。 | |
もし「Pinb.0 = 0」ならば次行のプログラムを実行。 | |||
8 | Porta = 1 | ポートAを「1」にする。LED0が点灯。 | |
9 | Else | そうでなければ(「Pinb.0 = 1」ならば)、 | |
次行のプログラムを実行。 | |||
10 | Porta = 0 | ポートAを「0」にする。LED0が消灯。 | |
11 | End If | 条件分岐のプログラムここまで。 | |
12 | Loop | Doループの範囲ここまで。6行目へ戻る | |
13 | End | 終わり。 |
7行目「If Pinb.0 = 0 Then」で入力端子の状態を判断します。ここも「Pinb.0」と書かなければなりません。「Portb.0」ではだめです。「Pinb.0 = 0」(スイッチが押されている)ならば、8行目の「Porta = 1」が実行され、LEDは点灯します。もし「Pinb.0 = 1」(スイッチが押されていない)ならば、10行目の「Porta = 0」が実行されてLEDは消灯します。
このプログラムはいろいろ応用できます。たとえば8行目を「Porta = 0」、10行目を「Porta = 1」に変えれば、最初のプログラムと同じ、スイッチを押している間だけLEDが消灯する動作になります。また、8行目を「Porta = 255」と書けば、スイッチを押したとき8個のLEDすべてが点灯します。なお、「Else」命令(9行目と10行目)を書かないと、いったんLEDが点灯したら点灯しっぱなしになってしまいます。
入力スイッチを使ったプログラムもプログラムシミュレーターでシミュレーションすることができます。「Hardware Simulation」の画面で「PA」「PB」と書かれた赤いLEDが出力の状態、「IA」「IB」と書かれた緑のLEDが入力を表わしています。それぞれ消灯していれば「0」、点灯していれば「1」です。最初のプログラム「input1a.bas」を例に取ると、スイッチを押したときの状態は下記のようになります。PB0はプルアップされている(Portb.0 = 1)のでここだけ点灯しています。
押しボタンスイッチの動きと逆になる感じですが、スイッチを放したときの状態を見るには「IB0」の緑のLEDをクリックします。するとこれが点灯し(Pinb.0 = 1)、同時にPA0の赤いLEDも点灯します(Porta.0 = 1になる)。このときのようすを下に示します。