; Copyright 2005 Yasuhiro Kanzaki ; Filename: PIC110SSP.asm * list p=16f877A ; プロセッサを定義する #include ; インクルードファイルを読み込む __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC& _LVP_OFF & _CPD_OFF w_temp equ 70h ; 汎用レジスタをWレジスタの保存用に定義 status_temp equ 71h ; 汎用レジスタをSTATUSレジスタ保存用に定義 fsr_temp equ 72h ; FSR間接アドレス指定を行うのでFSRレジスタも保存する tempw equ 7Ah ; 汎用一時保存用のワーク・エリア(割り込み処理内では使用しない) temp_c equ 7Bh workn equ 7Ch tempw1 equ 7Eh ; 一時ワークファイル data1 equ 40h data2 equ 41h data3 equ 42h data4 equ 43h ; datao1 equ 44h datao2 equ 45h s_p equ 2eh ; 受信バッファの書き込みポインタ e_p equ 2fh ; 受信バッファの読み取りポインタ b2a_tmp equ 20h count_str equ 21h LCDPORT equ PORTE RS equ 0 RW equ 1 E equ 2 ;********************************************************************** ORG 000h ; リセット時の開始アドレス goto main ;割り込み処理ルーチン ORG 0x004 ; 割り込み処理の開始アドレス movwf w_temp ; Wレジスタを保存 movf STATUS,w ; STATUSレジスタの保存のためWレジスタへ移す movwf status_temp ; STATUSレジスタを保存 movf FSR,w ; 間接アドレス・インデックス  movwf fsr_temp ; FSRの保存 bcf STATUS,RP0 ; バンク0指定 btfsc PIR1,RCIF ; 受信割り込みかチェック call rx_data ; 受信割り込み時は受信処理に movf fsr_temp,w ; ほかの処理が無いので以後保存レジスタの回復処理 movwf FSR ; movf status_temp,w ; movwf STATUS ; STATUSレジスタの回復 swapf w_temp,f ; STATUSレジスタに影響を与えないためswapf命令を利用 swapf w_temp,w ; Wレジスタを回復 retfie ; 割りこみ処理を終えメイン・ルーチンに戻る rx_data ; リング・バッファへデータを書き込む incf s_p,f ; 受信データがあり書き込みポインタをカウント・アップ movf s_p,w ; Wレジスタにセット sublw 040h ; 上限超えか? btfss STATUS,Z ;  goto jamprx1 ; movlw 30h ; 上限超えの場合先頭に戻る movwf s_p ; jamprx1 movf s_p,w ; movwf FSR ; 読み取りアドレスを間接アドレス・レジスタで指定 movf RCREG,w ; 受信データを読み取る movwf INDF ; 受信データを間接アドレス指定で書き込む bcf PIR1,RCIF ; 受信割り込みフラグをクリア return ; 初期化ルーチンLCD関連の初期化 main bcf STATUS,RP0 ; バンク0を選択 clrf PORTD ; PORTDレジスタをクリアして0とする clrf PORTE ; ポートEの出力をクリア banksel TRISD ; バンク1を選択 clrf TRISD ; ポートDを出力として設定する clrf TRISE ; ポートEを出力として設定する movlw 04h ; ポートA,ポートEの設定 movwf ADCON1 ; アナログ入力,ディジタル入力の設定レジスタ ;タイマ0の初期化 bsf STATUS,RP0 ; バンク1を選択 bcf OPTION_REG,T0CS ; タイマ0 プリスケーラ256 bcf OPTION_REG,PSA ; プリスケーラはタイマ0 bcf STATUS,RP0 ; 以上で初期設定 完了 call inilcd8 ; LCDドライバの初期化 bcf STATUS,RP0 ; USART 初期化処理 movlw 30h ; 30h〜3Fhの16バイトのエリアを受信バッファとする movwf s_p ; 受信バッファのポインタの初期化 movwf e_p ; bsf STATUS,RP0 ; バンク1 movlw D'32' ; 10MHz 19.2kボーを設定 movwf SPBRG ; ボーレート設定レジスタ bsf TXSTA,BRGH ; ボーレート・ハイを設定 bsf TXSTA,TXEN ; 送信イネーブル bcf STATUS,RP0 ; バンク0 bsf RCSTA,SPEN ; シリアル・ポート・イネーブル bsf RCSTA,CREN ; 連続受信イネーブル ;割り込み処理設定 bcf STATUS,RP0 ; バンク0 bsf INTCON,GIE ; 全体の割り込み処理を許可 bsf INTCON,PEIE ; 周辺装置からの割り込み処理を許可 bsf STATUS,RP0 ; バンク1 bsf PIE1,RCIE ; CCP1の割り込みフラグをクリア bcf STATUS,RP0 ; バンク0に戻す ;表示処理 デバッグ時にはチェックしたいレジスタの値などは b2asubなどを使い表示する movlw 01h ; LCDのクリア call cmdwrt ; コマンド書き込み movlw 80h+4dh ; ACは4dhにセット call cmdwrt ; コマンド DDRAMアドレス・セット2行目 movlw 'V' ; V プログラム・バージョンのV call dtawrt ; データ書き出し movlw 35h ; バージョン・ナンバをセット call b2asub ; HEX表示で書き出し movlw 80h+0h ; アドレスをセット  call cmdwrt ; 入力アドレスを1行目の先頭 ; SSPモジュールの初期化 call sspinit ; SSPモジュールを I2Cで初期化 ; キー入力処理 ; movlw 'C' ; call dtawrt inploop call get_rd ; パソコンからのキーボード入力チェック btfsc STATUS,Z ; Z=0なら受信データあり goto inploop ; データ受信まで繰り返す movwf tempw ; 受信データを汎用レジスタに一時保存 sublw 0Dh ; パソコンからenterキー(0Dh)の入力で開始 btfss STATUS,Z ; goto inploop ; 0DHの入力まで繰り返す movf tempw,w ; キー入力データを返送するためワーク・エリアにセット call usdttx ; USART経由で返送 cmd1 movlw epdms1-tbl1; PCの画面表示するオープニング・メッセージのアドレスをセット call htstr1 ; PCのハイパーターミナルへオープニングメッセージ表示 cmdlp1 call get_rd ; データをリング・バッファから取り出す btfsc STATUS,Z ; キー入力の有無チェック   goto cmdlp1 ; 入力データがあるまで繰り返す call usdttx ; 入力データをUSART経由で返送,PCに表示(エコーバック) call cmdanly ; 入力データをコマンド解釈ルーチンでチェック goto cmd1 ; 次のコマンドの入力を待つために繰り返す ; 0からFの4ビットの値を文字コードに変換する bacon andlw 0Fh ; 上位のビットをクリアする addwf PCL,f ;  dt "0123456789ABCDEF" ; USARTで文字列送信  LCDの文字列表示処理の出力を USART経由でPCのハイパーターミナルへ出力   htstr1 bcf STATUS,RP0 ; バンク 0を選択 movwf count_str ; 文字列中の表示文字位置を示す値をカウンタにセット strlp2 movf count_str,W ; 最初は表示文字列の先頭の文字列の相対アドレスがセットされている call str010 ; 文字列を取り出すサブルーチンを呼び出す(LCDの表示で作成) andlw 0FFH ; 取り出したコードが00hの場合文字列の終わり btfsc STATUS,Z; 00hのチェックにandlw 0FFhを使用 00hならZフラグがセット return ; 文字列を取り出し送信が終了 call usdttx ; PCへの送信ルーチンで文字列を送信 incf count_str,f ; 文字の位置を示すカウンタをカウント・アップ goto strlp2 ; 終わりまで繰り返す ; 文字列の表示サブルーチン(LCD) lcdstr1 bcf STATUS,RP0 ; バンク 0を選択 movwf count_str; 文字列中の表示文字位置を示す値をカウンタにセット strlp1 movf count_str,W ; 最初は表示文字列の先頭の文字列の相対アドレスがセットされている call str010 ; 文字列を取り出すサブルーチンを呼び出す andlw 0FFH ; 取り出したコードが00hの場合文字列の終わり btfsc STATUS,Z; 00hのチェックにandlw 0FFhを使用 00hならZフラグがセット return ; 文字列取り出し送信が終了 call dtawrt ; LCDへ文字を表示するルーチンを呼び出す incf count_str,f ; 文字の位置を示すカウンタをカウントアップ goto strlp1 ; 終わりまで繰り返す str010 addwf PCL,F tbl1 dt "LCD TEST Pgm",00h ; これ以後に文字列をセットする tbl2 dt "debug mode",00h ; このサブルーチンはアドレスが00からFFhまでの間にセットしないとエラーとなる lsspst dt "st:",00h lsspc1 dt "sc:",00h lsspc2 dt "s2:",00h epdms1 dt 0dh,"edp>",00h epdmse dt 0Dh,"write>",00h epdmsr dt 0Dh,"read>",00h epdads dt 0Dh,"address>",00h epdds dt 0Dh,"setadr>",00h ; コマンド解釈ルーチン ; "e"は本来'e',"e"と記述しても1文字の文字列として解釈され同等になる ; PCから送られてきたキー入力データをチェックしそれぞれ指定した処理ルーチンを呼び出す cmdanly movwf tempw ; 受け渡された,入力データを保存する sublw "e" ; PICには比較命令が無いので引き算して0なら一致として処理する btfss STATUS,Z ; 一致したらZフラグがセット goto cmd2 ; 一致しなかったので次のチェック call cmde ; e コマンドの処理のサブルーチンを呼び出す return ; コマンドの処理を終えたらメインに戻る cmd2 movf tempw,w ; 引き算で元のデータが変わったためもう一度入力データを取り出す, sublw "r" ; r のコマンドかチェックする btfss STATUS,Z ; フラグのチェック goto cmd3 ; 一致しないので次に call cmdr ; EEPROMのデータを読み込む処理のサブルーチンを呼び出す cmd3 movf tempw,w ; 引き算で元のデータが変わったためもう一度入力データを取り出す, sublw "a" btfss STATUS,Z ; フラグのチェック goto cmd4 ; 一致しないので次に call cmdadset ; EEPROMのデータを読み込む処理のサブルーチンを呼び出す cmd4 movf tempw,w ; 引き算で元のデータが変わったためもう一度入力データを取り出す, sublw "d" btfss STATUS,Z ; フラグのチェック goto cmd5 ; 一致しないので次に call cmdar ; EEPROMのデータを読み込む処理のサブルーチンを呼び出す cmd5 return ; 同様に新しいコマンドを設定して容易に処理を追加できる ; EEPROMからI2C経由でメモリデータを読み取る ; プログラムを簡単にするために,書き込むアドレスをサブルーチンの中で設定している cmde ; キー入力データを書き込む movlw epdmse-tbl1; write> を表示する文字列表示のサブルーチンを呼ぶ call htstr1 ;  movf datao1,W call b2attx movf datao2,W call b2attx movlw ':' call usdttx call strc ; スタート・コンディション call addsnd ; アドレスデータ送信 1010000+0 ; movlw 01h ; 上位アドレスをセット  movf datao1,w call sdax ; 送信 ; movlw 4Ch ; 下位アドレスをセット.異なったアドレスを対象とする場合はここで上位,下位アドレスを変更する movf datao2,W call sdax ; 下位アドレスを変更する cmdelp call get_rd ; キーボードからの入力を待つ btfsc STATUS,Z;   goto cmdelp ; キー入力があるまで繰り返す movwf tempw ; 入力データをワーク・エリアに保存する  call usdttx ; パソコンに返送する movf tempw,w; ワーク・エリアからキー入力データを取り出す sublw 0dh ; エンタ・キーかチェック エンタ・キーなら終了とする btfsc STATUS,Z goto cmdeend; エンタ・キーなら終了とする movf tempw,w; ワーク・エリアからキー入力データを取り出す call sdax ; EEPROMに書き込みデータとして送信する goto cmdelp ; 0dh(改行)キーが入力されるまで繰り返す cmdeend movf tempw,w; 入力キー(0dh)を取り出す call sdax ; EEPROMに送信 call stpcon ; ストップ・コンディションを開始し,通信を終える bcf STATUS,RP0; バンク0を選択 movlw d'150'; 内部書き込みの時間待つ call tm01 ; 運用によっては省いても良い,キー入力 return ; 書き込み処理を終える ; EEPROM 読み取り ; プログラムを簡単にするために,読み取るエリアの開始アドレス,読み取るデータの数をサブルーチンの中で指定している cmdr movlw epdmsr-tbl1; read> を表示する文字列表示のサブルーチンを呼ぶ call htstr1 ;  movf datao1,W call b2attx movf datao2,W call b2attx movlw ':' call usdttx call strc ; スタート・コンディション開始 call addsnd ; アドレス・データ送信 movf datao1,W ; movlw 01h ; 読み取りエリアの開始上位アドレス.変更する場合これを変更する call sdax ; 上位アドレス送信 movf datao2,W ; movlw 4Ch ; 下位アドレスをセット.変更する場合これを変更 call sdax ; movlw 80h+41h ; LCDのアドレスをセット  ; call cmdwrt ; LCDコントローラをセット,2行目から表示 ;繰り返しスタート call rstrc ; 繰り返しスタート,アドレス書き込み後,メモリの値を読み取るため call addsndr; 繰り返しスタート時のアドレス送信処理を行う,R/-Wビットが0になっている movlw d'128'; 読み取るデータの数をセット,変更する場合この値を変更する,実際の受信データの数-1をセット movwf temp_c; 読み込み数を一時保存 cmdrlp call sdar ; データ受信 movwf tempw ; 受信データを保存 call usdttx ; 読み取ったデータをPCに送信,ハイパーターミナルの画面に表示される decfsz temp_c,f;読み取る数のカウンタをカウントダウン 0になったら終わり goto cmdrlp cmdend call lsdar ; 最後のデータを受信 NACK(Not ACK)を返すため movwf tempw ;   call usdttx ;  call b2asub ;  call stpcon ; return ; ; cmdadset movlw epdads-tbl1; アドレス読み取りのプロンプト表示 call htstr1 ; USART経由で文字列の表示   bcf STATUS,RP0 bcf STATUS,RP1 movlw 04h ; アドレスは4桁のHEX表示,文字で入力 movwf workn ; 入力文字数のカウンタ movlw data1 ; data1のアドレスを取り出す movwf FSR ; 間接アドレス指定の為data1のアドレスをセット movwf tempw1 cmdalp call get_rd ; キーボードからの入力を待つ btfsc STATUS,Z;   goto cmdalp ; キー入力があるまで繰り返す movwf tempw ; 受信データを保存 movf tempw1,W movwf FSR movf tempw,w movwf INDF ; call b2asub ; デバッグ用で,必要な時に活かして確認する call usdttx ; 読み取ったデータをPCに送信,ハイパーターミナルの画面に表示される movf tempw,W;  incf FSR,F movf FSR,W movwf tempw1 decfsz workn,F goto cmdalp call d4set return ; ;設定したアドレスの読み取り処理 cmdar movlw epdds-tbl1; アドレス表示のプロンプト call htstr1 ; USART経由で文字列の表示  movf datao1,W call b2attx movf datao2,W call b2attx ; movf data1,W ; データの確認のためテスト時には表示する ; call b2attx ; cmdarで正しくデータがセットされたか確認するために用意した(初版で ; movf data2,W ; はcmdaとあるが正しくはcmdar) ; call b2attx ; movf data3,W ; call b2attx ; movf data4,W ; call b2attx return ;SSP I2C マスター設定  初期化処理 sspinit movlw 028h ; SSPEN をON マスタ・モード banksel SSPCON ; movwf SSPCON ; 初期値設定 movlw d'24' ; クロック 100kHzの場合 ; movlw d'2' ; 1.25MHzの場合(動作確認のためテストを行い正常に動作した) banksel SSPADD ; SSPADDのバンクを選択 movwf SSPADD ; ボーレートの設定完了 movlw 080h ; サンプル・ビット標準モード 100KHz 1MHz banksel SSPSTAT movwf SSPSTAT ; SSPSTATレジスタをセット banksel TRISC ; ポートCのI2Cで使用するディジタルI/Oの入力設定 bsf TRISC,3 ; SCL ディジタル・ポートを入力に設定 bsf TRISC,4 ; SDA ディジタル・ポートを入力に設定 bcf STATUS,RP0 return ; スタート・コンディション strc bcf SSPCON,WCOL ; 書き込み banksel SSPCON2 ; bsf SSPCON2,SEN ;スタート・コンディションを開始する banksel SSPCON ; btfsc SSPCON,WCOL ; goto strc ; banksel SSPCON2 ; bsf SSPCON,SEN ; coplchk btfsc SSPCON2,SEN ; スタート・コンディションの完了チェック goto coplchk ; return ; 繰り返しスタート・コンディション 繰り返しスタート rstrc bcf PIR1,SSPIF ;   banksel SSPCON2 ;  bsf SSPCON2,RSEN; 繰り返しスタート開始ビットをセット rstrclp btfsc SSPCON2,RSEN ; 完了まで待つ goto rstrclp bcf STATUS,RP0 return ; アドレス送信 & Write addsnd movlw b'10100000' banksel SSPBUF ;  movwf SSPBUF bcf PIR1,SSPIF adrep1 btfss PIR1,SSPIF goto adrep1 return ; アドレス送信 & Read addsndr movlw b'10100001' banksel SSPBUF movwf SSPBUF bcf PIR1,SSPIF adrep2 btfss PIR1,SSPIF goto adrep2 return ; データ送信 sdax bcf STATUS,RP0 ; バンク0を選択 bcf PIR1,SSPIF ; 割り込みフラグをクリア movwf SSPBUF ; 送信データをセット sdaxrp btfss PIR1,SSPIF; 完了後 goto sdaxrp ; 割り込みフラグONを待つ return ; マスタのデータ受信処理 sdar bcf PIR1,SSPIF ; データ受信 banksel SSPCON2 bsf SSPCON2,RCEN sdarlp1 btfsc SSPCON2,RCEN goto sdarlp1 bcf SSPCON2,ACKDT bsf SSPCON2,ACKEN sdarlp2 btfsc SSPCON2,ACKEN goto sdarlp2 banksel SSPBUF movf SSPBUF,W return ; 最終データ受信として NACKを返す.それ以外は sdar と同一 lsdar bcf PIR1,SSPIF banksel SSPCON2 bsf SSPCON2,RCEN sdarlp5 btfsc SSPCON2,RCEN goto sdarlp5 bsf SSPCON2,ACKDT bsf SSPCON2,ACKEN sdarlp6 btfsc SSPCON2,ACKEN goto sdarlp6 banksel SSPBUF movf SSPBUF,W return ; ストップコンディション stpcon bcf PIR1,SSPIF ; ストップ・コンディション処理 banksel SSPCON2 ; バンクを選択 bsf SSPCON2,PEN ; ストップ・コンディションを開始 stplp btfsc SSPCON2,PEN ; 完了チェック goto stplp ; 繰り返し banksel PIR1 ; バンク選択 bcf PIR1,SSPIF ; フラグをクリア return usdttx btfss PIR1,TXIF ; 送信バッファ空チェック goto usdttx ;  movwf TXREG ; 送信データをセットし待つ return ; 一バイトデータの値をHEX表示でUSART経由で書き込む b2attx bcf STATUS,RP0 movwf b2a_tmp ; 表示データを保存 swapf b2a_tmp,w ; 上下のニブルを入れ替え call bacon ; 下位4ビットを 文字コードに変換 call usdttx ; 変換されたデータをUSARTに出力 movf b2a_tmp,w ; 保存したデータをWレジスタにセット call bacon ; 下位4ビットを 文字コードに変換 call usdttx ; 変換されたデータをUSARTLCDに出力 return ; ; 受信処理ルーチン RXloop call get_rd ; 受信データの有無をチェック btfsc STATUS,Z ; Z=1で受信データなし goto RXloop ; 繰り返す movwf TXREG ; 送信レジスタに書き込み送信 goto RXloop ; 繰り返す ; get_rd movf e_p,w ; e_p =s_pをチェック subwf s_p,w ; 引き算で等しいかチェック btfsc STATUS,Z ; Z=1で データ受信無し return ; e_p =s_pで受信データ無く戻る incf e_p,f ; 受信デーがあるのでカウント・アップ movf e_p,w ; Wレジスタでチェック sublw 040h ; 上限チェック btfss STATUS,Z ; 上限を超えたらZ=1 goto jpget2 ; 上限でない場合ジャンプ movlw 30h ; 上限超え先頭に戻る movwf e_p ; 先頭の値をセット   jpget2 movf e_p,w ; ポインタの値をWデータにセット movwf FSR ; 間接アドレスのポインタをセット movf INDF,w ; 間接アドレス指定で受信データをWレジスタにセット return ; ;タイマ処理サブルーチン0.1ms 255 tm01 bcf INTCON,T0IF ; sublw 0FFh ; movwf TMR0 ; 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'00001111' ; 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 ; 1バイトデータの値をHEX表示でLCDに書き込む b2asub bcf STATUS,RP0 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フラグがOFFまで待つ 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フラグがOFFまで待つ bcf LCDPORT,RW ; WRITEでL bsf LCDPORT,RS ; データでRSはH movwf PORTD ; データを出力 bsf LCDPORT,E ; Eをオン bcf LCDPORT,E ; Eをオフ return ; ; ASCII to HEX ; 0から9, Aからfのキャラクタを HEX表示に変換する aschex movwf tempw ; データを引き算するため,元のデータを保存する sublw 039h ; 9 以下かチェックする btfss STATUS,C; 大小の比較 W=<39h goto ova ;  W>39h movf tempw,W; 元のデータを取り出す andlw 00Fh ; 上位ビットをカット return ova movf tempw,W; 元のデータを取り出す andlw 00fh ; 上位ビットをカット addlw 009h ; +9で補正 return d4set movf data1,W; 最上位桁を取り出す call aschex ; 変換 movwf datao1; 出力エリアにセット swapf datao1,F; ニブルの入れ替え movf data2,W; 次の桁を取り出す call aschex ; 変換 iorwf datao1,F; 下の桁をセット movf data3,W;  次の桁を取り出す call aschex; 変換 movwf datao2; 下位桁にセット swapf datao2,F; ニブルの入れ替え  movf data4,W; 最下位桁を取り出す call aschex ; 変換 iorwf datao2,F; 下の桁をセット return END ; 各モジュールのテストSIMを使ってテストする場合メイン・ルーチンの先頭で該当するレジスタに値をセットして ; テストするサブルーチンを呼び出し各動作を確認します.SIMで入力はシミュレートできますが,割り込みの場合 ; main  ; シミュレートできないものもあります.多くの演算処理などはこのように追加の命令を ; movlw 33h    ; 書き込むだけで実際の動作を確認デバッグできます ; movwf data1    ; sublw命令の引き算を反対に考えていた勘違いが直ぐに分かりました. ; movlw 34h    ; ; movwf data2     ; movlw 32h ; movwf data3 ; movlw 31h ; movwf data4 ; call d4set ; call cmdar