PICでキャラクタ液晶制御
前々からやってみたかったキャラクタLCDの制御をPICでやってみました。
Cコンパイラを使えばライブラリが用意されているので簡単にLCDの制御ができますが、今回はアセンブラで書いたので少し面倒でした。
"はじめてのPICアセンブラ入門(CQ出版)"で制御の手順が解説されているのでそれを見ながら作っていきました。
使用PICはPIC16F887。通信は4ビット×2
無事"Hello World!"の表示ができました。
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 #define lcdRS PORTE,0 #define lcdRW PORTE,1 #define lcdE PORTE,2 #define lcdPort PORTB tm1 equ 0x20 tm2 equ 0x21 lcdData equ 0x22 lcdWrite4temp equ 0x23 lcdReadReg equ 0x24 ;********************************************************************** ORG 0x000 ; processor reset vector nop goto main ; go to beginning of program main bcf STATUS,RP0 ;bank0 bcf STATUS,RP1 clrf INTCON bcf STATUS,RP1 bsf STATUS,RP0 ;bank1 clrf TRISA clrf TRISB clrf TRISC clrf TRISD clrf TRISE bsf STATUS,RP1 bsf STATUS,RP0 ;bank3 clrf ANSEL clrf ANSELH bcf STATUS,RP0 ;bank0 bcf STATUS,RP1 clrf PORTA clrf PORTB clrf PORTC clrf PORTD clrf PORTE call clearAllReg call lcdInit goto mainLoop clearAllReg clrf tm1 clrf tm2 clrf lcdData clrf lcdWrite4temp clrf lcdReadReg return mainLoop call lcdBusyCheck movlw 'H' movwf lcdData call lcdWriteData movlw 'e' movwf lcdData call lcdWriteData movlw 'l' movwf lcdData call lcdWriteData movlw 'l' movwf lcdData call lcdWriteData movlw 'o' movwf lcdData call lcdWriteData movlw ' ' movwf lcdData call lcdWriteData movlw 'W' movwf lcdData call lcdWriteData movlw 'o' movwf lcdData call lcdWriteData movlw 'r' movwf lcdData call lcdWriteData movlw 'l' movwf lcdData call lcdWriteData movlw 'd' movwf lcdData call lcdWriteData movlw '!' movwf lcdData call lcdWriteData bsf PORTD,0 goto breakLoop breakLoop nop goto breakLoop lcdInit bcf lcdE bcf lcdRW bcf lcdRS call wait_10ms call wait_10ms movlw b'00000011' movwf lcdPort call lcdWrite call wait_10ms movlw b'00000011' movwf lcdPort call lcdWrite call wait_10ms movlw b'00000011' movwf lcdPort call lcdWrite call wait_10ms movlw b'00000010' movwf lcdPort call lcdWrite call wait_10ms movlw 0x2C movwf lcdData call lcdWriteCmdNoBusyCheck movlw 0x08 movwf lcdData call lcdWriteCmd movlw 0x0F movwf lcdData call lcdWriteCmd movlw 0x06 movwf lcdData call lcdWriteCmd call lcdClear return lcdWriteData call lcdBusyCheck bsf lcdRS goto lcdWrite4 lcdWriteCmdNoBusyCheck bcf lcdRS goto lcdWrite4 lcdWriteCmd call lcdBusyCheck bcf lcdRS goto lcdWrite4 lcdWrite4 ;上位ビット movfw lcdData andlw b'11110000' ;lcdDataの上位ビットのみwに保持=xxxx0000 movwf lcdWrite4temp swapf lcdWrite4temp,f ;lcdDataの上位ビットがlcdWrite4tempの下位ビットに入ってる=0000xxxx movfw lcdWrite4temp ;lcdWrite4tempをwへ movwf lcdPort ;上位ビット書き込み bsf lcdE ;送信 bcf lcdE ;下位ビット movfw lcdData andlw b'00001111' ;lcdDataの下位ビットのみwに保持=0000xxxx movwf lcdPort ;下位ビット書き込み bsf lcdE ;送信 bcf lcdE return lcdWrite bsf lcdE ;送信 bcf lcdE return lcdBusyCheck bcf STATUS,RP1 bsf STATUS,RP0 ;bank1 movlw b'00001111' ;LCDのデータポートだけ入力に設定 movwf TRISB bcf STATUS,RP1 bcf STATUS,RP0 ;bank0 bcf lcdRS ;busy読み込み指定 bsf lcdRW ;lcdBusyCheckに続けて書くこと lcdBusyMain call lcdRead btfsc lcdReadReg,7 goto lcdBusyMain bcf lcdRW bcf STATUS,RP1 bsf STATUS,RP0 ;bank1 clrf TRISB bcf STATUS,RP1 bcf STATUS,RP0 ;bank0 return lcdRead clrf lcdReadReg ;上位ビット bsf lcdE movfw lcdPort ;液晶からの上位ビットがwの下位ビットに入る=0000xxxx movwf lcdReadReg swapf lcdReadReg,f ;液晶からの上位ビットがlcdReadRegの上位ビットに入る=xxxx0000 bcf lcdE ;下位ビット bsf lcdE movfw lcdPort ;液晶からの下位ビットがwの下位ビットに入る=0000xxxx iorwf lcdReadReg,f ;lcdReadRegと論理和=xxxxxxxx bcf lcdE return lcdClear movlw 01H ;clear command movwf lcdData call lcdWriteCmd return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;10ms待機 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; wait_10ms movlw d'70' movwf tm1 wait_10ms_sub decfsz tm1,f goto wait_10ms_loop return wait_10ms_loop movlw d'237' movwf tm2 decfsz tm2,f goto $-1 goto wait_10ms_sub ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; END ; directive 'end of program'