目次>5章 第2ステップ(色々な実験)>(1)LEDを点滅させる
LEDを点滅させる
更新日2005.6.25
PIC16F84Aに緑と赤のLEDを接続し、0.5秒毎に点滅させるプログラムを作ります。
実験回路
|
・ | 実験回路は以下の通りです。3章.第1ステップ(動かしてみる)で作成したものと同じです。
PORTBのRB0とRB1に緑と赤のLEDを接続していますので、RB0とRB1をオン/オフさせれば2つのLEDを点滅できます。
-
|
点滅させるには
|
| 0.5秒毎にLEDをオン/オフさせるプログラムは、以下のような処理をすれば良い事になります。
-
それでは、順にプログラムを作って行きましょう。
|
PICを初期化する
|
| 今回のプログラムでは、PORTBのRB0,RB1を出力モードに設定するだけです。また、RB2〜7には何も接続しませんので、PORTB全てを出力モードに設定しましょう。
(使わないポートは入力モードにしておくのが安全ですが、今回は簡易的このようにします)
PORTBの入出力モード設定は、TRISBレジスタで指定します。(PICの仕組み参照)
PORTB全てのピンを出力に設定しますので、TRISBの全ビットをオフ(0)にします。
この処理は以下のようになります。
|
BSF | STATUS,RP0 | ; ファイルレジスタSTATUSのRP0(ビット5)をセット(1)する → バンク1
| CLRF | TRISB | ; ファイルレジスタTRISBをクリア(0) → PORTBは全て出力
| BCF | STATUS,RP0 | ; STATUSのRP0をクリア(0) → バンク0に戻しておく
|
|
|
RB0,RB1をオン/オフする
|
| これは、3章で作ったプログラムと同じです。
RB0,RB1をオンにするには、次のようになります。
|
MOVLW | 03h |
| MOVWF | PORTB | ; RB0,RB1をオンにする
|
|
この処理は、03hをWレジスタに格納し、Wレジスタの内容(03h)をPORTBに転送します。
03hは16進表現であり、ビット表現(2進数)では
00000011となります。
これで、ビット0と1(RB0と1)がオンになり、他のビットはオフになります。
(2進数と16進数については、7章(9)2進数と16進数(と10進数)を参照下さい。)
逆に、RB0,RB1をオフ(と言うかPORTBの全ビットをオフ)にするには、
となります。
|
0.5秒待つ(考え方)
|
| 簡単そうですが、少し厄介です。(分かってしまえば簡単ですが・・・)
- PIC16F84Aで一定時間待つには以下の2通りの方法があります。
- (1)命令を一定回数繰り返し実行する事で時間を稼ぐ
- (2)TMR0割込みを使う
ここでは、(1)の方法を使用します。TMR0割込については、5章(5),(6)で実験します。
PIC16F84Aには、35個の命令があります。そして全ての命令は4クロックで実行されます。
(4クロックを1サイクルと呼びます)
クロックは、OSC1/2ピンに接続するレゾネータ(発振子)の周波数により決定されます。
今回は、10MHzのレゾネータを使用していますので、1秒当たりのクロック数は、
となります。
従って、1クロックの時間は
| 1秒/10,000,000 = 0.1μS(マイクロ秒)
|
となります。
1つの命令は、4クロック(1サイクル)で実行されますので、1命令を実行するのに
かかります。
以上の事から、0.5秒待つには、
| 0.5S/0.4μS = 1,250,000命令(サイクル) |
実行すればよい事になります。
時間とクロックの関係を図で表すと次のようになります。
ここで留意点が2つあります。
| @PICの命令には、8クロック(2サイクル)かかるものがある(→PICの命令一覧を参照)
| | A簡単に実装できるループ回数は256回が上限(→20×250回×250回のように実現する)
|
|
0.5秒待つ(プログラムを作る)
|
| それではプログラムを作って見ましょう。
考え方でも説明した通り、1回で0.5秒待つ事はできませんので、3つのサブルーチンを作る事にします。
3つのサブルーチンの概要は以下のようになります。
0.5S待つサブルーチン
100mS待つサブルーチンを5回呼び出す
|
100mS待つサブルーチン
0.4mS待つサブルーチンを250回呼び出す
|
0.4mS待つサブルーチン
命令を0.4mS分実行する(1サイクル0.4μS×1000サイクル)
|
|
それぞれのプログラムは次のようになりました。
「サイクル」は、1命令実行にかかるサイクル数(1サイクルは4クロック)です。CALL命令でサブルーチンを呼び出している所は、サブルーチンが消費するサイクル数を加算しています。
「小計」は、サブルーチンが1回呼ばれた時に、各命令が実行されるサイクル数の合計です。
各サブルーチンの最後の「合計」は、サブルーチンが1回呼び出された時に実行されるサイクル数の合計です。
尚、ループ回数は上の概要と少し異なります。
; << 0.4mS待つサブルーチン >> | |
| T04mS | | | サイクル | 小計 | コメント
| | MOVLW | 0F9h | 1 | 1 | F9h=249(ループ回数として249をセット)
| | MOVWF | GPR_1 | 1 | 1
| T04LP | NOP | | 1 | 1×249=249 |
| | DECFSZ | GPR_1,F | 1(2) | 1×248+2=250 |
| | GOTO | T04LP | 2 | 2×248=496 |
| | RETURN | | 2 | 2 |
| | | | 合計 | 999サイクル(0.3996mS)
|
; << 100mS待つサブルーチン >> | |
| T100mS | | | サイクル | 小計 | コメント
| | MOVLW | 0F9h | 1 | 1 | F9h=249(ループ回数として249をセット)
| | MOVWF | GPR_2 | 1 | 1 |
| T100LP | CALL | T04mS | 2+999 | (2+999)×249=249,249 |
| | DECFSZ | GPR_2,F | 1(2) | 1×248+2=250 |
| | GOTO | T100LP | 2 | 2×248=496 |
| | RETURN | | 2 | 2 |
| | | | 合計 | 249,999サイクル(99.999mS)
|
; << 0.5S待つサブルーチン >> | |
| T05S | | | サイクル | 小計 | コメント
| | MOVLW | 05h | 1 | 1 | ループ回数5をセット
| | MOVWF | GPR_3 | 1 | 1 |
| T05LP | CALL | T100mS | 2+249,999 | (2+249,998)×5=1,249,995 |
| | DECFSZ | GPR_3,F | 1(2) | 1×4+2=6 |
| | GOTO | T05LP | 2 | 2×4=8 |
| | RETURN | | 2 | 2 |
| | | | 合計 | 1,250,013サイクル(500.005mS)
|
これで、0.5秒待つサブルーチンができました。使い方は次の通りです。
|
プログラム全体
|
| 以上でプログラムのパーツができました。それではプログラムとして完成させましょう。
これをメモ帳などのテキストエディタに取り込んで、LED2.ASMという名で保存し、MPLABでアセンブル&PICライタでPICに書き込んで動かしてみて下さい。
MPLAB,PICライタの使い方は、「3章.第1ステップ(動かしてみる) 」を参照して下さい。
緑と赤のLEDが同時に点滅すれば成功です。0.5秒毎に点滅させていますので、周期は1秒です。
なお、ソースの先頭にいくつか説明していない命令があります。
これは、最初にこのように記述して下さい。(説明は、4章(2)PICの命令とアセンブラ命令の「アセンブラ命令」を参照して下さい。)
| LIST | P=PIC16F84A | ; LIST宣言で、使用するPICをPIC16F84Aと定義する
| | INCLUDE | P16F84A.INC | ; 設定ファイルp16f84a.incを読み込む
| | __CONFIG | _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
|
GPR_1 | EQU | 0Ch | ; GPRの1バイト目にGPR_1と言う名前を付ける
| GPR_2 | EQU | 0Dh | ; GPRの2バイト目にGPR_2と言う名前を付ける
| GPR_3 | EQU | 0Eh | ; GPRの3バイト目にGPR_3と言う名前を付ける
|
|