PICの使い方の「コツ」

【ハードウェアに関するもの】

 注意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ビットしかアドレスに反映されない。


目次ページへ