; Copyright 2005 Yasuhiro Kanzaki ; f877A130100.asm  EEPROM,プログラムメモリ アクセステストプログラム1 list p=16f877A ; プロセッサを定義する #include ; インクルード・ファイルを読み込む __CONFIG _CP_OFF & _WDT_OFF & _HS_OSC & _LVP_OFF & _DEBUG_OFF & _CPD_OFF ; 変数定義域 ;***** LCD 変数の定義域 b2a_tmp equ 20h ;  count_str equ 21h ; LCDPORT equ PORTE ; RS equ 0 ; RW equ 1 ; E equ 2 ; ;******************************************************* ee_adrl equ 060h ; EEPROM/プログラム・メモリのアドレス・ワーク eep_adrh equ 061h ; プログラム・メモリのアドレス上位バイト eep_data equ 062h ; EEPROM/プログラム・メモリ書き込みデータ eep_datah equ 063h ; プログラム・メモリのデータ上位バイト ; ブロック書き込み 書き込みデータ・エリア pgdata1 equ 065h pgdata2 equ 066h pgdata3 equ 067h pgdata4 equ 068h pgdata5 equ 069h pgdata6 equ 06Ah pgdata7 equ 06Bh pgdata8 equ 06Ch ORG 0x000 ; リセット時の開始位置 goto main ; org 01ch main: ; WRERR EEPROMライト・エラー フラグ・ビットをクリアする 未完でライト処理が終了をチェックする場合 ; クリアする.エラー・チェックしない場合は必要ない.読み書きの処理には必須ではない bsf STATUS,RP1 bsf STATUS,RP0 bcf EECON1,WRERR bcf STATUS,RP1 bcf STATUS,RP0 ;タイマ0の初期化 bsf STATUS,RP0 ; バンク1を選択 bcf OPTION_REG,T0CS ; タイマ0 プリスケーラ256 bcf OPTION_REG,PSA ; プリスケーラはタイマ0 bcf OPTION_REG,NOT_RBPU ;ポートBプルアップ Clrf TRISD ; TRISDが0で出力,1で入力 clrf TRISE ; ポートEを出力として設定する bcf STATUS,RP0 ; バンク0を選択 movlw b'10000011' ; 右詰 AN3が+リファレンス btfss PORTB,1 ; PORTBはバンク0 movlw b'00000011' ; 左詰 AN3が+リファレンス bsf STATUS,RP0 ; ADCON1はバンク1 movwf ADCON1 ; アナログ・ポートの構成をセット bcf STATUS,RP0 ; 以上で初期設定 完了 call inilcd8 ; LCDドライバの初期化 ;タイマ1初期化 movlw 0Bh ;プリスケーラ1:1 32.768kHz ,外部クロック,同期 movwf T1CON ; タイマ1構成セット及びタイマ1オン ;表示処理 LCDの表示の準備 movlw 01h ; LCDのクリア call cmdwrt ; コマンド書き込み movlw 80h+4dh ; ADCは4dhにセット call cmdwrt ; コマンド DDRAMアドレスをセット2行目 movlw 'V' ; V プログラム・バージョンのV call dtawrt ; データ書き出し movlw 04h ; プログラム・バージョン改訂ナンバをセット call b2asub ; データ書き出し movlw 80h ; LCDの表示アドレスをセット call cmdwrt ; movlw tb14-tbl1 ; 開始メッセージを表示 call lcdstr1 ; movlw 80h+40h ; 入力位置を2行目の1桁めに設定 call cmdwrt ; ; movlw 25h ; EEPROMのアドレス 25h を読む   call eep_rd ; 読み出しのサブルーチンをCall call b2asub ; LCDに表示 9章参照 movlw 25h ; 書き込みのアドレスを25hと設定 movwf ee_adrl ; EEPROMの書き込みアドレスをワークにセット movlw 09Ah ; EEPROMへの書き込みデータをWレジスタにセット call eepwr ; EEPROMに書き込む ; movlw 25h ; 書き込んだ結果を読み出しLCDに表示する call eep_rd ; call b2asub ; movlw 00h ; プログラムメモリの1800hの内容を読み出す movwf ee_adrl ; movlw 018h ; movwf eep_adrh ; call eepgrd ; movf eep_datah,W; 読み取ったデータの上位データをLCDに表示 call b2asub ; movf eep_data,W ; call b2asub ; 読み取ったデータの下位データをLCDに表示 ; 16F877で1ワードの書き込みを行う場合 ; movlw 00h ; プログラム・メモリの 1800h ; movwf ee_adrl ; ; movlw 0018h ; ; movwf eep_adrh ; ; movlw 03h ; ; movwf eep_datah ; ; movlw 7Ah ; ; movwf eep_data ; ; call epgmwr ; call pgw7a ; 16F877Aのブロック書き込みのデータをセットし,16F877A movlw 000h ; のブロック書き込みを行う movwf ee_adrl movlw 018h movwf eep_adrh call eepgrd movf eep_datah,W call b2asub movf eep_data,W call b2asub le goto le ; リスト13−5を使用して書き込み処理を877Aで書き込むサブルーチン ; 書き込み処理 pgw7a movlw pgdata1 ; 書き込みデータのセットエリアのアドレスを取得 movwf FSR ; 間接アドレス指定を利用 movlw 038h ; 書き込みデータをセット@ movwf INDF ; 間接アドレス指定で@を書き込み incf FSR,F ; 間接指定アドレスをひとつすすめる movlw 037h ; 書き込みデータをセットA movwf INDF ; 間接アドレス指定でAを書き込み incf FSR,F ; 間接指定アドレスをひとつすすめる movlw 037h ; 書き込みデータをセットB movwf INDF ; 間接アドレス指定でBを書き込み incf FSR,F ; 間接指定アドレスをひとつすすめる movlw 027h ; 書き込みデータをセットC movwf INDF ; 間接アドレス指定でCを書き込み incf FSR,F ; 間接指定アドレスをひとつすすめる movlw 057h ; 書き込みデータをセットD movwf INDF ; 間接アドレス指定でDを書き込み incf FSR,F ; 間接指定アドレスをひとつすすめる movlw 041h ; 書き込みデータをセットE movwf INDF ; 間接アドレス指定でEを書き込み incf FSR,F ; 間接指定アドレスをひとつすすめる movlw 031h ; 書き込みデータをセットF movwf INDF ; 間接アドレス指定でFを書き込み incf FSR,F ; 間接指定アドレスをひとつすすめる movlw 041h ; 書き込みデータをセットG movwf INDF ; 間接アドレス指定でGを書き込み movlw 00h ; アドレスを設定 movwf ee_adrl ; movlw 018h ; movwf eep_adrh ; movlw pgdata1 ; movwf eep_data ; 書き込みデータ・エリアのアドレスをセット call epgwxa ; リスト13-5のサブルーチンを呼び出す return ; 0からFの4ビットの値を文字コードに変換する bacon andlw 0Fh ; 上位のビットをクリアする addwf PCL,f ;  dt "0123456789ABCDEF" ; 文字列の表示サブルーチン lcdstr1 movwf count_str strlp1 movf count_str,W call str010 andlw 0FFH btfsc STATUS,Z return call dtawrt incf count_str,f goto strlp1 str010 addwf PCL,F tbl1 dt "LCD TEST Pgm",0h tbl2 dt "debug mode",00h tbl3 dt "LM35Z TEST",00h ; 12章のテストの表示 tb14 dt "EEPROM TEST",00h ; 今回のテストの表示 ; ;タイマ処理サブルーチン0.1ms 255 tm01 bcf INTCON,T0IF ; フラグをクリア sublw 0FFh ; カウント値を計算する movwf TMR0 ; タイマ0レジスタに0ffh-カウント値をセット stmlp btfss INTCON,T0IF ; オーバ・フローを待つ goto stmlp ;   bcf INTCON,T0IF ; フラグをクリア return ; ;LCDドライバーの初期化8ビットポート inilcd8 movlw d'150' ; call tm01 ; 電源立ち上げ後15ms以上確保するため movlw 30h ; コマンド 30hを出力 call cmdwrtw ; コマンド 30hを出力 movlw d'41' ; call tm01 ; 4.1msの時間待ち movlw 30h ; call cmdwrtw ; コマンド 30hを出力 movlw 1 ; call tm01 ; 100μsの待ち movlw 30h ; コマンド 30hを出力 call cmdwrtw ; movlw 1 ; call tm01 ; 100μsの待ち movlw b'00111000' ; function set 8bit 2line call cmdwrt movlw b'00001100' ; display on/off on call cmdwrt movlw b'00000001' ; clears display call cmdwrt movlw b'00000110' ; entry mode set call cmdwrt return ; busy check LCDドライバの処理中のチェック bsychk bsf STATUS,RP0 ; バンク1を設定 comf TRISD,f ; ポートDを入力に設定のコード bcf STATUS,RP0 ; バンク0 を設定 bsf LCDPORT,RW ; コマンド読み取りなのでRでHにする bsyrp: bcf LCDPORT,RS ; コマンドなのでLでクリアする bcf LCDPORT,E ; ループで戻った時Lにするため bsf LCDPORT,E ; E信号をHにする nop ; 時間待ち btfsc PORTD,7 ; Busy フラグのチェック goto bsyrp ; フラグがオンの時繰り返す bcf LCDPORT,E ; E信号をLにする bcf LCDPORT,RW ; WRITEに変更 bsf STATUS,RP0 ; バンク1を設定 clrf TRISD ; ポートDを出力に設定 bcf STATUS,RP0 ; バンク0 を設定 return ; 一バイトデータの値をHEX表示でLCDに書き込む b2asub movwf b2a_tmp ; 表示データを保存 swapf b2a_tmp,w ; 上下のニブルを入れ替え call bacon ; 下位4ビットを 文字コードに変換 call dtawrt ; 変換されたデータをLCDに出力 movf b2a_tmp,w ; 保存したデータをWレジスタにセット call bacon ; 下位4ビットを 文字コードに変換 call dtawrt ; 変換されたデータをLCDに出力 return ; ;コマンド書き込みルーチン cmdwrt call bsychk ; Busyフラグがオフまで待つ cmdwrtw bcf LCDPORT,RW ; WRITEでL bcf LCDPORT,RS ; コマンドでRSはL movwf PORTD ; ポートDにコマンドを出力 bsf LCDPORT,E ; Eをオン bcf LCDPORT,E ; Eをオフ return ; ; 文字コードをデータとしてLCDに書き込む,文字が表示される dtawrt: call bsychk ; Busyフラグがオフまで待つ bcf LCDPORT,RW ; WRITEでL bsf LCDPORT,RS ; データでRSはH movwf PORTD ; データを出力 bsf LCDPORT,E ; Eをオン bcf LCDPORT,E ; Eをオフ return ;リスト13-1 eep_rd bsf STATUS,RP1 ; bcf STATUS,RP0 ; movwf EEADR ; bsf STATUS,RP0 ; bcf EECON1,EEPGD; bsf EECON1,RD ; bcf STATUS,RP0 ; movf EEDATA,W ; bcf STATUS,RP1 ; return ; リスト13-2 ; EEPROMに書き込む eepwr bsf STATUS,RP1 ; bcf STATUS,RP0 ; movwf EEDATA ; bcf STATUS,RP1 ; movf ee_adrl,W; bsf STATUS,RP1 ; movwf EEADR ; bsf STATUS,RP0 ; ; bcf EECON1,WRERR bcf EECON1,EEPGD; bsf EECON1,WREN ; movlw 55h ; movwf EECON2 ; movlw 0AAh ; movwf EECON2 ; bsf EECON1,WR ; wr_lp btfsc EECON1,WR; goto wr_lp ; bcf EECON1,WREN ; bcf STATUS,RP0 bcf STATUS,RP1 return ;リスト13-3 eepgrd bcf STATUS,RP0 ;  bcf STATUS,RP1 ; バンク0選択  movf ee_adrl,W ; アドレス下位取り出す bsf STATUS,RP1 ; バンク2選択 movwf EEADR ; 下位アドレスセット bcf STATUS,RP1 ; バンク0選択  movf eep_adrh,W ; アドレス上位取り出す bsf STATUS,RP1 ; バンク2選択 movwf EEADRH ; 上位アドレスセット bsf STATUS,RP0 ; バンク3選択 bsf EECON1,EEPGD; プログラム・メモリ選択 bsf EECON1,RD ; 読み込みスタート nop ; 読み込み完了まで2命令サイクル必要 nop ; この期間の命令は全て無視されNOPとなる bcf STATUS,RP0 ; バンク2を選択 movf EEDATA,W ; 下位バイト取り出す bcf STATUS,RP1 ; バンク0選択 movwf eep_data ; bsf STATUS,RP1 ; バンク2選択 movf EEDATH,W ; 下位バイト取り出す bcf STATUS,RP1 ; バンク0選択 movwf eep_datah ; return ; リスト13-4 ; PGMメモリに書き込む(877) epgmwr bcf STATUS,RP0 ;  bcf STATUS,RP1 ; バンク0選択 movf eep_data,W ; bsf STATUS,RP1 ; バンク2を選択 movwf EEDATA ; 下位バイトセット bcf STATUS,RP1 ; バンク0選択 movf eep_datah,W; 上位バイトを取り出す bsf STATUS,RP1 ; バンク2選択 movwf EEDATH ; 上位バイトをセット bcf STATUS,RP1 ; バンク0選択 movf ee_adrl,W ; 下位アドレスを取り出す bsf STATUS,RP1 ; バンク2をセット movwf EEADR ; 下位アドレスをセット bcf STATUS,RP1 ; バンク0を選択 movf eep_adrh,W ; 上位アドレスを取り出す bsf STATUS,RP1 ; バンク2を選択 movwf EEADRH ; 上位バイトをクリア bsf STATUS,RP0 ; バンク3を選択 bsf EECON1,EEPGD; プログラムメモリをアクセス EEPGD=1  bsf EECON1,WREN ; 書き込み可を設定 movlw 55h ; 書き込みシーケンス movwf EECON2 ; movlw 0AAh ; movwf EECON2 ; bsf EECON1,WR ; 書き込み開始 nop ; 内部処理のため停止 nop bcf EECON1,WREN ; 書き込み禁止にする bcf STATUS,RP0 ; バンク0に設定 bcf STATUS,RP1 ; return ; ; リスト13−5 XAのブロック書き込み対応のプログラム・メモリ書き込みサブルーチン epgwxa bcf STATUS,RP0 ;  bcf STATUS,RP1 ; バンク0選択 movf ee_adrl,W ; 下位アドレスを取り出す bsf STATUS,RP1 ; バンク2をセット movwf EEADR ; 下位アドレスをセット bcf STATUS,RP1 ; バンク0を選択 movf eep_adrh,W ; 上位アドレスを取り出す bsf STATUS,RP1 ; バンク2を選択 movwf EEADRH ; 上位バイトをセット   ; 以上でスタートアドレスセット完了 bcf STATUS,RP1 ; バンク0を選択 movf eep_data,W; 書き込みデータのセット・エリアの先頭アドレスを取り出す bsf STATUS,RP1; バンク2を選択 movwf FSR ; 間接アドレスのインデックス設定 pglp movf INDF,W ; 書き込みデータをゲット movwf EEDATA ; 下位バイトセット incf FSR,F ; 次の書き込みデータのアドレスとする movf INDF,W ; 上位バイト書き込みデータをゲット movwf EEDATH ; 上位バイトをセット incf FSR,F bsf STATUS,RP0 ; バンク3を選択 bsf EECON1,EEPGD; プログラム・メモリをアクセス EEPGD=1  bsf EECON1,WREN ; 書き込み可を設定 movlw 55h ; 書き込みシーケンス movwf EECON2 ; movlw 0AAh ; movwf EECON2 ; bsf EECON1,WR ; 書き込み開始 nop ; 内部処理のため停止 nop bcf EECON1,WREN ; 書き込み禁止にする bcf STATUS,RP0 ; バンク2を選択 incf EEADR,F movf EEADR,W andlw 003h btfss STATUS,Z goto pglp bcf STATUS,RP0 ; バンク0に設定 bcf STATUS,RP1 ; return end