Raspberry Pi 3でCentOS7からのキャラクタLCDへのアクセス方法をまとめました。
過去の資産(秋月のLCD)が何個jかありますので、これらのアクセスについて記します。
パラレルバスインタフェースといえばこの系統が主流ですね。往年の68系バスに接続するインタフェース仕様です。
8ビット以外に4ビットでのアクセスが可能ですが、どうしてもData(4)+E+R/W*RSで最低、7本のインタフェースが必要になります。#ref(): File not found: "SC1602BSLB.jpg" at page "キャラクタLCDをアクセス"
#ref(): File not found: "sc1602bslb_pin_assign.jpg" at page "キャラクタLCDをアクセス"
ピン数の節約のため、4bitモードででアクセスし必要なソフトはCで作成することにします。
まず、ピンの割り当てですが、他の機能と併用されていないピンを使用することにします。
電源はRaspberryPi?の3.3Vを使用します。PINのラッチアップ等を避けるため、同一電源とします。
Raspberry Pi LCD Signal Pin# Signal Pin# 3V3 01,17 3V3 01 GND 34,39 GND 02 VO(contrast) 03 GPIO 21 40 E 06 GPIO 22 15 R/_W 05 GPIO 23 16 RS 04 GPIO 24 18 D4 11 GPIO 25 22 D5 12 GPIO 26 37 D6 13 GPIO 27 13 D7 14
- PullUp?/Pulldown
信号の衝突を避けるため、R/_W、EはPulldownを行います。
また、コントラスト調整(VO)は20kΩのVRにより電位を調整するようにします。
Read/Write用の関数を作成してアクセスすることになります。
たとえばvoid lcd_init( void );
void lcd_write( int mode, int data );
int lcd_read( int mode, init data );基本として、各種のコマンドを作成することとします。上記の関数を利用して
void lcd_set_position( int x, int y );
void lcd_put_char( int char );
void lcd_clear( void );
void lcd_print( int line, char *str );位を用意すれば良いでしょう。
実際はリード系のコマンドは不要と思いますが。
テストのつもりでコーディングします。
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // HD44780/SC1602 LCDモジュール(16 x 2) 秋月版 制御TP // このTPでは、2行表示に対して、これぞれの行に文字を表示します。 // 基本的に16文字固定表示でスクロールはしません。カーソルも表示しません。 // // コンパイル方法 // gcc -o lcd_test lcd_test.c -l bcm2835 // // copyright (c) 2016 Kazuhiro WATANABE All right reserved. // mailto:jj1req@ca.mbn.or.jp // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #include <bcm2835.h> #include <stdio.h> #include <stdlib.h> #include <string.h> // キャラクタ液晶ディスプレーへの接続 #define LCD_E 21 #define LCD_R_W 22 #define LCD_RS 23 #define LCD_DB4 24 #define LCD_DB5 25 #define LCD_DB6 26 #define LCD_DB7 27 //****************************************************************************** //* LCDモジュールに対してストローブをかけます(E端子ストローブ) //* //* Function Name //* void lcd_strobe( void ) //* Arguments //* none //* Return //* none //* //****************************************************************************** void lcd_strobe( void ) { bcm2835_delayMicroseconds( 1LL ); bcm2835_gpio_write( LCD_E, HIGH ); bcm2835_delayMicroseconds( 1LL ); bcm2835_gpio_write( LCD_E, LOW ); } //****************************************************************************** //* LCDモジュールに対して表示のクリアを行います //* //* Function Name //* void lcd_clear( void ) //* Arguments //* none //* Return //* none //* //****************************************************************************** void lcd_clear( void ) { // Display OFF 0000 1000 bcm2835_gpio_write( LCD_DB7, LOW ); bcm2835_gpio_write( LCD_DB6, LOW ); bcm2835_gpio_write( LCD_DB5, LOW ); bcm2835_gpio_write( LCD_DB4, LOW ); bcm2835_gpio_write( LCD_RS, LOW ); bcm2835_gpio_write( LCD_R_W, LOW ); lcd_strobe(); bcm2835_gpio_write( LCD_DB7, HIGH ); lcd_strobe(); bcm2835_delayMicroseconds( 40LL ); // Display clear 0000 0001 bcm2835_gpio_write( LCD_DB7, LOW ); lcd_strobe(); bcm2835_gpio_write( LCD_DB4, HIGH ); lcd_strobe(); // Entry Mode set 0000 0110 bcm2835_gpio_write( LCD_DB4, LOW ); lcd_strobe(); bcm2835_gpio_write( LCD_DB6, HIGH ); bcm2835_gpio_write( LCD_DB5, HIGH ); lcd_strobe(); bcm2835_delayMicroseconds( 40LL ); } //****************************************************************************** //* LCDモジュールに対して初期化を行います //* //* Function Name //* void lcd_init( void ) //* Arguments //* none //* Return //* none //* //****************************************************************************** void lcd_init( void ) { // ライブラリ初期化 if( !bcm2835_init() ) { printf( "bcm2835 library initialize error!!\n" ); exit(1); } // I/O ピンの初期化 bcm2835_gpio_fsel( LCD_DB4, BCM2835_GPIO_FSEL_INPT ); bcm2835_gpio_set_pud( LCD_DB4, BCM2835_GPIO_PUD_UP ); bcm2835_gpio_fsel( LCD_DB5, BCM2835_GPIO_FSEL_INPT ); bcm2835_gpio_set_pud( LCD_DB5, BCM2835_GPIO_PUD_UP ); bcm2835_gpio_fsel( LCD_DB6, BCM2835_GPIO_FSEL_INPT ); bcm2835_gpio_set_pud( LCD_DB6, BCM2835_GPIO_PUD_UP ); bcm2835_gpio_fsel( LCD_DB7, BCM2835_GPIO_FSEL_INPT ); bcm2835_gpio_set_pud( LCD_DB7, BCM2835_GPIO_PUD_UP ); bcm2835_gpio_fsel( LCD_RS, BCM2835_GPIO_FSEL_OUTP ); bcm2835_gpio_set_pud( LCD_RS, BCM2835_GPIO_PUD_DOWN ); bcm2835_gpio_write( LCD_RS, LOW ); bcm2835_gpio_fsel( LCD_R_W, BCM2835_GPIO_FSEL_OUTP ); bcm2835_gpio_set_pud( LCD_R_W, BCM2835_GPIO_PUD_DOWN ); bcm2835_gpio_write( LCD_R_W, LOW ); bcm2835_gpio_fsel( LCD_E, BCM2835_GPIO_FSEL_OUTP ); bcm2835_gpio_set_pud( LCD_E, BCM2835_GPIO_PUD_DOWN ); bcm2835_gpio_write( LCD_E, LOW ); // 初期化フェーズ1 bcm2835_gpio_write( LCD_DB7, LOW ); bcm2835_gpio_write( LCD_DB6, LOW ); bcm2835_gpio_write( LCD_DB5, HIGH ); bcm2835_gpio_write( LCD_DB4, HIGH ); bcm2835_gpio_write( LCD_E, HIGH ); lcd_strobe(); bcm2835_delay( 5 ); // 初期化フェーズ2 lcd_strobe(); bcm2835_delayMicroseconds( 100LL ); // 初期化フェーズ3 lcd_strobe(); // 初期化フェーズ4 bcm2835_gpio_write( LCD_DB4, LOW ); lcd_strobe(); // ファンクション設定( 2 Line 5×10 dots) lcd_strobe(); bcm2835_gpio_write( LCD_DB7, HIGH ); bcm2835_gpio_write( LCD_DB6, HIGH ); lcd_strobe(); bcm2835_delayMicroseconds( 40LL ); // 通常のクリア処理 lcd_clear(); } //****************************************************************************** //* LCDモジュールにデータ/コマンドの書き込みを行います //* //* Function Name //* void lcd_write( int rs, unsigned char data ) //* Arguments //* int rs register select 0:command, 1: data //* unsigned char data byte data //* Return //* none //* //****************************************************************************** void lcd_write( int rs, unsigned char data ) { bcm2835_gpio_write( LCD_R_W, LOW ); bcm2835_gpio_write( LCD_RS, rs ); bcm2835_gpio_write( LCD_DB7, (data >> 7) & 0x01 ); bcm2835_gpio_write( LCD_DB6, (data >> 6) & 0x01 ); bcm2835_gpio_write( LCD_DB5, (data >> 5) & 0x01 ); bcm2835_gpio_write( LCD_DB4, (data >> 4) & 0x01 ); lcd_strobe(); bcm2835_gpio_write( LCD_DB7, (data >> 3) & 0x01 ); bcm2835_gpio_write( LCD_DB6, (data >> 2) & 0x01 ); bcm2835_gpio_write( LCD_DB5, (data >> 1) & 0x01 ); bcm2835_gpio_write( LCD_DB4, data & 0x01 ); lcd_strobe(); bcm2835_delayMicroseconds( 40LL ); } //****************************************************************************** //* LCDモジュールに文字列を表示します。 //* //* Function Name //* void lcd_print( int line, char *str ) //* Arguments //* int line target position 0:first line, 1:second line //* char *str string data //* Return //* none //* //****************************************************************************** void lcd_print( int line, char *str ) { int i; int data; data = (line * 0x40) || 0x80; lcd_write( 0, data ); for( i=0; i<16; i++) { lcd_write( 1, 0x20 ); } data = (line * 0x40) || 0x80; lcd_write( 0, data ); for( i=0; i<strlen(str); i++ ) { lcd_write( 1, (unsigned char)str[i] ); } } int main(int argc, char **argv) { lcd_init(); lcd_print( 0, "test123" ); lcd_print( 1, "########" ); return( 0 ); }
サンプルのLEDチカチカがありますので、テストします。
LEDはGPIO-17(コネクタP1の11)に接続し、1秒間隔で点滅(ON:500ms、OFF:500ms)します。# cd examples/ # cd blink/ # gcc blink.c -o blink_led -l rt -l bcm2835 # ./blink_led
※-l rt はreal-time extensionsです。(RTカーネルではないので、意味ないかもしれませんが)
お疲れ様でした。