RX62N 用FM音源プログラム -- TGRX62N (4)

RX62N 基板にキャラクLCD / 入力スイッチをつなぐのに、どういう方法をとろうか迷っていましたが、8 ビット MCU を介在させて接続することにしました。
LCD 表示させた基板の写真を下に示します。

キャラクタ表示 LCD の R/W 信号を GND レベルに固定し、ライト・オンリで 4 ビット・モードでインターフェースした場合でも、LCD との接続は DB7 〜 DB4、RS、E の合計 6 本の信号線が必要です。
ライト・オンリなので、LCD 側から信号線をドライブされることはありませんが、E 以外の 5 本の線は PMOS による弱いプルアップがされているので、マイコン側が 3.3 V 電源、LCD 側が 5 V 電源の場合に、マイコン側の出力端子が 5 V に向かってプルアップされることになります。
プルアップは抵抗値に換算すると数十 kΩ の程度なので、デバイスを破壊するようなことはなく、保護回路で十分吸収される程度のものですが、気持ち良くはありません。
LCD 側も 3.3 V 電源で使用すれば問題ありませんが、次のような理由で LCD 側は 5 V 電源で使用する方がメリットがあります。

  • 液晶デバイスのバイアス電圧 (Vo) は Vdd 基準で -4 V 程度になるので Vdd = 3.3 V だと Vo に -1 V 程度のマイナス電圧が必要になる
  • 白色 LED バックライトの Vf は 4 V 程度なので、LCD モジュール側の電源を 5 V とすれば、LED バックライト用電源と共通化できる

5 V 電源の LCD を 3.3 V 電源のマイコンで「安心」して使うには 5V トレラント対応のポートを使うか、レベル変換用バッファを介することになります。
インターフェース誌 2011 年 5 月号の pp.70 〜 71 のコネクタ・ピン配置一覧表には、LCD 拡張ボードと組み合わせて使う場合の信号名が併記されています。
これを見ると、ほとんどの信号線は拡張ボードで使われており、空欄となっていて使われいないと思われる信号線は 4 本ほどしかありません。
拡張ボードの価格はインターフェース本誌の価格の 10 倍以上であり、決して購入することはないと思うので、実際のところは分かりませんし、回路図も公開されていないので、「未割り当て」の信号線だけを使うことにしました。
未割り当ての信号線だけでは、LCD インターフェースに必要な 6 本の信号線を確保できないので、8 ビット MCU を介在させ、RX62N 基板とのインターフェースは調歩同期式のシリアル形式で行うことにしました。
このために、

  • P00 / TxD6-A (CN2-29)
  • P01 / RxD6-A (CN2-30)

の 2 本の 5 V トレラント IO を使います。
5 V トレラントなので、安心して LCD モジュールと 8 ビット MCU を 5 V 電源で使えます。
FM音源プログラムでは、約 2 ms に一回のレートで 4 ビット・モードの LCD への書き込みを行っています。
後に示すように、8 ビット MCU として PIC16F628 を内蔵 4 MHz RC クロックで動作させているので、ボーレイトとして 1 [MHz] / 64 = 62.5 [kbps] の設定にしています。
データのフォーマットとしては、RX62N 基板側からは、単純に RS、D7 〜 D4 の 5 ビットをシリアルで渡すだけとし、LCD の E 信号については 8 ビット MCU 側で自動作成することにしました。
5 ビット・データは LSB 側に詰め、上位 3 ビットの「空き」のデータには、ストップ・ビットの値と同じ「1」を詰めています。
これは、実質的にデータ長が 5 ビットのフォーマットとすることで、全体のビット長を短くし、ボーレイトの誤差の影響を受けにくくするためです。
入力スイッチの状態についても、チャタリング除去などはせずに、単純にスイッチの接続されたポートを読み出し、シリアルで RX62N 基板側に送るようにしました。
8 ビット MCU では、RX62N 基板側からの LCD データを受信するたびに、スイッチ・データを送信するようにしてあります。 自発的には RX62N 基板側には送信しません。
この 8 ビット MCU として、手持ちの PIC16F628 (18 ピン) を使った場合の回路を下に示します。

後で示すように、MCU のプログラムは非常に簡単なので、LCD への信号線が確保できるだけのピン数があるチップなら何でも実現可能だと思います。
AVR についても、手持ちの ATtiny2313 (20 ピン) を使って実験したいと思っています。
RX62N も PIC16F628 も、シリアルで 9 ビット・データを送受できるモードがあるので、8 ビット・モードでの LCD とインターフェース可能ですが、配線が 4 本増えることと、ボーレイト誤差の影響を受けやすくなるために 8 ビット・モードは採用しませんでした。
ちなみに、PIC16F628 の 4 MHz 内部 RC クロックを 4 分周したクロックを外部に出力する config で実測したところ、約 973 kHz、つまり約 -3 % のクロック誤差となっていて、ビット長が長くなるとマージンが少なくなります。
最後に PIC16F628 用のプログラムを示します。

;
; lcd4uart:  4-bit mode character LCD and keySW I/F
;            using UART (62.5 kbps) to HOST
;  
; 2011-Apr-19, created by pcm1723
;
; CLOCK FREQUENCY: 4 MHz (internal RC osc)
;
; INPUT SIGNAL:
; 
;  RB1/RX (Pin 7) -- connect to HOST TxD
;
; OUTPUT SIGNAL:
; 
;  RA4 (Pin  3) -- connect to LCD RS
;  RA3 (Pin  2) -- connect to LCD DB7
;  RA2 (Pin  1) -- connect to LCD DB6
;  RA1 (Pin 18) -- connect to LCD DB5
;  RA0 (Pin 17) -- connect to LCD DB4
;
;  RB0 (Pin  7) -- connect to LCD E
;
;  RB2/TX (Pin 8) -- connect to HOST RxD
;
        processor pic16f628
;
        List    p=pic16f628,f=inhx8m
        include "p16f628.inc"
        __config _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _BODEN_OFF
;
        udata   0020h
rxdata  res     1            ; Rx data buffer
txdata  res     1            ; Tx data buffer
;
; 
        code    0000h
        goto    start        ; reset vector
        res     1
        res     1
        res     1
        goto    start        ; interrupt vector
;
start:
        call    port_setup   ; setup for PORT
        call    usart_setup  ; setup for USART and BRG
        banksel PIR1         ; PIR1, RCREG, PORTA,
                             ; PORTB, TXREG on BANK0
rxloop0:
        btfss   PIR1,RCIF    ; skip if RCIF=1 (RCREG full)
        goto    rxloop0      ; loop if RCIF=0 (RCREG empty)
        movfw   RCREG        ; read the received data
        movwf   PORTA        ; out data to LCD RS, D7..D4
        bsf     PORTB,0      ; output '1' to LCD_E (RB0)
        swapf   PORTB,w      ; PORTB[7:4] --> w[3:0]
        iorlw   b'11110000'  ; fill "1" in w[7:4]
        movwf   TXREG        ; output to USART
txloop1:
        banksel TXSTA        ; TXSTA on BANK1
        btfss   TXSTA,TRMT   ; skip if TRMT=1 (TSR empty)
        goto    txloop1      ; loop if TRMT=0 (TSR full)
        banksel PORTB        ; PORTB, PIR1 on BANK0
        bcf     PORTB,0      ; output '0' to LCD_E (RB0)

        goto    rxloop0
;
;
; port setup for LCD interface
;
port_setup:
        banksel TRISA        ; TRISA, TRISB, OPTION on BANK1
        bcf     TRISA,4      ; RA4 output enable (LCD RS)
        bcf     TRISA,3      ; RA3 output enable (LCD DB7)
        bcf     TRISA,2      ; RA2 output enable (LCD DB6)
        bcf     TRISA,1      ; RA1 output enable (LCD DB5)
        bcf     TRISA,0      ; RA0 output enable (LCD DB4)
        bcf     TRISB,0      ; RB0 output enable (LCD E)
        bcf     TRISB,2      ; RB2/TX output enable
        bcf     OPTION_REG,NOT_RBPU ; enable PB weak pull up
        banksel PORTB        ; PORTB on BANK0
        bcf     PORTB,0      ; RB0 = '0' (LCD E)
        return
;
; setup for USART and Baud Rate Generator 
; for 62.5 kbps at 4 MHz osc
;
usart_setup:
        movlw   b'00100000'  ; TX enable, async, BRGH=0
        banksel TXSTA        ; TXSTA, SPBRG on BANK1
        movwf   TXSTA        ; set Tx config
        movlw   d'0'         ; 4 [MHz]/64/(0+1)=62.5 [kbps]
        movwf   SPBRG        ; set Baud rate
        movlw   b'10010000'  ; SPEN=1, CREN=1
        banksel RCSTA        ; RCSTA on BANK0
        movwf   RCSTA        ; set Rx config
        return
;       
        end