応用情報処理Ⅰ

応用情報処理Ⅰ
アセンブラの基礎
PIC16F84Aの
内部構造
ごちゃごちゃしているが、
ざっと把握するとよし。
プログラムする側からとっ
て重要なのはフラッシュプ
ログラムメモリ(FPR)と
ワーキングレジスタ(Wreg)
初期設定等やI/Oの入出
力のためのFSRも大事か
も
フラッシュプログラムメモリ
アセンブラされたHEX
ファイルの内容がここに
ストアされる
1024命令を格納可能
(1命令14ビット)
ワークレジスタ
(Wreg)
計算動作の結果の一
時的保管や演算。
他のレジスタからコピー
したり他のレジスタへコ
ピーする。
コピー先がI/Oポートで
あれば、ポート値を読
み書きできる。
RAM
SFR(Special Function
Register)や
GPR(General Purpose
Register)からなる。
SFRではPICの設定やI/O
読み書きなどの機能が、まと
められている。
GPRを個人用レジスタ(変
数)として使える
SFRレジスタの構造
• SFR(Specifial Function Register)は
PICのI/Oポートの設定や状態を設定
したり保持できる特別用途のメモリで
ある。
• SFRはバンク0とバンク1から構成さ
れている。必要に応じて、バンクを切
り替え、必要なメモリにアクセスする。
• メモリにはこちらが書き込んでPICの
動作条件を設定するもの、PICの動
作の結果が反映され、該当メモリの
中身を読むという、両方の用途があ
る。
初期設定1
LIST P=PIC16F84A;
INCLUDE "P16F84a.INC" ;標準ヘッダ定義ファイルのインクルード
CNT1 EQU 0CH
;タイマ用変数
・・・・・・・・・・・・
初期設定2
ORG
MAIN
BSF
CLRF
CLRF
BCF
0
STATUS,RP0 ;バンク1へ切り替え
TRISA
;TRISAをクリア
TRISB
;TRISBをクリア
STATUS,RP0 ;バンク0に戻す
前処理
MOVLW 03H
MOVWF PORTA
;8列LEDを出力先に選択
メインループ
MAINLP
MOVLW 0FH
MOVWF PORTB
CALL TIMER
・・・・・・・・・・・・
GOTO MAINLP
;ポートBに出力
;少し待つ
タイマールーチン
TIM10 MOVLW 0F9H
MOVWF CNT1
TIMLP1 NOP
・・・・・・・・・・・・
RETURN
END
;1
;1+1=2
P16F84Aの中身
;----- Register Files-----------------------------------------------------INDF
TMR0
PCL
STATUS
FSR
PORTA
PORTB
EEDATA
EEADR
PCLATH
INTCON
OPTION_REG
TRISA
TRISB
EECON1
EECON2
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
H'0000'
H'0001'
H'0002'
H'0003'
H'0004'
H'0005'
H'0006'
H'0008'
H'0009'
H'000A'
H'000B'
EQU H'0081'
EQU H'0085'
EQU H'0086'
EQU H'0088'
EQU H'0089'
;----- STATUS Bits -------------------------------------------------------IRP
RP1
RP0
EQU H'0007'
EQU H'0006'
EQU H'0005'
初期設定1
「定数」の定義
LIST P=PIC16F84A
;
INCLUDE "P16F84a.INC" ;標準ヘッダ定義
ファイルのインクルード
; 変数レジスタの定義
CNT1 EQU
CNT2 EQU
CNT3 EQU
0CH
0DH
0EH
;タイマ用変数
;タイマ用変数
;タイマ用変数
GPRレジスタの構造
• アドレス0Chから4FhはGPR(General
Purpose Register)と呼ばれ、ユーザ
は変数などにつかうことができる。
• サンプルプログラムでは、0Ch、0Dh、
0Ehをタイマーカントルーチン用変数
として使用している。
CNT1 EQU 0Ch
CNT2 EQU 0Dh
CNT3 EQU 0Eh
• プログラムを格納するレジスタではな
いので注意。
初期設定2
ORG 0
MAIN
BSF
CLRF
CLRF
BCF
I/Oポートの切り替え
STATUS,RP0 ;バンク1へ切り替え
TRISA
;TRISAをクリア
TRISB
;TRISBをクリア
STATUS,RP0 ;バンク0に戻す
SFRレジスタの構造
• 例えばSTATUSレジスタをいじる時には、
SFRがバンク0になっていてもバンク1
になっていても可能である。
• これに対し、TRISAを操作するには、
SFRがバンク1の状態になっていないと
いけない。
• 同様に、PORTAをSFRがバンク0の状
態になっている必要がある。
• メモリにはこちらが書き込んでPICの動
作条件を設定するもの、PICの動作の
結果が反映され、該当メモリの中身を
読むという、両方の用途がある
SFRレジスタの構造
• 実は、TRISA(8ビット)は、PORTA(8
ビット)の対応する各I/Oを「入力にす
るか」「出力にするか」を定める。
• このため、PORTAを出力にするか入
力にするかは、まずバンク1に切り替
え、TRISAをいじる必要がある。
• この後で、バンク0に切り替え、
PORTAから実際に入出力をおこなう
ことができる。
• PORTBについても同じである。
SFRレジスタの構造
• サンプルプログラムの前処理
BSF STATUS,RP0
;バンク1へ切り替え
CLRF TRISA
;TRISAをクリア
CLRF
TRISB
;TRISBをクリア
BCF
STATUS,RP0
;バンク0に戻す
• バンクの切り替えはSTATUSレジス
タのビット0を操作しておこなう。
STATAUSレジスタは、両方のバンク
からアクセス可能なので、まずバン
ク1に切り替え、TRISAをいじり、
PORTA出力専用にしている。
• このあと、再びSTATUSレジスタをい
じり、バンクを0に戻し、PORTA、
SFRレジスタの構造
• レジスタへのアクセスは、本来はアド
レスでやるべきだが、アドレスに別名
がつけられていて、アクセスしやすく
なっている。
• 例えば、
BSF STATUS,RP0
では、STATUSは03hに、RP0は0に変
換され、結局
BSF 03h、0
が実行される。
• 別名はファイル”PIC16F84A.h"内で
定義されている。
前処理
8列LEDを出力先に選択
MOVLW 03H
MOVWF PORTA
;8列LEDを出力先に選択
MOVLW 03H
• 値O3Hをワーキングレジストリ格納する。
03H
ワーキングレジスタ
MOVWF PORTA
• ワーキングレジスタの内容をPORTAにコピーする。
• 実際にはPORTA=05H(SFRレジストリのアドレス05H)
• PORTAは「8ビットとも出力」に設定されているので、対応する8つ
のピンがON/OFFされる
ワーキングレジスタ
ワーキングレジスタ
PORTA
ポートAの役割
• ポートAは受け取った数値によって、ポートBの出力を切り替える。
• 数値
• 数値
• 数値
• 数値
00
01
10
11
->7セグ左側
->7セグ右側
->サイコロ
->8列LED
メイン処理の説明
• 中核の処理は
MAINLP
MOVLW 0FH
MOVWF PORTB
CALL TIMER
・・・・・・
GOTO MAINLP
である。
MOVLW 0FH
• 値OFHをワーキングレジストリ格納する。
0FH
ワーキングレジスタ
MOVWF PORTB
• ワーキングレジスタの内容をPORTBにコピーする。
• 実際にはPORTB=06H(SFRレジストリのアドレス06H)
• PORTBは「8ビットとも出力」に設定されているので、対応する8つ
のピンがON/OFFされる
ワーキングレジスタ
ワーキングレジスタ
PORTB
SFRレジスタの構造
• 実は、TRISA(8ビット)は、PORTA(8
ビット)の対応する各I/Oを「入力にす
るか」「出力にするか」を定める。
• このため、PORTAを出力にするか入
力にするかは、まずバンク1に切り替
え、TRISAをいじる必要がある。
• この後で、バンク0に切り替え、
PORTAから実際に入出力をおこなう
ことができる。
• PORTBについても同じである。
CALL
TIMER
• サブルーチン TIMER を呼び出す。
• 実際には現在の処理位置を保存し、TIMERラベルに処理位置が移
る。ただし、TIMERの処理が終わったら、RETURN命令で元の処理
位置に戻るようになっている。
プログラムカウン
タ(PC)とスタック
PC
現在どの命令を
実行しているか
スタック
サブルーチン(CA
LL命令など)を使
う場合、どの命令
に戻ればよいか
プログラム実行時のアドレス変化
GOTO MAINLP
• ラベルMAINLPに行け。
• 実際にはプログラムカウンタにMAINLPのアドレスをいれる。
MOVLW ドローン(配送便イメージ)
• 商品「ドローン」を配送ボックスに入れる。
MOVWF 山田
(配送便イメージ)
• 配送ボックスの中身を「アドレス」山田に配送する。
• 実際の「アドレス」を記述すると面倒なので、「アドレス」の別名を使っ
ている。
山田
EQU
東京都中野区中野6丁目
• MOVWF 山田は実際にはMOVWF 東京都中野区中野6丁目と
解釈されるわけである。
CALL 休憩処理
(配送便イメージ)
• 現在の処理を中断し、(中断した処理を覚えておけ)、休憩時間処理
を実行せよ。
• ブラックな会社では休憩時間処理も仕事の一部である。
GOTO 配送処理(配送便イメージ)
• 配送処理に行け。
配送会社イメージだとこーなる
配送処理
MOVLW ドローン
MOVWF 山田
CALL 休憩処理
MOVLW パソコン
MOVWF 山田
CALL 休憩処理
・・・・・・
GOTO 配送処理
PORTB の役割
• 住所山田=東京都中野区中央は実際には運び屋で、届いた荷物を
電車の荷だなに置いておく。
• 実際にどこ商品が伝わるかは、中野駅の状態による
前処理の説明(運送会社イメージ)
MAIN
←ラベル(実は一回も使われない)
「命令:東西」 を配送ボックスに入れる。
配送ボックスの内容を中野駅に届ける
ポートAの役割(運送会社イメージ)
• 中野駅は受け取った命令文書によって、電車の行き先をきりかえる。
• 命令:中上
• 命令:中下
• 命令:東西
• 命令:総武
->中央線上がり
->中央線下り
->東西線
->総武線
TIMERルーチン
DECFSZ命令
DECFSZ CNT3,F
•
•
アドレスCNT3に格納されている数値を1引け。
さらに、もし結果が0であれば次の命令を飛ばせ。
TIMERルーチン
TIMER MOVLW 5
MOVWF CNT3
;100msec* 5(about)
アドレスCNT3に5をいれろ。
TIMLP3 CALL TIM100
DECFSZ CNT3,F
GOTO TIMLP3
無限ループのなかでサブルーチンTIM100を呼び出している。DECFSZ CNT3で1ルー
プごとにアドレスCNT3の値を1つづ引いている
RETURN
TIMERルーチン
TIMER MOVLW 5
MOVWF CNT3
TIMLP3 CALL TIM100
;100msec* 5(about)
DECFSZ CNT3,F
GOTO TIMLP3
RETURN
• 一言でいうと、ループごとにアドレスCNT3が保持している数値が減って
いき、これが0になったとき、次のGOTO命令が飛ばされる。
すなわち、5回、サブルーチンTIM100を呼び出している。
TIM100ルーチン
TIM100 MOVLW
0F9H
MOVWF CNT2
TIMLP2 CALL TIM10
;0.4msec* 249(about)
;2+(999+2+3)*249-1=249997
DECFSZ CNT2,F
GOTO
TIMLP2
RETURN
• 一言でいうと、ループごとにアドレスCNT2が保持している数値が減って
いき、これが0になったとき、次のGOTO命令が飛ばされる。
すなわち、0F9H=249回、サブルーチンTIM100を呼び出している。
TIM100ルーチン
TIM10 MOVLW 0F9H
MOVWF CNT1
TIMLP1 NOP
DECFSZ CNT1,F
GOTO TIMLP1
RETURN
;1
;1+1=2
;1+1+ 2= 4
;2+4*249-1=997
• 一言でいうと、ループごとにアドレスCNT1が保持している数値が減っていき、こ
れが0になったとき、次のGOTO命令が飛ばされる。
一方、NOP命令は何もしない命令で、他のサブルーチンを呼
び出していない。
両方の7セグをコントロールするには?
これまで、
1.ポートAに値をセットして7セグを出力先に指定する
ループ
2.ポートBに値をセットして7セグに好みのパターンを表示
3.時間待ち
ループに戻す
とやってきた。では2つの7セグを同時にコントロールするには?
両方の7セグをコントロールするには?
案1:ループ内でポートAによる出力先切り替えをやってしまう
ループ
1.ポートAに値をセットして7セグNO1を指定する
2.ポートBに値をセットして7セグに好みのパターンを表示
3.時間待ち
4.ポートAに値をセットして7セグNO2を指定する
5.ポートBに値をセットして7セグに好みのパターンを表示
6.時間待ち
ループ終わり
うまくいくか?
両方の7セグをコントロールするには?
案2:タイマー内で表示をやってしまう
TIMER MOVLW 5
MOVWF CNT3
;100msec* 5(about)
TIMLP3 CALL TIM100
ポートAに値をセットして7セグNO!を指定する
ポートBに値をセットして7セグに好みのパターンを表示
ポートAに値をセットして7セグを指定する
ポートBに値をセットして7セグに好みのパターンを表示
DECFSZ CNT3,F
GOTO TIMLP3
RETURN
うまくいくか?
使えそうな命令
MOVF アドレス,f
アドレスアドレスの値をワーキングレジスタに書き込む
MOVF CNT3,f
アドレスCNT3に保存されている値をワーキングレジス
タに書き込む