2013.12.28
前へ
次へ
ホームページトップへ戻る

復活!CP/M ワンボードマイコンでCP/Mを!
CP/MがTK−80互換のワンボードマイコンの上で復活します
ND80ZVとMYCPU80の上でCP/Mが走ります

[第531回]


●PICサンプルプログラムの説明(割込みルーチン)

また間が2日空いてしまいました。
この2週間ほどは、ちょっと必要がありまして、私としては全く未経験の新しいことに首をつっこんでしまいましたので、なかなかホームページの更新のために時間を割くことができませんでした。
やっとめどが少しついたと思ったら、もう年の暮れも押し迫ってきてしまいました。
その新しいことにつきましては、年が明けたあたりからまたご説明することになろうかと思います。
その前に、書きかけのPICプログラムの説明を片付けてしまわなければなりません。

今回は割込みプログラムの本体について簡単に説明をいたします。
下が割込みプログラムの本体です。
サンプルプログラムの全体のリストは[第516回]にあります。

;
        org 300
;
int
     movwf savew
     swapf STATUS,w
        clrf STATUS
     movwf savests
;
     bcf STATUS,5;bank 0
        movlw 1
        xorwf PORTE,f;pulse out
        bcf T1CON,0;stop T1
        movf t1Hdata,w
        movwf TMR1H
        movf t1Ldata,w
        movwf TMR1L
        movlw 1
        movwf T1CON;start T1
intend
        clrf PIR1;***************
     swapf savests,w
     movwf STATUS
     swapf savew,f
         swapf savew,w
     retfie
;


割込みプログラムはアドレス300Hに置いてあります。
別にこのようにしなければならない理由はありません。
メインプログラムの前に置いても、途中に置いても構いません。
それではなぜ300Hに置いたかといいますと、このあと説明をする予定のテーブルアクセスとのからみで、上位8ビットが00ではないアドレスに割込みプログラムを置いた場合に、何か特別の操作が必要かどうかを確かめるためにそのようにしてみたのです。
結果から言えば、そのようにしても全く問題はありませんでした。
しかしそれはあくまでメインプログラムと同じページ内(2KB)にあれば、という前提でのお話です。
ページについては[第514回]で説明をしました。
ま、しかし、それについて追求を始めますとまた終わらなくなってしまいます。
ですのでそれについては置いておくことにいたします。
お話を元に戻しまして、テーブル参照ではアドレスの上位8ビットに注意が必要である、ということについて少し[第514回]で触れています。
しかし上に書きましたように、割込みプログラムについてはメインプログラムと同じページ内にあるのならば、特にそれを意識する必要はありません。
ただどこに割り込みプログラムを置いても、割込みプログラムへのgoto文を必ず4番地に書いておかなければいけません。

;
     org 0
st0
     goto start
;
     org 04
        goto int
;
        org 05
;
start


さてそれでは、割込みプログラムの説明です。
PICの割込みプログラムでは決ったルールがあります。
下がその先頭の部分です。
割込みプログラムを正しく実行させるためには、このように書いておかなければなりません。

;
int
     movwf savew
     swapf STATUS,w
        clrf STATUS
     movwf savests
;
 


clrf STATUSは必須ではありません。
これは必要があればこうするというだけです。
しかし割込みが発生した時点ではどのレジスタバンクが有効になっているかわからないので、大抵はSTATUSに値を与えて必要なレジスタバンクにアクセスすることになると思います。
clrf STATUS の実行によってレジスタバンク0がセレクトされます。
movwf savew
swapf STATUS,w

movwf savests
は必須です。
これは割込み発生直前のwレジスタとSTATUSの値を保存しておくためです。
ちょいと変わった書き方ですが、おまじないだと思ってください(そのわけは後ほど説明します)。
savewとsavestsはユーザーレジスタです。この名前ではなくてもどんな名前でもいいのですが、置く場所には約束事があります。
PIC16F887の場合、wレジスタとSTATUSレジスタを保存しておくためのユーザーレジスタは、アドレス70H〜7FHに置く必要があります。
このアドレスはバンク0〜バンク3まで共通にアクセスできるアドレスです([第520回]参照)。
そのようにしておかないと、割り込みが発生した直後にはどのバンクが有効になっているか分からないので、movwf savewが正しく実行されません。

;
savew equ 70
savests equ 71
;


このようにして保存したwレジスタとSTATUSレジスタは、割込みプログラムを終わるときに、これもまた決った書き方で元の値に戻します。

intend
     clrf PIR1;***************
     swapf savests,w
     movwf STATUS
     swapf savew,f
     swapf savew,w
     retfie
;


swapf savests,wからswapf savew,wまでがその部分です。
なぜこのようなややこしい書き方をするかと言いますと、movf命令を使うとフラグが変化してしまうからです。
それを防ぐためにswapf命令を使います。
movwf命令,swapf命令はフラグを変化させません。


[出典]Microchip Technology Inc. PIC16F882〜887Data Sheet

最後のretfieは割込みプログラムからメインプログラムに戻るためのリターン命令です。

clrf PIR1に****がつけてありますが、そもそもこのお話を書くことにした理由の1つがこの命令でした。
これは必ず書かなければならない命令だったのですが、うっかりして書き忘れてしまったために、プログラムが期待した通りに実行されずに、かなり悩んでしまいました。
この命令は必須です。
忘れないように注意いたしましょう。

最後は割込み処理の本体です。
ここは個々の処理によってそれぞれ必要なことを書きます。

;
     bcf STATUS,5;bank 0
        movlw 1
        xorwf PORTE,f;pulse out
        bcf T1CON,0;stop T1
        movf t1Hdata,w
        movwf TMR1H
        movf t1Ldata,w
        movwf TMR1L
        movlw 1
        movwf T1CON;start T1


今、気が付きました。
この上のところで clrf STATUS を実行していますから、bcf STATUS,5 は全く無駄な命令でした。
clrf STATUS によって、すでにバンク0がセレクトされています。

もうあと少しのところだったのですが、時間がなくなってしまいました。
この続きは次回にいたします。

ワンボードマイコンでCP/Mを![第531回]
2013.12.28upload

前へ
次へ
ホームページトップへ戻る