マイクロチップ社のマイクロコンピュータPIC16C/F84を使った製作例の
ソフトウェア製作方法の紹介です。(「ゲームラボ’98/6月号に掲載)
さて前回製作した電子ルーレットのプログラムの作り方を紹介します。
PICマイクロチップの基本的なプログラムの作り方を、実際の製作を
しながら紹介して行きます。
2.PICのプログラム
PICの命令はどうやって実行されるのでしょうか?
まずPICはプログラムを格納するプログラムメモリを内蔵しています。
しかも、PIC16C/F84はこのプログラムメモリが何回でも書いたり消したり
することが出来るという、超便利なワンチップマイコンです。
このプログラムを「書いたり消したり」というのはどういうことでしょうか?
PICのこのメモリは電気が無くなっても消えないメモリとなっています。
つまり、電気を入れた瞬間に0番地から命令が実行されることになります。
しかし、電気を切っても消えないメモリも、ある特定の電気的条件を
満たしてやると自由に変更することが出来るようになります。
この条件を整えるのが第1回で製作した「PICライタ」なのです。
このPICライタでプログラムをメモリに書き込みます。プログラムは命令の
集まりで出来ている訳で、メモリの0番地から順次取り出されて実行されて
行きます。
この命令には大きく分けて (1)バイト処理命令 (2)ビット処理命令 (3)リテ
ラル(定数)処理命令 (4)ジャンプ命令 (5)制御命令の5種類があります。
(1)〜(3)はレジスタを使った演算処理をする命令で、(4)はプログラムの実行
の流れを変更する命令、(5)はタイマなどのハード制御をします。
PICは、これら全部を合わせても表-1の35種類の命令しかありませんので、
覚え易く使いやすいマイコンです。
表−1
nemonic : 内容 : 影響フラッグ :サイクル :オペコード
---------------------------------------------------------------------
ADDLW k : w + k -> w : C,DC,Z : 1 : 11 111x kkkk kkkk
ADDWF f,d : w + f -> dest : C,DC,Z : 1 : 00 0111 dfff ffff
ANDLW k : w AND k -> w : Z : 1 : 11 1001 kkkk kkkk
ANDWF f,d : w AND f -> dest : Z : 1 : 00 0101 dfff ffff
BCF f,b : 0 -> f<b> : None : 1 : 01 00bb bfff ffff
BSF f,b : 1 -> f<b> : None : 1 : 01 01bb bfff ffff
BTFSC f,b : skip if f<d>=0 : None : 1(2) : 01 10bb bfff ffff
BTFSS f,b : skip if f<d>=1 : None : 1(2) : 01 11bb bfff ffff
CALL adr : Subroutine Call : None : 2 : 10 0kkk kkkk kkkk
PC+1 -> TOS k -> PC<10:0> PCLATH<4:3> -> PC<12:11>
CLRF f : 00h -> f : Z(=1) : 1 : 00 0001 1fff ffff
CLRW : 00h -> w : Z(=1) : 1 : 00 0001 0xxx xxxx
CLRWDT : 00h -> WDT : PD,TO : 1 : 00 0000 0110 0100
0 -> WDT prescaler 1 -> PD(STATUS<3>) 1 -> TO(STATUS<4>)
COMF f,d : f -> dest : Z : 1 : 00 1001 dfff ffff
DECF f,d : f - 1 -> dest : Z : 1 : 00 0011 dfff ffff
DECFSZ f,d : f - 1 -> dest, : None : 1(2) : 00 1011 dfff ffff
skip if result=0
GOTO k : k -> PC<10:0> : None : 2 : 10 1kkk kkkk kkkk
PCLATH<4:3> -> PC<12:11>
INCF f,d : f + 1 -> dest : Z : 1 : 00 1010 dfff ffff
INCFSZ f,d : f + 1 -> dest, : None : 1(2) : 00 1111 dfff ffff
skip if result=0
IORLW k : w OR k -> w : Z : 1 : 11 1000 kkkk kkkk
IORWF f,d : w OR f -> dest : Z : 1 : 00 0100 dfff ffff
MOVLW k : k -> w : None : 1 : 11 00xx kkkk kkkk
MOVF f,d : f -> dest : Z : 1 : 00 1000 dfff ffff
MOVWF f : w -> f : None : 1 : 00 0000 1fff ffff
NOP : No Operation : None : 1 : 00 0000 0xx0 0000
RETFIE : 割り込み処理から : None : 2 : 00 0000 0000 1001
のリターン TOS -> PC, 1 -> GIE(INTCON<7>)
RETLW k : k -> w して : None : 2 : 11 01xx kkkk kkkk
リターン TOS -> PC
RETURN : サブルーチン : None : 2 : 00 0000 0000 1000
からのリターン TOS -> PC
RLF f,d : 左回転 : C : 1 : 00 1101 dfff ffff
f<n> -> d<n+1> f<7> -> C C -> d<0>
RRF f,d : 右回転 : C : 1 : 00 1100 dfff ffff
f<n> -> d<n-1> f<0> -> C C -> d<7>
SLEEP : スリープモード : PD,TO : 1 : 00 0000 0110 0011
00h -> WDT 1 -> PD(STATUS<3>) 0 -> TO(STATUS<4>)
SUBLW k : k - w -> w : C,CD,Z : 1 : 11 110x kkkk kkkk
SUBWF f,d : f - w -> dest : C,CD,Z : 1 : 00 0010 dfff ffff
SWAPF f,d : f<0:3> -> d<4:7>, : None : 1 : 00 1110 dfff ffff
f<4:7> -> d<0:3>
XORLW k : w XOR k -> w : Z : 1 : 11 1010 kkkk kkkk
XORWF f,d : w XOR f -> dest : Z : 1 : 00 0110 dfff ffff
3.レジスタとは?
PICなどのマイコンには必ずレジスタと呼ばれるものがあります。
これは、命令の実行をする際のデータを一時的に格納するメモリで、一般に
データを格納するメモリより高速な動作をします。しかしPICの場合は特殊で、
このレジスタとデータメモリが一緒の内蔵データメモリとなっています。
例えば図-1はPIC16F84の場合のレジスタ一覧です。
図にあるアドレスを命令の中で指定します。例えば、「MOVWF 3」と書くと
ワーキングレジスタ(演算用の中継レジスタ)から、3番地にあるSTATUS
レジスタへ8ビットのデータが転送されるという動作をします。
しかしこのように数値で番地を直接指定していては、プログラムを読むのが
難しくなってしまうので、プログラムの最初に「STATUS EQU 3」という命令
でラベルを指定して「MOVWF STATUS」というように、番地の代わりにラ
ベルで書くようにします。
これでグンとプログラムが読みやすくなります。さらに、このようなラベルの
定義を毎回書いているのでは面倒なので、一括して定義することが出来
ます。これが「インクルードファイル」と呼ばれるものです。
システム共通で使うレジスタのラベルを定義したインクルードファイルが、
あらかじめ用意されています。このファイルを利用してプログラムの最初に
「INCLUDE P16F84.INC」という1行を追加すると、システムで毎回必要な
ラベルはまとめて定義されます。
4.サイクルとは?
PICの中では命令は、フェッチ(メモリから取り出し)と実行の2サイクルの
ステップで実際の処理がなされます。
さらにパイプライン処理といって、前の命令の実行中に次の命令のフェッチ
をしてしまうため、見かけ上、大部分の命令は1サイクルで実行が完了します。
但し、ジャンプ命令(CALL,GOTO)と判断命令(BTFSS,BTFSC,DECFS,DECFSC)
については、実行アドレスが突然スキップするため、フェッチし直しとなるため
2サイクル必要とします。
この命令の実行に必要な時間、つまりサイクルの時間をプログラムでタイミ
ングを取る時に利用します。
今回のルーレットでも、発光ダイオードを光らせる時間間隔をプログラムで
作っていますが、その作り方は、
(サイクル数)=(必要な時間)÷(サイクル時間)
で求めたサイクル数になるよう命令実行を繰り返すことで必要な時間を作り
出します。
実際の数え方の例は、リストの最後の方にあるタイマーサブルーチンで、
下記リストとなります。コメントしてありますので参考にして下さい。;******************************************
; タイマーサブルーチン
; TIM04 : 0.4msec TIM100:100msec
;******************************************
;**** 間隔待ちサブルーチン ****
WAIT
MOVWF CNT3 ;間隔保存
WAITLP
MOVF CNT3,W ;カウンタget
BTFSC STATUS,Z ;終わりか?
RETURN ;終了,戻る
CALL TIM04 ;0.8msec待つ
CALL TIM04
DECF CNT3,F ;カウンタ-1
GOTO WAITLP
;*** 0.4msecタイマサブルーチン ****
TIM04
MOVLW 0F9H ;249回
MOVWF CNT1
TIMLP1
NOP
DECFSZ CNT1,F
GOTO TIMLP1 ;2+4*249-1=997
RETURN ;997+1=998*0.4usec=約0.4msec
;**** 100msecタイマサブルーチン ****
TIM100
MOVLW 0F9H ;249回
MOVWF CNT2
TIMLP2
CALL TIM04 ;2+1003*249-1
DECFSZ CNT2,F
GOTO TIMLP2
RETURN ;+1=249749*0.4usec=約100msec
5.ルーレットのプログラム
さてそれでは実際の電子ルーレットのプログラムを見ていきます。
プログラムリストは下記でダウンロードできます。リストには日本語の説明
をつけたものもありますので参考にして下さい。
(プログラムをアセンブルする時は日本語の無いものを使って下さい。)
全体の流れは、まず初期化で入出力ピンのモード設定を行います。
RA4以外は全て出力モードです。
その次はstartキーの入力チェックの繰り返しループで、何も無いときは
常にここをループしています。
一旦startキーの入力を検出したら、100msec待ってからキー入力を再確認
しています。これはチャッタリングを避けるためのキー入力プログラミングの
基本です。
このチャッタリングとは何かというと、スイッチやリレー類に必ずあるもので、
下図の様にスイッチ動作の時、一旦スイッチの接点が接触しても、バネの
弾みで短時間の間付いたり離れたりを繰り返すことを言います。
普通この時間は10msec以下です。
この不安定な時間を待ってから再度キー入力が続いているかを確認する
ことで、実際にキー入力があったと判断します。
次では、このキー入力が続いている間、「INTERVAL」という変数をカウント
ダウンしながらLEDを順番にシフトさせて点灯しています。
(ブザーはスイッチによりハードウェアで自動的に連続鳴動します。)
そしてstartキー入力が無くなったら、そこからルーレット動作が始まります。
まず、ブザーを鳴らすためにRA4を出力モードに設定変更します。
次にINTERVALの値x0.8msecの間だけ、LEDを点灯させたら、INTERVALを
+1だけカウントアップして、次のLEDを点灯させ、またINTERVAL分だけ
光らせたら次を点灯する。というように順次点灯をシフトさせて、INTERVAL
がFF(16進数)になったらそこで停止したままとします。
つまり順次点灯シフトがゆっくりになります。またLEDを点灯させる時には、
直前にブザーを鳴らすため、RA4にトリガーパルス信号を出力します。
瞬時だけ信号を出せば、あとはタイマICが0.1秒間だけブザーを鳴らしてくれ
ます。
停止させるときには、RA4ポートのモードを元の入力に戻してから、最初の
キー入力待ちのループに戻ります。これで繰り返し同じ動作をすることに
なります。
キーを押している間は非常に高速でLEDの順次点灯が行われるため、人間
がキーを離す瞬間を同じ位置にすることは不可能です。
これによって、毎回スイッチを離した瞬間のLEDの位置が異なるため、最後
の停止位置も毎回異なることになりギャンブルとすることが出来ます。
★ 電子ルーレットプログラムリスト(日本語説明コメント付き)
(ダウンロード出来ます、ディスクに保存し印刷して使って下さい)
6.プログラム作成
いよいよプログラム作成です。作成とテストには「MPLAB」というソフトの道具
を使います。
入手方法はマイクロチップ社のホームページからダウンロードします。
下記プログラムリストをソースリストとして「MPLAB」を使ってパソコン上で編集
します。
編集後、MPLABでアセンブルします。アセンブルエラーが無くなるとPICに書
込むための「HEXファイル」というものが生成されます。
これを前回作成したPICライタを使ってパソコンからPICに書込みます。
この書込みが完了したPICをルーレットのICソケットに実装して電源をONと
すれば、動作を開始します。
正常に開始しなければ、プログラムのどこかが間違っていますので再度
チェックします。プログラムのチェックはMPLABのシミュレータ機能を使います。
パソコン上で擬似的に作成プログラムを実行させ内部動作の確認をします。
このシミュレーションはちょっと面倒ですが、目にみえる形でプログラムの
テストが出来ますので非常に便利です。必ず使いましょう。
★ 電子ルーレットプログラムリスト
(ダウンロードしてお使い下さい)