このページは、わたしの備忘録として作成しました。
(1) スイッチを使ってみる
前回では、PICを使ってLEDを点滅させることができましたので、今回は、PICへのユーザーインターフェースのひとつ、入力装置としてスイッチを使ってみたいとおもいます。
スイッチといっても、スライドスイッチ、トグルスイッチ、プッシュボタンスイッチ、タクトスイッチ、キースイッチ、ロータリスイッチ、DIPスイッチなど、用途にあわせておおくの種類があります。今回は、6ミリ角のタクトスイッチを使います。タクトスイッチは、リードがあらかじめ曲げられている、リードフォーム加工済みのものがおおいので、リードをペンチでまっすぐにしてブレッドボードの穴にはいるようにします。
スイッチの実験ボード
![]() |
GP3は、10kオームの抵抗で+5Vにプルアップされ、タクトスイッチでGNDに接続されています。GP3は、タクトスイッチのボタンを押さない状態では+5V、ボタンを押すと0Vになります。このボタンを押している間だけ、GP0に接続されたLEDを点灯させてみようとおもいます。今回は、GPIOレジスタの現在の内容をBTFSC(Bit Test File, Skip if Clear)命令をつかってチェックします。GP3は+5Vにプルアップされていますので、GPIOレジスタのビット3はタクトスイッチのボタンを押さなければHigh、すなわち 1 と読まれ、アドレスがBTFSCから1つ進みます。ボタンを押せば、GP3の電位は0Vになりますので、Low、すなわち 0 と読まれ、BTFSCのつぎのアドレスを1つ飛ばして(スキップして)進みます。
下記は、タクトスイッチのボタンを押している間だけLEDが点灯するプログラムです。
1 |
LIST |
P = 12F509 |
; プロセッサの種類を指定 |
|||||
2 |
#INCLUDE |
<P12F509.INC> |
; プロセッサのインクルードファイルを指定 |
|||||
3 |
__CONFIG |
0x0A |
; このように記述することもできます | |||||
4 |
; 外部リセットを使用しない |
|||||||
5 |
; コードプロテクトしない |
|||||||
6 |
; ウォッチドッグタイマを使用しない |
|||||||
7 |
; 内蔵クロックを使用する |
|||||||
8
|
ORG |
0x000 |
; プログラム実行開始番地 |
|||||
9
|
MOVWF |
OSCCAL |
; OSCCALレジスタを更新 |
|||||
10
|
MOVLW |
0x08 |
; GP3を入力ポート、他は出力ポートに設定 |
|||||
11 |
TRIS |
0x06 |
; f=6 |
|||||
12 |
MOVLW |
0xDF |
; T0CSはゼロ、GP2を出力ポートに |
|||||
13 |
OPTION |
; OPTIONレジスタに書き込む |
||||||
14 |
GP0_OFF |
MOVLW |
0x00 |
; Wにb'000000'を格納して、それを |
||||
15 |
MOVLW |
0x06 |
; GPIOレジスタ(0x06番地)に書き込む |
|||||
16 |
SW1 |
BTFSC |
GPIO,3 |
; GPIOのビット3がLowのとき、アドレスを2つ進める |
||||
17 |
GOTO |
GP0_OFF |
; アドレスを2つ進める |
|||||
18 |
GP0_ON |
MOVLW |
0x01 |
; Wにb'000001'を格納して、それを |
||||
19 |
MOVWF |
GPIO |
; GPIOレジスタ(0x06番地)に書き込む |
|||||
20 |
GOTO |
SW1 |
; おなじことを繰り返す |
|||||
21 |
END |
; プログラムはここで終了 |
ダウンロード
12F509_SW1.asm
このプログラムを実行すると、ボタンを押している間だけLEDが「点灯しているようにみえます」。しかし、実際は、ボタンを押してから数ミリ秒の間、LEDは点滅しているのです。前回の「LEDを点滅させよう」のところでためしたように、ボタンを押してからLEDが点灯、消灯を高速にくりかえしていても、網膜の残像でLEDが点灯しつづけているかのようにみえるのです。これは、スイッチのボタンを押したりはなしたときに、スイッチの接点には弾性があるので、一瞬の間、バウンド(反跳、バウンス)して開閉を繰り返す、チャタリング(Chattering)がおきるためです。
ためしに、チャタリングがおきていることをたしかめるためのプログラムをつくってみました。下記のプログラムを実行すると、タクトスイッチのボタンを押すタイミングによっては、LEDが点灯しないことがあります。
ダウンロード
12F509_SW2.hex
チャタリングの防止
チャタリングは、蛍光灯のスイッチでは使用上の不都合はなくても、1回ボタンを押すと1個ではなくて2個以上のパルスが発生するということですから、デジタル回路では不都合が生じるかもしれませんね。このチャタリングを防止するには、スイッチからの入力部分に、CR時定数をチャタリングの継続時間より多くした波形整形回路を追加するか、PICのプログラムでスイッチの入力判定にチャタリングの継続時間より多めの遅延時間をとる必要があります(注:ストップウォッチのような用途では、スイッチの入力判定の遅延時間をとってしまうと、不具合が生じる場合もあります)。
![]() |
上記以外にもさまざまなチャタリング防止回路があるようです。
ここでは、外つけ部品を増やすのはめんどうですので、プログラムで処理することにしました。実験ボードで使用しているタクトスイッチの場合、データシートではチャタリングの時間は5ミリ秒以下と記載されていました。他のメーカーでもだいたいおなじようです。それで、スイッチ入力判定用の遅延時間を5ミリ秒にしたプログラムを考えてみました。しかし、いざ実行してみると、「チョイ押し」のような、ボタンの押し方によってはしばしば誤作動しました。ボタンを押したときとボタンをはなしたときの両方で接点がバウンスしているようです。それで、入力判定の遅延時間をボタンをはなしたときもふくめて倍以上長くして、タクトスイッチのような押しボタンスイッチ以外でも対応できるように、20ミリ秒に変更してみたところ、誤作動はなくなりました。
ボタンを押すと、GP0につないだLEDが点灯し、もういちどボタンを押すとLEDが消灯するプログラムです。ボタンの押し下げによるトグルの判定時間を長くするとLEDの点灯・消灯まで間延びする感じがしましたので、200ミリ秒でトグルの判定をするようにしました。したがって、ボタンをそれ以上の時間押しつづけると、LEDは点滅することになります。期待どおりにPICが動くと、うれしいものですね。もっとスマートなコードが書ければいいのですが、あせらずに一歩一歩勉強していくことにしましょう(FENG3曰、「吾五十而志於学」…がんばろう!)。今回はここまで。
1 |
LIST |
P = 12F509 |
; プロセッサの種類を指定 |
|||||
2 |
#INCLUDE |
<P12F509.INC> |
; プロセッサのインクルードファイルを指定 |
|||||
3 |
__CONFIG |
0x0A |
; このように記述することもできます | |||||
4 |
; 外部リセットを使用しない |
|||||||
5 |
; コードプロテクトしない |
|||||||
6 |
; ウォッチドッグタイマを使用しない |
|||||||
7 |
; 内蔵クロックを使用する |
|||||||
8
|
i |
EQU |
0x07 |
; ループカウンタの変数の定義 |
||||
9
|
j |
EQU |
0x08 |
; ループカウンタの変数の定義 |
||||
10
|
k |
EQU |
0x09 |
; ループカウンタの変数の定義 |
||||
11 |
ORG |
0x000 |
; プログラム実行開始番地 |
|||||
12 |
MOVWF |
OSCCAL |
; OSCCALレジスタを更新 |
|||||
13 |
MOVLW |
0x08 |
; GP3を入力ポート、他は出力ポートに設定 |
|||||
14 |
TRIS |
0x06 |
; f=6 |
|||||
15 |
MOVLW |
0xDF |
; T0CSはゼロ、GP2を出力ポートに |
|||||
16 |
OPTION |
; OPTIONレジスタに書き込む |
||||||
17 |
START |
MOVLW |
0x00 |
; Wにb'000000'を格納して、それを |
||||
18 |
MOVWF |
GPIO |
; GPIOレジスタ(0x06番地)に書き込む(LED消灯) |
|||||
19 |
BTFSC |
GPIO,3 |
; ボタンが押されるまで待つ |
|||||
20 |
GOTO |
$-1 |
; 上記のループ |
|||||
21 |
MOVLW |
.20 |
; ボタンが押されたら |
|||||
22 |
MOVWF |
i |
; バウンシングが収束するまで |
|||||
23 |
CALL |
DELAYms |
; 20ミリ秒待つ |
|||||
24 |
BTFSC |
GPIO,3 |
; ボタンが押されているか |
|||||
25 |
GOTO |
$-6 |
; 押されていなければもういちど繰り返す |
|||||
26 |
MOVLW |
.200 |
; ボタンのトグル判定時間 |
|||||
27 |
MOVWF |
i |
; 200ミリ秒 |
|||||
28 |
CALL |
DELAYms |
; 待つ |
|||||
29 |
LED_ON |
MOVLW |
0x01 |
; LEDを |
||||
30 |
MOVWF |
GPIO |
; 点灯させる |
|||||
31 |
BTFSC |
GPIO,3 |
; ボタンが押されるまで待つ |
|||||
32 |
GOTO |
$-1 |
; 上記のループ |
|||||
33 |
MOVLW |
.20 |
; ボタンが押されたら |
|||||
34 |
MOVWF |
i |
; バウンシングが収束するまで |
|||||
35 |
CALL |
DELAYms |
; 20ミリ秒待つ |
|||||
36 |
BTFSC |
GPIO,3 |
; ボタンが押されているか |
|||||
37 |
GOTO |
$-6 |
; 押されていなければもういちど繰り返す |
|||||
38 |
MOVLW |
.200 |
; ボタンのトグル判定時間 |
|||||
39 |
MOVWF |
i |
; 200ミリ秒 |
|||||
40 |
CALL |
DELAYms |
; 待つ |
|||||
41 |
GOTO |
START |
; はじめにもどってLEDを消灯、以後繰り返し |
|||||
42 |
INCLUDE |
delayms.inc |
; 遅延ルーチンのインクルードファイルを指定 |
|||||
43 |
END |
; プログラムはここで終了 |
ダウンロード
12F509_SW3.asm
delayms.inc
注: ソースファイルのコメントが上記とことなる場合があります
ダウンロード
12F509_SW3.hex
2005年3月15日作成