前へ | 目次 | 次へ |
LEDを1mS間隔で点滅してみる |
LEDを点灯できたところで、 次はLEDを点滅させてみましょう。 |
システムのクロックとプログラム実行のクロック |
PICの命令は、4システムクロック単位で実行されます。 つまり、システムクロックが20MHzである場合には、 多くの命令が5MHzの実行クロックで動作していることになります。 ただし、分岐がある場合には、 先回りして読み込まれた命令が捨てられるために、 倍の8システムクロックを必要とします。 この性質を用いれば、プログラムから実行時間を見積もることができることになります。 割り込みなどを用いることなく、 LEDを希望する時間間隔で点滅させることができるわけです。
システムクロックが20MHzである場合には、
5MHz単位で実行されますから、
1命令は |
Wレジスタ |
Wレジスタというのは、 データの転送や演算の際に、 作業場所として利用されます。 たとえば、あるメモリに値をセットする場合には、 一旦Wレジスタに値を代入して、Wレジスタの値をメモリに転送するという方法をとったりします。 |
LEDを1mS間隔で点滅するプログラムの例 |
; LEDを点滅させる1mS 2002/04/16(Tue) LIST P=16F84 ;アセンブラにPICデバイスの情報を与える STATUS EQU H'0003' ;STATUSレジスタは3番地 RP0 EQU H'0005' ;ページ操作ビットは5bit目 PORTB EQU H'0006' ;ポートBは6番地 TRISB EQU H'0086' ;TRISBは86番地 CNT EQU H'0010' ;ワークメモリの利用 CLRF PORTB ;PORTBのポートを0にクリア BSF STATUS,RP0 ;STATUSの5ビット目を1にする(ページ1に変更) CLRF TRISB ;TRISB=0で、すべてアウトプットに設定 BCF STATUS,RP0 ;STATUSの5ビット目を0にする(ページ0に変更) LOOP BSF PORTB,7 ;PORTBの7ビット目を1にする MOVLW D'250' ;Wレジスタに250をセット MOVWF CNT ;CNTに250をセット DLY1 GOTO $+1 ;次の命令へ(クロック数稼ぎ) GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 NOP ;何もしない(クロック数稼ぎ) DECFSZ CNT,1 ;CNTが0になったら次の命令をスキップ GOTO DLY1 ;DLY1のループ BCF PORTB,7 ;PORTBの7ビット目を0にする MOVLW D'250' ;Wレジスタに250をセット MOVWF CNT ;CNTに250をセット DLY2 GOTO $+1 ;次の命令へ(クロック数稼ぎ) GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 NOP ;何もしない(クロック数稼ぎ) DECFSZ CNT,1 ;CNTが0になったら次の命令をスキップ GOTO DLY2 ;DLY2のループ GOTO LOOP END ;終了 |
プログラム解説 |
CNT EQU H'0010' ワークメモリのアドレスは(ページ0の)H'000C'からH'004F'までです。 変数などを用いたい場合に利用します。 ここでは切りが良いのでH'0010'を使いました。 LOOP これはラベルといい、 この行に名前を付けるために使います。 つまり、以後「LOOP」はこの行のことをあらわします。 GOTO文の移動先として指定しています。 MOVLW D'250' MOVLWは指定した値をWレジスタに読み込みます。 値は1バイト(8Bit)で指定します。 ここでは10進数250を指定しています。 この値は繰り返しの回数として使います。 MOVWF CNT MOVWFはWレジスタの値を指定したメモリに転送します。 ここでは10進数250をCNTに転送しています。 GOTO $+1 GOTOはプログラムの流れを変える働きをします。 指定した行へ移動します。 ここの命令は次の行へ移動するというだけのものです。 GOTOは分岐になるので、2実行クロックを要します。 ここでは、単にクロック数を稼ぐためだけに使っています。 NOP 何もしません。 タイミングの調節に使います。 1実行クロックを要します。 DECFSZ CNT,1 DECFSZは、最後に指定した値が0か1かで演算結果の格納先が異なります。 0ならばWレジスタに、1ならば指定したメモリに格納されます。 ここでは、1が指定されているので、 メモリCNTに格納されることになります。 DECFSZは、指定したメモリの値から1を引き指定したメモリもしくはWレジスタに格納します。 ここでは、最後に指定した値が1ですので、 CNTの値から1を引き、CNTに戻します。 結果が0の場合には次の行をとばします。 この命令は、次の行の命令とともに、 CNTに最初に設定された値だけ(ここでは250)ループをまわすのに利用しています。 演算結果が0でなければ1実行クロックを、 0ならば2実行クロックを要することになります。 |
ループの時間を計算する |
ループにかかる時間を計算してみましょう。
DLY1 GOTO $+1 2クロック GOTO $+1 2クロック GOTO $+1 2クロック GOTO $+1 2クロック GOTO $+1 2クロック GOTO $+1 2クロック GOTO $+1 2クロック GOTO $+1 2クロック NOP 1クロック DECFSZ CNT,1 1クロック GOTO DLY1 2クロック
このループは計20実行クロックを要することが分かります。
CNTは250ですから、このループは250回実行され、
ループを抜けるまでに、 |
実行してみる |
さて、実行してみましょう。 あれ? 点滅せずに、つきっぱなしですね。 1mSでの点滅は人間の目には識別できないのですね。 オシロスコープで見てみると、 確かに1mSごとに点滅を繰り返していることが分かります。 では、0.1Sでの点滅に書き換えてみてください。 次回では、0.1Sでの点滅を、サブルーチンを使って記述してみます。 |
2002/03/08(Sat) |
PICのトップページへ |
トップページへ |
SEO | [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送 | ||