キャラクタLCDをアクセス

はじめに

Raspberry Pi 3でCentOS7からのキャラクタLCDへのアクセス方法をまとめました。
過去の資産(秋月のLCD)が何個jかありますので、これらのアクセスについて記します。

HD44780互換IC系

概要

パラレルバスインタフェースといえばこの系統が主流ですね。往年の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 PiLCD
SignalPin#SignalPin#
3V301,173V301
GND34,39GND02
VO(contrast)03
GPIO 2140E06
GPIO 2215R/_W05
GPIO 2316RS04
GPIO 2418D411
GPIO 2522D512
GPIO 2637D613
GPIO 2713D714
  • 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カーネルではないので、意味ないかもしれませんが)

お疲れ様でした。


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS