PIC内蔵EEPROMへのアクセス

PIC16F887で内蔵EEPROMへの読み書きができました。
といっても実作業はほとんどなしで、データシートに読み書き用の記述例があるからそのままそっくり持ってきただけですw
サンプルと変えた部分は、
・sleep命令の削除。今回はsleepしなくていい
・regというレジスタに読み書きしてきたデータを入れる
・サンプルでDATA_EE_ADDRと記述されてる部分に実際のアドレスを記述。今回はデータEEPROMの先頭の0x00


動作としては電源が入るとEEPROMの0x00から1バイトのデータを読み込んでPORTBに繋がってるLEDにそのまま出力。
その後読み込んだデータをインクリメントして同じアドレスのEEPROMへ格納。
その後は無限ループで何もしない。


これで電源をON/OFFするたびにLEDが1ずつカウントアップされていくような動作になります。
内臓のEEPROMを使う利点は何といっても電源を切ってもデータが保持されるということ。そのため上記のような動作が可能となっています。


今回戸惑ったのがANSELと汎用レジスタの扱い。
アナログポートとして動作させるか指定するANSELというレジスタが電源投入時は全て1、つまりアナログ入力とデジタルI/Oどちらにも使えるポートをアナログ入力として使うっていう設定になっています。(PIC16F887とか新しめのPICからそうなった?)
今回はデジタルOUTとして使いたいのでANSELを0にしてアナログ入力を無効にして、TRISレジスタを0にしておけば・・・と思っていたのですが全く出力されません。
そこでデータシートをよくよく読んでみると、デジタルOUTとして使いたいときはTRISレジスタは0、ANSELは1にしておくこと、とありました。
どうやらANSLEをいじるのはTRISが1(入力)の時だけみたいで、デジタルOUTの時は特に指定なしで良さそうです。


それから汎用レジスタregの扱い。
EEPROMを読み書きする際はバンク切り替えが多く発生します。そこで最初に書いたプログラムではバンク0のレジスタを指定してたためデータが意図したレジスタに入っていませんでした。これは毎回ちゃんとそのレジスタのバンクを指定するか、どのバンクからでも読める0x70以降のアドレスに配置するかで解決できました。


今回作ったプログラムを以下に書いておきます。使用PICはPIC16F887

   list      p=16f887   ; list directive to define processor
   #include   <p16f887.inc>   ; processor specific variable definitions

   __CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC
   __CONFIG    _CONFIG2, _WRT_OFF & _BOR21V

reg EQU 0x70

   org 0x2100
   de 0x00

;**********************************************************************
   ORG     0x000             ; processor reset vector

   nop
     goto    main              ; go to beginning of program

main
   bcf   STATUS,RP0         ;bank0
   bcf   STATUS,RP1

   clrf   INTCON

   banksel TRISA         ;bank change

   clrf TRISA
   clrf TRISB
   clrf TRISC
   clrf TRISD
   clrf TRISE

   bcf   STATUS,RP0         ;bank0
   bcf   STATUS,RP1

   clrf PORTA
   clrf PORTB
   clrf PORTC
   clrf PORTD
   clrf PORTE

   clrf reg

main_loop
   call read
   movfw reg
   movwf PORTB
   incf reg,f
   call write
   bsf PORTD,1
   nop
   goto $-1

read
   BANKSEL EEADR ;
   MOVLW 0x00
   MOVWF EEADR ;Data Memory
   BANKSEL EECON1 ;
   BCF EECON1, EEPGD ;Point to DATA memory
   BSF EECON1, RD ;EE Read
   BANKSEL EEDAT ;
   MOVFw EEDAT
   movwf reg
   banksel PORTA
   return

write
   BANKSEL EEADR
   MOVLW 0x00
   MOVWF EEADR ;Data Memory Address to write
   movfw reg
   MOVWF EEDAT ;Data Memory Value to write
   BANKSEL EECON1 ;
   BCF EECON1, EEPGD ;Point to DATA memory
   BSF EECON1, WREN ;Enable writes
   BCF INTCON, GIE ;Disable INTs.
   BTFSC INTCON, GIE ;SEE AN576
   GOTO $-2
   MOVLW 0x55 ;
   MOVWF EECON2 ;Write 55h
   MOVLW 0xaa ;
   MOVWF EECON2 ;Write AAh
   BSF EECON1, WR ;Set WR bit to begin write
   BSF INTCON, GIE ;Enable INTs.
   BCF EECON1, WREN ;Disable writes
   BCF STATUS, RP0 ;Bank 0
   BCF STATUS, RP1
   return

   END                       ; directive 'end of program'