注意1:動作はしているようだが不安定、手で触ると止まったり動いたり。
MCLR端子のプルアップ忘れ。MCLRは抵抗でプルアップ
しなくても動いてしまうこともあるが、本来ダイオードでVss
にクランプされているのでプルアップ(5K〜20K)が必須。
注意2:RA4ピンは入力で使う時にもプルアップが必要。
RA4はシュミットバッファで受ける内部回路になっているので
一見入力の時にはそのまま接続しても良いように見えますが間違
いで、必ずプルアップをしないと常にLレベルでの入力となって
しまいます。(5K〜20Kオーム)
注意3:PORT Bを入力に使う時には内部プルアップをONとする。
内部プルアップをONにするには、OPTIONレジスタの
Bit7に”0”をセットする。指定は8ポート分一括である。
しかし出力に指定したポートは自動的に内部プルアップはOFF
となるので支障ない。
注意4:PORT A,Bの各ポートの入力/出力の指定は レジスタ
TRIS A,Bで指定する。”0”で出力、”1”で入力。
注意3、4を実際にプログラムで行うには下記のようにする。
BSF STATUS,RP0 ;ページ1を指定
CLRF TRISA ;PortAは全て出力
MOVLW 0F0H ;PortBの上位は入力
MOVWF TRISB ;下位は出力
BCF OPTION_REG,NOT_RBPU ;PORTBプルアップON
BCF STATUS,RP0 ;ページ0に戻る
注意5:EEPROMの書き換え回数寿命。
プログラムエリアは最低100回、データエリアは最低10万回
の保証である。しかしデータエリアを通常のプログラム変数領域
として使うと10万回は直ぐ使い切ってしまい寿命が来てしまう
ので、特別に電源断後の次回起動時にそのデータを使いたいとい
うような目的で使うのが本来の使い方です。
注意6:ROM書込み時にはConfigの書込みも忘れずに
プログラムをROMライタでPICに書き込む際、Configのレジスタも
忘れずに書き込まないと、水晶発振子が正常に発振しないなどの
不安定な状態となってしまいます。
注意1:定数減算命令「SUBLW k」は「k−w->w」を実行する。
Z80等のアセンブラと逆なので要注意。
ちなみに「SUBWF f,d」は「f−w->d」を実行する。
さんざん悩んだ挙句がこれだったりする厳重注意。
さらに結果のCフラグは"0"のとき負で"1"の時正であり通常と
これも逆なので要注意。
注意2:「MOVF f、d」はZフラグに影響する。
レジスタ内容を持ってくるだけの積もりが、Zフラグも変わって
しまう。Zフラグを分岐判定に使うときには厳重注意。
逆にdを"1"とすればfレジスタのゼロテストができ便利です。
注意3:TRISやOPTIONレジスタの指定時のアセンブラの
WARNINGメッセージが出ないようにするには。
アセンブラでIMPORTする標準ライブラリ(P16c84.inc)の一部を
下記の様に書き換える。
OPTION_REG EQU H'0081' H'0001
TRISA EQU H'0085' H'0005
TRISB EQU H'0086' → H'0006
EECON1 EQU H'0088' H'0008
EECON2 EQU H'0089' H'0009
注意4:割込み処理でフラグの待避を忘れないこと。
割込み処理に入った所でフラグを待避しておかないと、割込み
の都度結果が変化するという不安定な現象として現れる。
フラグの待避の具体的プログラミング方法は下記。
INT_ROUTINE
movwf WORK_REG ;Wレジスタの退避
swapf STATUS,W
movwf WORK_STATE ;ステータスレジスタの退避
・・・・・
・・・・・(割込みに関する処理)
・・・・・
swapf WORK_STATE,W
movwf STATUS ;ステータスレジスタの復帰
swapf WORK_REG
swapf WORK_REG,W ;Wレジスタの復帰
retfie ;割込み処理完了リターン
注意5:プログラム中の変数として使えるレジスタエリアは
ページ0のアドレス$0C〜$2Fまでの36バイト。
アドレス$00〜$0Bまでは各種設定用のレジスタとして
確保されているので、汎用の変数領域として使えるのは上記
範囲のみ。普通はプログラムの最初に変数領域として下記の
様に定義しておく。
WORK1 EQU $0C ;WORK1のアドレス定義
WORK2 EQU $0D ;WORK2のアドレス定義
・・・・・・
注意6:EEPROMデータメモリエリアへのリード/ライト
PIC16C84には64バイトのEEPROMデータメモリが内蔵
されている。ここに書かれたデータは電源がOFFとなっても
消えることは無い。しかし注意が必要なのは、リード/ライト
に特別な手順が必要であることと、ライトには約10msec
という時間がかかる事です。
リード/ライトの具体的なコーディングは下記のようにします。
サブルーチン形式としてあるのでそのまま使っても大丈夫です。
;*********************************
; Read/Write to EEPROM
;*********************************
RD_EEPROM
MOVF E_ADRS,W ;データエリアのアドレス指定
MOVWF EEADR ;Set address register
BSF STATUS,RP0 ;Set to page 1
BSF EECON1,RD ;Start read
BCF STATUS,RP0 ;Return to page 0
MOVF EEDATA,W ;Wレジスタにデータ取り出し
RETURN
WR_EEPROM
BCF STATUS,RP0 ;Set to page 0
MOVF E_ADRS,W ;データエリアのアドレス指定
MOVWF EEADR ;Address set
MOVF E_DATA,W ;書き込むデータ
MOVWF EEDATA ;Data set
BSF STATUS,RP0 ;Set to Page 1
BSF EECON1,WREN ;Set WR Enable
MOVLW 55H ;Write Sequence
MOVWF EECON2 ;Start write
MOVLW 0AAH
MOVWF EECON2
BSF EECON1,WR ;Go write
WR_LP ;書き込み確認待ちループ
BTFSC EECON1,WR ;Check Write end
GOTO WR_LP
BCF STATUS,RP0 ;Return to page 0
RETURN
(注)E_ADRSとE_DATAは変数です。
注意7:スタックの深さは8レベルまで。
これはCALL命令と割込みによるジャンプ時にスタックエリア
に戻り番地を保存します。従って、飛び先の中でさらにCALL
命令を使うという入れ子は8レベルまでという制限があるので
注意。(要はサブルーチンからさらにサブルーチンへということ
を余り深くするなということ)
注意8:バイナリコードから7セグメントへの変換
7セグメントLEDを直接PICのポートからドライブする場合に
内部演算をバイナリで実行し結果を出力する時の変換サブルーチンです。
本例はポートBのビット1から7へ出力しビット0は使わないものと
しています。
サブルーチンを呼ぶ前にWレジスタに値をロードしておきます。
帰りにはWレジスタに7セグメント用の出力データが出てきます。
またデータが0でしかもブランキングの指定がある場合には全ビット
OFFつまりブランクが返されます。
__________
| PB0 |--- NOT USE
| PB1 |--- a
| | | | 7SEGMENT LED
| PB7 |--- g
|___________|
;*************************************************
; Convert Binary to 7SEG Code
; Display PORT B is shifted 1 bit to left,
; then data is shifted 1 bit left
;*************************************************
GET_7SEG
BTFSS BLANK,0 ;BLANK flag check
GOTO NOTBLNK
ANDLW 0FH ;Mask upper 4bits
BTFSC STATUS,Z ;0 check
RETLW 0 ;BLANK return
BCF BLANK,0 ;BLANK flag reset
NOTBLNK
ANDLW 0FH ;Mask upper 4bits
ADDWF PCL,F ;Add to PC reg
RETLW B'01111110' ;Code 0
RETLW B'00001100' ;Code 1
RETLW B'10110110' ;Code 2
RETLW B'10011110' ;Code 3
RETLW B'11001100' ;Code 4
RETLW B'11011010' ;Code 5
RETLW B'11111010' ;Code 6
RETLW B'00001110' ;Code 7
RETLW B'11111110' ;Code 8
RETLW B'11001110' ;Code 9
RETLW B'10000000' ;Code A
RETLW B'10000000' ;Code B
RETLW B'10000000' ;Code C
RETLW B'10000000' ;Code D
RETLW B'10000000' ;Code E
RETLW B'10000000' ;Code F
注意9:BSF,BCF命令の使い方の注意
BSF、BCFでポートの出力をする場合、例えば、BSF POTRB,RB0
という命令を実行すると実際の動作は下記手順で実行されます。
・まずポートBの全ビットをCPUに読み込む
・CPUでビット0に1をセットする演算をする
・演算結果をポートBに出力する
つまり出力する前に入力を実行します。その時、たまたま出力電圧
が低い負荷の場合(トランジスタの直接ドライブの様な場合)には
出力にHighを出していても約0.7V程度にしかならないため、その
ポートを入力するとLowとみなしてしまいます。従って、演算結果
を出力する時にLowとして再セットするため、Highを出力していた
直接関係無いビットが突然 Low となってしまうという誤動作となっ
てしまいます。
これを避けるには、MOVWF命令で常に意識して同時に出力してやる
ことが必要です。
注意10:間接アドレス指定の使い方の注意
間接アドレスを使うとき、アドレスを演算で求める時には、演算結果は
8ビットしかアドレスに反映されない。