9.LCD(液晶文字表示)モジュールについて

 

マイコンを高度に利用しようとすると、LCD(液晶文字表示)モジュールの接続が不可欠になりますが、今回はPIC16F88でLCD(液晶文字表示)モジュール(シャープ製 LM162AT1)を4ビットモードで制御する方法を紹介します。(一番ポピュラーなサンライク製SC1602とはVddとVssとが逆にピン配置されていますので、それを変更すれば問題なく動作します。)

過去に何回か同様の設計し問題なく動作していましたが、今回はADCを利用しないので、RA0RA3のポートをデータバスに使いました。

ところが、それが思わぬ落とし穴となり1W悩みました。 その結果は文末の「後書き」に記載しましたが、まずは以下の回路を使った制御方法を解説します。

9.1 コーディング例

シリアルポートから受信したデータをLCDに表示する処理をコーディングしたものです。 LCDポートの初期設定、LCDのイニシャライズ処理、LCDへのコマンドや文字データ書き込み、連続文字の書き込み等をまとめました。(このコーディングは全コーディングからLCD制御関連を抜粋したもので、このままでは使えません。)

;          

;******************************************

; Initialize Routine

;******************************************

INIT

              BSF                     STATUS,RP0                   ;bank1

;set clock

              MOVLW              070H                                 ;internal clock 8 MHz

              MOVWF              OSCCON                    ;

;initialize PORTs

四角形吹き出し: 各ポートの入出力を設定する。              MOVLW              020H                                 ;init ports

            MOVWF              TRISA                               ;

              MOVLW              0FH                                   ;

            MOVWF              TRISB                               ;

四角形吹き出し: ANSELレジスタの電源ON時のデフォルト値はすべてアナログ入力(1)になっているので、上でポートAのPA0〜PA3を出力に設定してもデジタルIOポートとして利用できない。
 解ってしまえば、しごく当たり前のことですが、実は今回1Wも悩んだのはこの設定を忘れた為で、最初はLCDの制御波形に問題があると思い込み、考えられるすべてを試行してみましたが、解決できず。 初歩から見直してやっとこの忘れに気付きました。
              CLRF                   ANSEL                              ;

;

              MOVLW              0FFH                                 ;set FF to TMR2

              MOVWF              PR2                                   ;

              BSF                     PIE1,TMR1IE                   ;enable TMR1 interrupt                 

              BSF                     PIE1,TMR2IE                ;enable TMR2 interrupt

;initialize USRT

              MOVLW              0H                                     ;async,8bit,no-parity,2400bps

              MOVWF              TXSTA                               ;

              MOVLW              .51                                     ;

              MOVWF              SPBRG                              ;

              CLRF                   OPTION_REG                  ;permit week-pullup of PORTB          

              BCF                     STATUS,RP0                     ;bank0

;Start TMR2

              CLRF                   TMR2                                ;set zero to TMR2

              MOVLW              01BH                               ;start TMR2 counter ( prescaler 1/4

              MOVWF              T2CON                           ;,postscaler 1:16 (8.2ms))

;             BSF                     T2CON,TMR2ON             ;start TMR2

;Start TMR1

              CLRF                   INTCH                              ;reset int. timer

              CLRF                   INTCL                               ;

              MOVLW              030H                                 ;ready TMR1(262 ms interval)

              MOVWF              T1CON                              ;

;start IR receive

              MOVLW              090H                                 ;start receive

              MOVWF              RCSTA                              ;

;

              CLRF                   CFLAG                              ;

              CLRF                   PORTA                              ;clear ports

四角形吹き出し: LCDモジュールのイ二シャライズ処理            CLRF                   PORTB                              ;

;init LCD module

              CALL                   LCDINIT4                         ;init LCD module(4 bits-mode)

;permit all interrupts

              MOVLW              0C0H                                 ;enable all interrupts

              MOVWF              INTCON                            ;

;

;display running signal

ILED    

              BSF                     PORTA,LEDR                   ;illuminate LED

              MOVLW              .4                                       ;wait for 1 sec.

四角形吹き出し: LCDモジュールへの連続文字表示処理              CALL                   WAITT                              ;

              BCF                     PORTA,LEDR                   ;

              CALL                   DISPM                              ;display starting message to LCD

              MOVLW              .4                                       ;wait for 1 sec.

              CALL                   WAITT                              ;

;          

四角形吹き出し: シリアルポートから2400BPSで16進データを受信し、表示文字に変換後、タイトルを付けてデータをLCDに表示する。;******************************************

; Main Routine                               

;******************************************

;

MAIN

              BSF                     PORTA,LEDR                   ;light on LED(R)

;check pre-amble

              CALL                   RDATA                              ;receive pre-amble            

              SUBLW               0AAH                                ;check pre-amble(AA)

              BTFSS                 STATUS,Z                         ;

              GOTO                  MAIN                                ;

;check ID

MAIN1

              CALL                   RDATA                              ;receive ID=1      

              MOVWF              RDATAID                          ;save received data

;receive 1st.command

              CALL                   RDATA                              ;receive 1st.command

              MOVWF              RDATA1C                          ;save received data

              MOVF                 CCODE,W                         ;check code

              BTFSS                 STATUS,Z                         ;

              GOTO                  MAIN                                ;

;receive 1st.command (reverse)

              CALL                   RDATA                              ;receive reverse-command

              MOVWF              RDATA1R                          ;save received reverse data

              COMF                 RDATA1R,W                     ;

              SUBWF               RDATA1C,W                     ;check error of transmit

              BTFSS                 STATUS,Z                         ;

              GOTO                  MAIN                                ;

              MOVF                 CCODE,W                         ;check code

              BTFSS                 STATUS,Z                         ;

              GOTO                  MAIN                                ;

;receive 2nd.command

              CALL                   RDATA                              ;receive 2nd.command

              MOVWF              RDATA2C                          ;save received data

              MOVF                 CCODE,W                         ;check code

              BTFSS                 STATUS,Z                         ;

              GOTO                  MAIN                                ;

;receive 2nd.command (reverse)

              CALL                   RDATA                              ;receive reverse-command             

              MOVWF              RDATA2R                          ;save received reverse data

              COMF                 RDATA2R,W                     ;

              SUBWF               RDATA2C,W                     ;check error of transmit

              BTFSS                 STATUS,Z                         ;

              GOTO                  MAIN                                ;

              MOVF                 CCODE,W                         ;check code

              BTFSS                 STATUS,Z                         ;

              GOTO                  MAIN                                ;

;receive 3rd.command

              CALL                   RDATA                              ;receive 3rd.command

              MOVWF              RDATA3C                          ;save received data

              MOVF                 CCODE,W                         ;check code

              BTFSS                 STATUS,Z                         ;

              GOTO                  MAIN                                ;

;receive 3rd.command (reverse)

              CALL                   RDATA                              ;receive reverse-command

              MOVWF              RDATA3R                          ;save received reverse data

              COMF                 RDATA3R,W                     ;

              SUBWF               RDATA3C,W                     ;check error of transmit

              BTFSS                 STATUS,Z                         ;

              GOTO                  MAIN                                ;

              MOVF                 CCODE,W                         ;check code

              BTFSS                 STATUS,Z                         ;

              GOTO                  MAIN                                ;

;receive 4th.command

              CALL                   RDATA                              ;receive 4th.command

              MOVWF              RDATA4C                          ;save received data

              MOVF                 CCODE,W                         ;check code

              BTFSS                 STATUS,Z                         ;

              GOTO                  MAIN                                ;

;receive 4th.command (reverse)

              CALL                   RDATA                              ;receive reverse-command             

              MOVWF              RDATA4R                          ;save recieved reverse data

              COMF                 RDATA4R,W                     ;

              SUBWF               RDATA4C,W                     ;check error of transmitte

              BTFSS                 STATUS,Z                         ;

              GOTO                  MAIN                                ;

              MOVF                 CCODE,W                         ;check ccode

              BTFSS                 STATUS,Z                         ;

四角形吹き出し: シリアルポートから受信したデータ(RDATAID、RDATA1C〜4C)を表示する。              GOTO                  MAIN                                ;

;Display received data

MAIN22

              CALL                   DISPRD                            ;display data

              GOTO                  MAIN                                ;

;

;*******************************************

; Display Start Message to LCD

;

四角形吹き出し: LCDへの連続文字の表示ルーチン。少し特殊な処理方法であり、DT記述子で記述したSTART MONITORの文字列を順次ピックアップしてLCDDATA4ルーチンに送る。
 この処理はRETLW命令を多用して実現しているので、ページ・バウンダリー領域(xFF番地〜x00番地)にまたがらないようコーディングしないと暴走するので要注意。
 アッセンブリー・リストを確認してバウンダリー領域にかかっている場合はこのルーチン全体を別の番地に移動させるのが簡単な解決策。
;*******************************************

;

DISPM

              CLRF                   POINT                               ;clear pointer

DISPM1                                                       

              MOVF                 POINT,W                          ;get pointer

              CALL                   ABLE                                ;pick character

              ADDLW               0                                        ;check end mark (0)

              BTFSC                STATUS,Z                         ;

              RETURN                                                       ;

              CALL                   LCDDATA4                       ;display character

              INCF                   POINT,F                            ;inc pointer

              GOTO                  DISPM1                            ;loop till end mark

;

TABLE

              ADDWF              PCL,F                                ; PCOFFSET

              DT                       "START MONITOR",0

;

;*******************************************

; Display received data to LCD

;

;*******************************************

;

DISPRD

              BCF                     PORTA,LEDR                   ;light off LED

              CALL                   LCDCLR4                         ;clear LCD module

              MOVLW              "I"                                      ;display ID title (ID)

              CALL                   LCDDATA4                       ;

              MOVLW              "D"                                     ;

              CALL                   LCDDATA4                       ;

              MOVLW              " "                                       ;

              CALL                   LCDDATA4                       ;

;

              MOVLW              "C"                                     ;display title (CH1)

              CALL                   LCDDATA4                       ;

              MOVLW              "H"                                     ;

              CALL                   LCDDATA4                       ;

              MOVLW              "1"                                      ;

              CALL                   LCDDATA4                       ;

              MOVLW              "="                                      ;

              CALL                   LCDDATA4                       ;

              SWAPF                DATA1C,W                        ;pick data

              CALL                   CHGHA                            ;

              CALL                   LCDDATA4                       ;display CH1 data

              MOVF                 RDATA1C,W                     ;

              CALL                   CHGHA                            ;

              CALL                   LCDDATA4                       ;

              MOVLW              "  "                                    ;

              CALL                   LCDDATA4                       ;                          

;

              MOVLW              "C"                                     ;display title (CH2)

              CALL                   LCDDATA4                       ;

              MOVLW              "H"                                     ;

              CALL                   LCDDATA4                       ;

              MOVLW              "2"                                      ;

              CALL                   LCDDATA4                       ;

              MOVLW              "="                                      ;

              CALL                   LCDDATA4                       ;

              SWAPF                RDATA2C,W                     ;pick data

              CALL                   CHGHA                            ;

              CALL                   LCDDATA4                       ;display CH2 data

              MOVF                 RDATA2C,W                     ;

              CALL                   CHGHA                            ;

              CALL                   LCDDATA4                       ;            

;

              MOVLW              0C0H                                 ;positioning to 2L1D

              CALL                   LCDCMD4                        ;

              SWAPF                RDATAID,W                     ;pick data

              CALL                   CHGHA                            ;

              CALL                   LCDDATA4                       ;display ID data

              MOVF                 RDATAID,W                     ;

              CALL                   CHGHA                            ;

              CALL                   LCDDATA4                       ;display ID data

              MOVLW              "  "                                  ;

              CALL                   LCDDATA4                       ;

;

              MOVLW              "C"                                     ;display title (CH3)

              CALL                   LCDDATA4                       ;

              MOVLW              "H"                                     ;

              CALL                   LCDDATA4                       ;

              MOVLW              "3"                                      ;

              CALL                   LCDDATA4                       ;

              MOVLW              "="                                      ;

              CALL                   LCDDATA4                       ;

              SWAPF                RDATA3C,W                     ;pick data

              CALL                   CHGHA                                          ;

              CALL                   LCDDATA4                       ;display CH3 data

              MOVF                 RDATA3C,W                     ;

              CALL                   CHGHA                            ;

              CALL                   LCDDATA4                       ;

              MOVLW              "  "                                  ;

              CALL                   LCDDATA4                       ;

;

 

              MOVLW              "C"                                     ;display title (CH4)

              CALL                   LCDDATA4                       ;

              MOVLW              "H"                                     ;

              CALL                   LCDDATA4                       ;

              MOVLW              "4"                                      ;

              CALL                   LCDDATA4                       ;

              MOVLW              "="                                      ;

              CALL                   LCDDATA4                       ;

              SWAPF                RDATA4C,W                     ;pick data

              CALL                   CHGHA                            ;

              CALL                   LCDDATA4                       ;display CH data

              MOVF                 RDATA4C,W                     ;

              CALL                   CHGHA                            ;

              CALL                   LCDDATA4                       ;                          

              RETURN

;

;*************************************************

; Change HEX to ASCII

; 

;*************************************************

CHGHA1

              ANDLW               0FH                                   ;get lower digit

              ADDWF              PCL,F                                ;Add to PC reg

              DT                       "0123456789ABCDEF"                                

;

;

;***************************************

; Initialize LCD ( for LM162AT1,SC1602 )

; 4 bits-mode

;***************************************

;

LCDINIT4

              CALL                   TIM10M                            ; wait  for 40ms

             CALL                   TIM10M                            ;

              CALL                   TIM10M                            ;

              CALL                   TIM10M                            ;

              MOVLW              03H                                   ; set 8bit mode

              CALL                   LCDCMD8                        ;

;

              CALL                   TIM10M                            ; wait  for 10ms

              MOVLW              03H                                   ; set 8bit mode

              CALL                   LCDCMD8                        ;

;

              CALL                   TIM100U                          ; wait(100μs)

              MOVLW              03H                                   ; set 8bit mode

              CALL                   LCDCMD8                                      ;

;

              CALL                   TIM100U                          ; wait(100μs)

              MOVLW              02H                                  ; set 4bit mode

              CALL                   LCDCMD8                        ;

;

              CALL                   LCDBUSY4                       ; check busy

              MOVLW              028H                                 ; set display mode

              CALL                   LCDCMD4                        ;

;

              CALL                   LCDBUSY4                       ; check busy

              MOVLW              08H                                   ; set display off

              CALL                   LCDCMD4                        ;

;

              CALL                   LCDBUSY4                       ; check busy

              MOVLW              01H                                   ; clear display data

              CALL                   LCDCMD4                        ;

;

              CALL                   LCDBUSY4                       ; check busy

              MOVLW              06H                                   ; set entry mode

;

              CALL                   LCDCMD4                        ;

;

              CALL                   LCDBUSY4                       ; check busy

              MOVLW              0CH                                   ; display on,cursor off

              CALL                   LCDCMD4                        ;

;

              CALL                   LCDBUSY4                       ; check busy

              RETURN

;

;+++++++++++++++++++++++++++++++++++++++++

; Write Command to LCD module

; 4 bit mode

LCDCMD4                                                                                                                                       

              MOVWF              DPDT                                ; save command

              SWAPF                DPDT,W                            ;

              ANDLW               0FH                                   ;

四角形吹き出し: LCDにコマンドを書き込むルーチン。
LCDCMD4は4ビット用、LCDCMD8は8ビット用で使用する。
              CALL                   LCDCMD8                        ; write upper 4bit

              MOVF                 DPDT,W                            ;                          

              ANDLW               0FH                                   ;

              CALL                   LCDCMD8                        ; write lower 4bit

              CALL                   LCDBUSY4                       ;

              RETURN

; 8 bit mode

LCDCMD8                                     

              MOVWF              PORTA                              ; write command to LCD

              BCF                     PORTB,RW                       ; R/W = 0 write mode

              BCF                     PORTB,RS                        ; RS  = 0 command mode

              NOP

              BSF                     PORTB,E                          ; E   = 1 strobe up

              NOP                                                              ; E             (keep strobe wide)

              NOP

              NOP

              BCF                     PORTB,E                          ; E   = 0 strobe down

              NOP

              RETURN

 

四角形吹き出し: LCDにデータ(文字)を書き込むルーチン。
LCDDATA4は4ビット用、LCDDATA8は8ビット用で使用する。
;++++++++++++++++++++++++++++++++++++++++++

; Write Data to LCD module

; 4bit mode

LCDDATA4                                    

              MOVWF              DPDT                                ; save data

              SWAPF                DPDT,W                            ;

              ANDLW               0FH                                   ;

              CALL                   LCDDATA8                       ; write upper 4bit

              MOVF                 DPDT,W                            ;

              ANDLW               0FH                                   ;

              CALL                   LCDDATA8                       ; write lower 4bit

              CALL                   LCDBUSY4                       ;

              RETURN

; 8bit mode

LCDDATA8                                                  

              MOVWF              PORTA                              ; write data to LCD

              NOP

              BCF                     PORTB,RW                       ; R/W = 0 write mode

              BSF                     PORTB,RS                        ; RS  = 1 data mode

              NOP

              BSF                     PORTB,E                          ; E   = 1 strobe up

              NOP                                                              ; E       (keep strobe)

              NOP

              NOP

              BCF                     PORTB,E                          ; E   = 0 strobe down

              NOP

              RETURN

;

;++++++++++++++++++++++++++++++++++++++++++

; Check LCD module Busy

; 4 bit mode

BUSYF  EQU      3

;

LCDBUSY4

              BCF                     INTCON,GIE                    ; inhibit int.

              BSF                     STATUS,RP0                     ; change bank 1

              MOVLW              0FH                                   ; set lower 4 bits to input

              IORWF                TRISA ,F                           ;

              BCF                     STATUS,RP0                     ; change bank 0

              BSF                     INTCON,GIE                    ; permit int.

四角形吹き出し: LCDが直前の指示を実行中かどうかをチェックするルーチン。
一時的にデータバスを入力に切り替えて、ビージーフラグをセンスし、0になるまで待つ。
LCDBUSY41

              BCF                     PORTB,RS                        ; RS  = 0 command mode

              BSF                     PORTB,RW                       ; R/W = 1 read mode

              BSF                     PORTB,E                          ; E   = 1 strobe up

              NOP

              NOP

              MOVF                 PORTA,W                          ; read upper 4bits status data

              BCF                     PORTB,E                          ; E   = 0 strobe down

              MOVWF              DPDT                                ; save data

;            

              BSF                     PORTB,E                          ; E   = 1 strobe up

              NOP

              NOP

              MOVF                 PORTA,W                          ; read lower 4bits unused data

              BCF                     PORTB,E                          ; E   = 0 strobe down

;

              BTFSC                DPDT,BUSYF                   ; check busy flag (bit7)

              GOTO                  LCDBUSY41                     ; loop till bit7=0

;

              BCF                     PORTB,RW                       ; restore R/W = 0

;

              BCF                     INTCON,GIE                    ; inhibit int.

              BSF                     STATUS,RP0                     ; change bank 1

              MOVLW              0F0H                                 ;restore lower 4 bits to output

              ANDWF              TRISA,F                                          ;

              BCF                     STATUS,RP0                     ; change bank 0

              BSF                     INTCON,GIE                    ; permit int.

              RETURN

;

;+++++++++++++++++++++++++++++++++++++++++++++

; Clear LCD Display

; 4 bit mode

LCDCLR4

              MOVLW              01H                                                 ;clear LCD

              CALL                   LCDCMD4                                      ;

              CALL                   TIM10M                                          ; wait for 10ms   

              MOVLW              0EH                                                 ;ready

              CALL                   LCDCMD4                                      ;

              RETURN

;

9.2 後書き

今回のLCDモジュールの制御方法を解説しましたが、冒頭記したように1Wも無駄な時間を費やしました。 結果はANSELレジスタの設定忘れでした。 過去にもLCDモジュールを何回も動作させており、何故こんなケアレス・ミスを犯したのか考えてみると、過去に作ったものは全てA/D変換(ADC)を利用してその結果をLCDに表示するものでした。 従ってANSELレジスタの設定は該当のポートだけアナログ入力に、他はデジタルIOに無意識に正しく設定していた訳です。  だが、今回はA/D変換を利用せず、そのポートをLCDのデータバスに利用した為、ANSELレジスタを設定することすら頭には無く、すべてのANポートがアナログ入力(デフォルト)のまま放置されていたのです。

「ANSELレジスタはA/D変換(ADC)を利用するときに設定するもの」という固定概念は捨てないと今回のようなミスを起こします。

他にもこのようなことがあると思います、直接利用しなくても各レジスタの初期値(デフォルト値)に注意しましょう。

意外なところに落とし穴がありますよ。 皆さんもこんな経験ないですか?・・・・

以上