動作環境設定
ラベル定義
;**************** Label Definition ********************
cblock h'20'
データエリアにはCBLOCK疑似命令を使用して20hから自動割付を行っています。割付の終了にはENDCを使います。
以下に今回使用しているデータエリアの意味(使用目的)を示します。
| ラベル |
| 用 途 |
| data_c | : | 聖、典、プの種別データを格納するエリアです。 |
| data_h | : | 100位のデータを格納するエリアです。 |
| data_t | : | 10位のデータを格納するエリアです。 |
| data_u | : | 1位のデータを格納するエリアです。 |
| disp_p | : | LEDに表示するデータの位置を格納するエリアです。 |
| key_p | : | 動作状態を確認するスイッチの位置を格納するエリアです。 |
| key_data | : | スイッチ押下状態を管理するデータの格納エリアです。 |
| key_flag | : | スイッチ押下で処理が繰り返えされないようにするためのガード情報格納エリアです。 |
| tx_p | : | 表示装置に送るデータの位置を格納するエリアです。 |
rc4 は RC4ポートのビット位置(4)を指定しています。この指定は p16f873.inc には含まれていないので、個別に指定しています。
seg7_0 から seg7_b では7セグメントLEDの点灯セグメントデータを指定しています。各ビットと各セグメントの対応はハードウェアの回路に合わせます。今回の回路では右から0ビット目が g セグメントに対応し、6ビット目が a セグメントに対応しています。0で点灯、1で消灯になります。7ビット目は 0 にしています。このビットは表示装置にデータを送る際、転送開始データの識別用に使用したので、0 を設定しています。
seg7_a は異常処理時の表示用で (E) を表示します。 seg7_b はLEDの全セグメントを消すためです。
プログラム開始
;**************** Program Start ***********************
電源投入/リセット時はプログラムメモリアドレスは h'0000' からスタートします。また、割り込み処理のスタート番地は h'0004' です。goto命令で各処理にジャンプするようにしています。 h'0000' は初期化処理、h'0004' はタイマー割込処理にジャンプします。
初期化処理
;**************** Initial Process *********************
電源投入後の初期化処理として以下の処理を行います。
| ポートA、BおよびCのモード初期化 |
| |
AポートはLED制御位置指定用で、全てデジタルモード(ADCON1)、出力モード(TRISA)にします。
BポートはLEDのセグメント制御用で、全て出力モードにします。(TRSIB)
CポートのRC0-RC3はスイッチ検出位置指定用なので出力モード、RC4はスイッチの状態取り込み用なので入力モードにします。(TRSIC) |
| |
| LED点灯制御、スイッチ検出スキャン用タイマーの初期化 |
|
|
LEDの点灯制御とスイッチの状態検出制御は同じ周期で行います。周期制御にはタイマー0を使用し、2_秒の周期を指定しています。プリスケーラを1:8にしているので、タイマー値を6にすると2_秒になります。タイマーは加算方式で256カウント目(255→0)でタイムアウト割り込みが発生します。
(256-6)×8=2000マイクロ秒。 |
| |
| ポートの初期化 |
|
|
AポートはLED制御位置指定用で、種別LEDの位置にしています。
BポートはLEDセグメント制御用で、全て消灯にしています。
Cポートはスイッチ検出位置指定用で、SW1の位置にしています。 |
| |
| ワークエリアの初期化 |
|
| LED表示データの初期化(消灯状態)、LED制御情報、スイッチ制御情報、データ送信情報の初期化を行います。 |
| |
| USARTの初期化 |
|
|
USARTの設定に関するレジスタの多くはバンク1にあるので、バンク指定に気を付ける必要があります。
通信速度9600bps、非同期シリアル通信を指定しています。送信完了割り込みも可能にします。この送信可能割り込みは送信データ設定レジスタの内容が送信バッファに送られ、設定レジスタが空き状態になったことを表すものです。データ送信が完了したことではありません。
このUSART初期化処理の時点では送信機能は、まだ、動作させません。TXSTAのTXENビット=0。 |
| |
| 割り込み初期化 |
|
| GIE、PEIE、T0IEを設定しています。送信完了割り込みを使うにはPEIEを設定する必要があります。 |
以上で初期化処理が終了しました。後は割り込みを待つだけなので、メイン処理としては同じアドレスを繰り返し実行させているだけです。オペランドの'$'は自分のアドレスを意味しています。'$+1'は自分のアドレスの次のアドレスを意味します。
割り込み処理
;*************** Interruption Process *****************
今回のソフトでは2種類の割り込みを使用しています。TMR0のタイムアウトによる割り込みと送信データ設定バッファが空きになったときの割り込みです。
TMR0の割り込みはINTCONレジスタのT0IFビット、送信バッファ割り込みはPIR1レジスタのTXIFビットで識別します。
異常割り込み処理
;******** Illegal interruption (For debugging) ********
上記の2種類の割り込みに当てはまらない割り込みが発生した場合、LEDの1位に "E" の文字を表示して異常発生が分かるようにしました。この処理は通常は動作することはありません。用途としてはソフトウェアの動作確認に使えます。
ほとんどのソフトウェアの動作確認はMPLABのデバッグ機能を使用して確認することができますが、送信機能、データ入力などの確認はできません。その場合には実際のPICにソフトウェアを書き込んで動作させて確認しますが、そのままでは正常に動作しているかどうか分かりません。その場合、チェックしたいロジックに goto illegal を入れておきます。例えば、送信キーを押した時に送信キー処理が実行されるかどうかを確認する場合などに使えます。702行目に goto illegal を入れると、送信キーを押したときに"E"が表示されるので、その処理が実行されることが分かります。ただし、処理は"E"を表示して停止するので、動作確認のあとに元の処理に戻しておく必要があります。
割り込み終了処理
;************ END of Interruption Process **************
割り込み終了割り命令(RETFIE)を実行し、次の割り込みを可能な状態にします。
割り込み時にレジスタ類の待避もしていないので他に何もすることはありません。
LED表示制御処理
;**************** LED control Process *****************
| 割り込みフラッグのクリア |
| | TRM0により2_秒毎に割り込みが発生します。最初にINTCONCレジスタのT0IF割り込みフラッグをクリアします。これをしないと次の割り込みが所定の時間を待たずに発生してしまいます。また、TMR0のタイマー値の再設定も行います。 |
| |
| LED制御 |
|
|
LEDの制御は2_秒の割り込み毎に1桁づつ行います。4種類(種別、100位、10位、1位)のLEDがあるので、一巡するのに8_秒かかります。ですから、各桁は8_秒毎に2_秒だけ点灯する動作をします。この速さで制御すると人間の目には残像により連続して点灯しているように見えます。LEDの制御は種別→100位→10位→1位の順で制御しています。
TMR0の周期を1_秒にすることもできますが、LEDおよびスイッチを制御するトランジスタの性能により誤動作する可能性があります。今回の回路では1_秒にすると100位のLEDのセグメントがその前に制御する種別データの影響により薄く点灯したので、周期を2_秒にしました。 |
スイッチ・スキャン処理
;****************** Key scan Process ******************
LED制御に引き続きスイッチのスキャン処理を行います。
| スイッチ・スキャン位置 |
| |
スイッチは割り込み毎に1つのスイッチの状態をチェックします。チェックする順番はSW1からです。
スイッチは全部で15個あるので、全スイッチをチェックするのに30_秒かかります。人間のスイッチを押す動作からすると問題にはならない時間です。 |
| |
| 誤検出防止 |
|
|
スイッチ動作の誤検出を防止するために2回連続してスイッチONを検出した場合に正常な押下動作として検出するようにしています。1回目のON検出では検出したスイッチ番号をkey_dataに格納するだけで、押下の処理はしません。そしてSW1からスキャンさせるようにしています。SW1からのスキャンに戻すことによりSW1を最優先スイッチとし、複数のスイッチが同時に押された場合の誤動作を防止しています。
同じスイッチを2回連続して検出するとスイッチが押下されたと認識し、そのスイッチに対応する処理を行います。それと同時にkey_flagを設定して処理済みの記録をしています。これにより、スイッチが連続的に押されていた場合に処理を何度も繰り返してしまうことを防止しています。
各スイッチのスキャンの方法は全て同じにしています。サブルーチンにすることもできますが、メモリに余裕があること、サブルーチンの入出力管理が複雑になることの理由でソースプログラムでは同じようなステップを書いています。見やすさを優先させたため、処理ステップ数は多くなりました。 |
| |
| 数字スイッチ |
|
| SW1からSW10は数字入力用のスイッチです。数字スイッチが押下されると7セグメントLEDの表示を左に1桁ずらしてスイッチに対応する数字を1位の位置に表示します。すなわち、10位→100位、1位→10位として1位に新たな数字を設定します。 |
| |
| 種別スイッチ |
|
| SW11からSW13は種別入力用のスイッチです。押下された種別に対応するLEDのみを点灯します。 |
| |
| 送信スイッチ |
|
| SW14は送信開始スイッチです。このスイッチが押下されるとTXSTAレジスタのTXENを"1"にして送信機能を動作させます。これにより送信割り込みが発生するようになります。実際のデータ送信動作は割り込み処理で行われます。 |
| |
| 表示クリアスイッチ |
|
| SW15は表示クリアスイッチです。このスイッチが押下されると種別、100位、10位、1位のLEDを消します。 |
データ送信処理
;***************** Data send Process ******************
表示装置へのデータ送信はこの処理により行われます。この処理はPIR1レジスタのTXIFビットによる送信バッファ割り込みで起動されます。TXIFビットは送信データを設定するTXREGレジスタが空きの状態を表しています。他の割り込み表示ビットと違ってソフトウェアでクリアする必要はありません。TXREGになかに入っているデータがTSRレジスタに転送され、TXREGから無くなると割り込みが発生します。また、TXSTAレジスタのTXENを"1"にして送信機能を動作させたときにも割り込みが発生します。TSRレジスタは送信動作で使用されるレジスタでソフトウェアで制御することはできません。
| 先頭データ |
| | 種別、数字データの送出に先立って先頭データ"10000000"を送出します。制御装置から送信される種別、数字データそれぞれにはデータの種別情報を付けていません。受信側では送出されるデータの順番でデータの種類を識別しています。ですから、先頭のデータが分からないとデータの種類を誤ってしまいます。そのため、データの先頭を識別するためにこのデータを送信しています。 |
| |
| データ送信 |
|
| 先頭データに続いて種別、100位、10位、1位のデータを順番に送信します。送信動作はTSRレジスタのデータが送り出されているときの次のデータを送信控えとしてTXREGレジスタに設定しているので、TSRレジスタのデータが送り出されると直ぐに次のデータの送信が行われます。この動作はバック・ツー・バック動作と呼ばれています。 |
| |
| 送信終了 |
|
| 1位のデータをTXREGレジスタに設定した後に発生する割り込みは1位データがTXREGレジスタからTSRレジスタに転送されたことを意味しています。ただ、このことは1位のデータが送信完了したことではありません。1位データがTSRレジスタから送信されたことはTXSTAレジスタのTRMTビットが"1"になることで確認します。TRMTビットの変化では割り込みは発生しません。ですから、送信完了はこのビットをソフトウェアで繰り返しチェックすることにより行います。送信完了を確認したあと、TXSTAレジスタのTXENビットを"0"にして送信機能を停止します。 |
各データは8ビットで構成され、それぞれスタートおよびストップが1ビットづつ加わり合計10ビットで構成されます。データは先頭データを含め5つあるので、合計50ビットのデータになります。今回の回路の回線速度は9600bps(bit par second)なので、全てのデータを送信するのに要する時間は 50bit/9600bps = 5.2_秒になります。
コーディングの終了
;********************************************************
; END of signboard control processing
;********************************************************
end
コーディングの最後は end命令 で終了します。endが無いとアッセンブラはコーディングの最後を検出できず。エラーになります。
|