PICNIC

課題1 ドア開放回数カウント・表示機能の実現

■ 課題1 

1. 課題1の目標

2. 回数カウント用の変数counterの新設

3. TMR1内部タイマ・割り込み処理ルーティン

4. ドア開閉状態(RB0)→LED#4(RB4)へ正論理で出力

5. ドア開放回数のカウントモジュール:test4

6. 回数カウンタのweb制御画面への表示

7. 実行例

8. 課題1の提出

9. 考察のポイント

■レポート提出システム

 

→質問やお気づきの点はこちら

←目次へ戻る

2009年10月29日 9:34 更新

 

●課題1の目標

課題1として、「ドア開放回数カウント・表示機能の実現」の課題提出を行う。→課題提出はここから

基本的な実装方針は以下の通りである。

・回数カウント用の変数(8bit)を新設する
・TMR1タイマ割り込み(約13.1msec)の間隔でドア開閉状態を検査する
・ドア開閉状態(RB0)→LED#4(RB4)へ正論理で出力
・ドア閉→開の状態遷移を捉えて、回数カウンタを1増やす
・回数カウンタのweb制御画面への表示(パケット数表示と入れ替え)

●回数カウント用の変数counterの新設 (2003/10/12変更)

レジスタBANK#3 に回数カウント用の変数counterを新設する。

<実装例>

;-------------------------------------------------------------
; 実験用メモリ領域 BANK#3 [RP1:RP0]=[1:1] 1B0h -- 1EFh
;-------------------------------------------------------------
; PAGE 3
counter EQU 1E0H ; カウンタ#0
counter1 EQU 1E1H ; カウンタ#1
counter2 EQU 1E2H ; カウンタ#2
counter3 EQU 1E3H ; カウンタ#3

今後のことも考えて、まとめて4つほどカウンタを新設しておく。
BANK#3のレジスタへの直接アクセスは、STATUSレジスタのRP1とRP0を1にセットしてバンク切り替えを行った後、参照を行うこと。(何のことか判らない人は、マニュアルページの14ページを参照せよ)


※2003/10/12変更点: 最初は 1B0からの4バイトをcounter変数として確保しましたが、Web制御画面上から、RB5を頻繁に切替えたり、webブラウザからの連続reload攻撃を行ったりすると、1B0付近の汎用レジスタに何処かで何か値が入ってしまうことが判明しました。この領域は実際にEQUで変数定義されていませんので、オリジナルのv12.asmの汎用レジスタ操作(RP0,RP1)の関係にバグ(BANK#1のつもりがBANK#3で変更をかけている)があるか、PIC16F877自体が抱えている問題かも知れません。この問題を回避するために、1E0からの4バイトをcounter変数として確保するように変更します。いずれにせよ、BANK#3であることに変わりはないので、以下の説明は修正前と変わりません。なお、変数counterの初期化は、startモジュールの最後の方で行うとよいでしょう。

●TMR1内部タイマ・割り込み処理ルーティン

注意点:課題0において、main0ラベル直後に、testモジュールcall処理のため、4ステップを追加して動作を確認したところである。(課題0のココを参照せよ)

しかしながら、課題1以降は、実装していくモジュールの呼び出しは、タイマ割り込みルーチンからジャンプする形態をとるため、課題0でmain0ラベル直後に追加した呼び出し処理については、必ずコメントアウトするか削除しておくこと。(2005/5/3追記)


※PIC16F877+PICNICファームウェアv12.asmにおける現状の内部タイマ・割り込み処理関係に関する説明はここから参照のこと。


割り込みルーティン内から外部callすると何処かでPCスタックが溢れて動作不良となる。

割り込みルーティン内では、無用にコードを増やしていくことが事実上困難(プログラムメモリPAGE#0は一杯)。

割り込みルーティンから、プログラムメモリPAGE#3に存在する外部モジュールをPCLATHしてgotoジャンプ→割り込みルーティン内のリターン用タグへ戻すのは容易なので、この方法を採用することとする。


割り込みルーティン側呼び出し
<実装例>

int_tmr1        ; DHCP要求完了タイムアウトチェック
bcf PIR1,TMR1IF
BSF STATUS,RP0
MOVF dhcp_done,0
andlw 7FH
btfss STATUS,Z
DECF dhcp_done,1
bcf STATUS,RP0
;;++++++++++++++++++++++++++++++++++++++
movlw HIGH (test4) ; test4 >> 8 PAGE位置取得
movwf PCLATH ; PAGE制御レジスタセット
goto test4 ; test4モジュールへジャンプ
int_tmr9 ; →test4からはここへ戻ってくる
clrf PCLATH ; PAGE制御レジスタリセット
;;++++++++++++++++++++++++++++++++++++++
int_tmr2 ; ソケットタイムアウトチェック

上記の例では、割り込み処理ルーティン内から

int_tmr1→test4へジャンプ→(カウント処理)→int_tmr9へ戻る→int_tmr2

の順序で実行されていく。

●ドア開閉状態(RB0)→LED#4(RB4)へ正論理で出力

チュートリアル(課題0)における実験4(test2モジュール)を参考にせよ。

【実験4】RB0(ドアセンサ)→RB4(LED#4)へ出力 test2モジュールの作成

 

●ドア開放回数のカウントモジュール:test4

割り込み処理ルーティンから13.1msec間隔で呼び出されるはず。
基本的は実装は、チュートリアルにおける実験4(test2モジュール)をベースとすれば良い。

割り込みルーティンからの呼び出しとなるので、チュートリアル(課題0)で説明したwk2,wk1によるSTATUS、Wレジスタ値の保存は危険である。

・STATUS値の保全は行わないこととする。
・Wレジスタ値の一時保存用には、LCD表示用の変数tmpを流用する(たぶん大丈夫)。


カウンタ変数counterを+1するタイミングは、先に作成したtest2モジュールをベースとした場合、処理の概要は以下のようになるであろう。

・ドアが開いているか?(RB0のチェック)
・「1ステップ前のドア状態」つまりRB4のビット検査を行う
・もし、1ステップ前にはドアは閉じていたならば、
 このタイミングが、ドア閉→開の状態変化が起きた瞬間である。
カウンタ値を+1する

test4モジュール側
<実装の雛形>

;----------------------------------------------------------------------
; test4モジュール [ver0.6]
;----------------------------------------------------------------------
org 1E00h
test4
; 割り込みルーティンからのエントリポイント
clrF STATUS ; STATUSレジスタクリア
;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
................
※上記の説明の通りに実装していく
ドア開閉状態(RB0)→LED#4(RB4)
ドア閉→開の状態変化の検出 カウンタ+1
................
;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; 割り込みルーティンへの復帰
movlw HIGH (int_tmr9) ; int_tmr9 >> 8 PAGE位置取得
movwf PCLATH ; PAGE制御レジスタセット
goto int_tmr9 ; int_tmr9へジャンプ
;----------------------------------------------------------------------

●回数カウンタのweb制御画面への表示

カウントした変数counterの値(8bit)をweb制御画面へ表示する。
表示場所については、Status:パケット数表示の部分と入れ替えることとする。
(コントロールコード '$9' を流用)

ctrl_code1で、コントロールコード '$9'からの呼び出しを変更する。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
<変更前>
goto put_send_packet ; 9:送信パケット数

<変更後>
goto put_counter ; 9:実験用カウンタ表示[ver0.6]
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


実験用カウンタcounter表示用のモジュール put_counterの処理は以下のようになるであろう
(2009.10.28修正)。

<処理手順の例>

put_counter     ; 実験カウンタ表示用
BANK#3へ切り替え
Wreg <-- counter
BANK#0へ切り替え
put_decimalモジュール呼び出し(8bit10進数表示用・引数 Wreg)

●実行例

電源投入直後 → 1回ドアを開け閉めした後 → .... → 10回目

ドア状態に応じて、LED#4(RB4)が点灯・消灯している。

●課題1の提出

【課題1】
ドア開放回数カウント・表示機能を実現するための各種モジュールの作成 を行いなさい。仕様通りの動作が行われることを、ドアセンサ状態、web制御画面、カウンタ値の変化を用いて確認せよ。

(1)ドア開放回数カウント・表示機能を実現するための各種モジュールの作成 を行いなさい。

(2)仕様通りの動作が行われることを、ドアセンサ状態、web制御画面、カウンタ値の変化を用いて確認せよ。

(3)アセンブルソースファイルのバージョン番号を、
 ver1.2.0.6
へ変更せよ。また、web制御画面のフッタ部分を、各自の学籍番号等に適宜変更せよ。

(4)完成したアセンブルソースファイルを v1206e1.asm という名前で保存せよ(全て半角英数字・アルファベットは小文字、半角カタカナ・全角文字はファイル名には決して使用しない)。

(5)以下のレポート提出システムから、v1206e1.asm をアップロードせよ。レポート受領後、採点が行われる。

<提出方法>
作成したプログラムは以下のレポートシステム(ファイルアップロード機能付き)を用いて、アセンブル・ソースファイル(拡張子が *.asm のもの。*.hexの方ではない)を提出します。 

提出されたファイルは、こちらで動作を確認した後、動作に不備があった場合には再提出、動作がOKの場合には修了の判定を行います。

レポート課題1(課題番号:picnic-exp01)の提出はここからどうぞ

(6)「判定待ち」となります。少々お待ちください。なかなか判定結果が出ない場合は、こちらへメールして下さい。

(7)再提出判定がなされた場合には指摘された不具合を修正し、v1206e1a.asmなどとファイル名を替えて、再提出する。

(8)(7)でない場合(修了判定)、レポート課題1は受理され、完了となった。

 

●考察のポイント

以下に、今回の仕様と実装に対する考察ポイントを挙げます。レポートとして回答必須ではありませんが、プログラム完成・レポート提出前に必ず各自で考えをまとめておくようにせよ。

 

[1] 8bitカウンタを使用しているため、256回ドアを開け閉めすると変数がオーバーフローして 0回 に回数が戻ってしまう。これを防ぐためにはどのように改良すればよいか?

[2] ドア開閉回数として16bitカウンタを使用すれば、実際の使用上、オーバーフローすることはないであろう。このための変更点はどの部分か?

[3] チャタリング時間が非常に長い(TMR1タイマ割り込み間隔の3倍程度)ようなドアスイッチを入力とした場合、1回の開け閉め動作に対して、2回以上、誤ったカウントアップが行われる可能性がある。これを防ぐためにはどのように改良すればよいか?

[4] 回数カウンタ counter は、リセット後、何処かで初期値:=0にセットされるべきである。これは具体的に何処へ実装したらよいか?

信州大学インターネット大学院

Creative Commons License

IT技術演習(院)−PICNIC− by Katsumi WASAKI is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.1 Japan License.