LCDライブラリ for Sunlike Display Tech. Corp.

神原です.
初投稿となりますがよろしくお願いします.

秋月などで売っているSunlike Display Tech. Corp.製 キャラクタ液晶用のLCDライブラリを作成しましたので紹介します.
本ライブラリはPICだけでなく他のマイコンにも簡単に移植できるようになっています.

ライブラリを構成するファイル

  • LCD_lib_Sunlike.h    ライブラリ本体
  • HardwareProfile_LCD.h 各種マイコンに対応させるためのユーザー設定項目がかかれたファイル

ユーザーは”HardwareProfile_LCD.h”のみを書き換える必要があります.

“HardwareProfile_LCD.h”内の設定項目

  • ピン設定 液晶の各ピンをマイコンのどのピンに接続するのかを設定
  • delay設定 ライブラリで用いるdelayの設定

本ライブラリではChaNさんの作成したxprintf関数を組み込みました.

ユーザーが使用する関数


void lcd_init();			----- 初期化
void lcd_clear();			----- 全消去
void lcd_cur_home();			----- カーソルをHome(1行目)へ移動
void lcd_first_line()			----- 1行目へ移動(多分lcd_cur_homeと同じ効果だがこちらはより高速)
void lcd_second_line();			----- 2行目へ移動
void lcd_third_line();			----- 3行目へ移動(4行LCDのみ)
void lcd_fourth_line();			----- 4行目へ移動(4行LCDのみ)
void lcd_print_text(char *);		----- 文字列表示(例:lcd_print_text("Hello PIC!");
void LCD_xprintf(const char*,...);	----- 文字列表示(例:LCD_xprintf("%d\n%d", 1, 2);

ライブラリのダウンロード

ライブラリはここからダウンロードできます.dsPIC33FJ128MC302を用いた場合のサンプルコードも置いておきましたので,よろしければ参考にしてください.

ライブラリのソースコード

  • HardwareProfile_LCD.h

/******************************************************************************
 *
 *                       Hardware Profile for LCD library
 *
 *   Sunlike Display Tech. Corp.製液晶表示器制御ライブラリ(LCD (SCxxxx) を4bitモードで使用)
 *    ピン配置が同じで3.3V駆動のLCD(SC1602BBWB-XA-LB-G)や20文字×4行のLCDにも対応
 *        ライブラリに必要なファイル: "LCD_lib_Sunlike.h", "HardwareProfile_LCD.h"
 *
 *         ユーザーはこのファイルの設定を変えることでLCDライブラリ使用可能
 *                     "LCD_lib_Sunlike.h"は変えなくてよい
 *
 *           mainプログラムでは"LCD_lib_Sunlike.h"のみをインクルードする
 *
 *        ※このライブラリの全てのファイルはmainファイルと同じディレクトリに配置する
 *
 ******************************************************************************/

#ifndef _HARDWAREPROFILE_LCD_H_		//重複回避
#define _HARDWAREPROFILE_LCD_H_

#ifndef LCD_LIB_SUNLIKE_H
	#error PrivateError : please define only "LCD_lib_Sunlike.h" when you use LCD library.
#endif

/* ユーザー設定項目 ----------------------------------------------------------*/
/* ピン設定 --------------------------------------------------------*/
#define LCD_PIN_STATE_SETTING_ON	// 各I/Oピンの入出力設定ON (使わないならばこの行をコメントアウト)

#define LCD_Enable_HIGH			LATBbits.LATB7=1	// Enable信号ピン(プルダウン)をHIGH
#define LCD_Enable_LOW			LATBbits.LATB7=0	//                             LOW
#define LCD_RS_HIGH				LATBbits.LATB6=1	// RS信号ピン
#define LCD_RS_LOW				LATBbits.LATB6=0
#define LCD_DataBit4_HIGH		LATBbits.LATB5=1	// Data Bit 4
#define LCD_DataBit4_LOW		LATBbits.LATB5=0
#define LCD_DataBit5_HIGH		LATAbits.LATA3=1	// Data Bit 5
#define LCD_DataBit5_LOW		LATAbits.LATA3=0
#define LCD_DataBit6_HIGH		LATAbits.LATA4=1	// Data Bit 6
#define LCD_DataBit6_LOW		LATAbits.LATA4=0
#define LCD_DataBit7_HIGH		LATBbits.LATB4=1	// Data Bit 7
#define LCD_DataBit7_LOW		LATBbits.LATB4=0

#ifdef LCD_PIN_STATE_SETTING_ON
#define LCD_Enable_Output		TRISBbits.TRISB7=0	// Enable信号ピンをOutputに設定
#define LCD_RS_Output			TRISBbits.TRISB6=0	// RS信号ピン
#define LCD_DataBit4_Output		TRISBbits.TRISB5=0	// Data Bit 4
#define LCD_DataBit5_Output		TRISAbits.TRISA3=0	// Data Bit 5
#define LCD_DataBit6_Output		TRISAbits.TRISA4=0	// Data Bit 6
#define LCD_DataBit7_Output		TRISBbits.TRISB4=0	// Data Bit 7
#endif // LCD_PIN_STATE_SETTING_ON
/*-------------------------------------------------------- ピン設定 */

/* delayの定義 -----------------------------------------------------*/
#include 	// dsPICでdelay関数を使用 (FCYを定義しておくことが必要)

#define LCD_DELAY_300ns		Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop()//__delay_us(1)
#define LCD_DELAY_1us		__delay_us(1)
#define LCD_DELAY_50us		__delay_us(50)
#define LCD_DELAY_1ms		__delay_ms(1)
#define LCD_DELAY_2ms		__delay_ms(2)
#define LCD_DELAY_15ms		__delay_ms(15)
#define LCD_DELAY_100ms		__delay_ms(100)
/*----------------------------------------------------- delayの定義 */
/*---------------------------------------------------------- ユーザー設定項目 */

#endif	// _HARDWAREPROFILE_LCD_H_

  • LCD_lib_Sunlike.h

/******************************************************************************
 *
 *                         Header File for LCD library
 *
 *   Sunlike Display Tech. Corp.製液晶表示器制御ライブラリ(LCD (SCxxxx) を4bitモードで使用)
 *    ピン配置が同じで3.3V駆動のLCD(SC1602BBWB-XA-LB-G)や20文字×4行のLCDにも対応
 *        ライブラリに必要なファイル: "LCD_lib_Sunlike.h", "HardwareProfile_LCD.h"
 *
 *      ユーザーは"HardwareProfile_LCD.h"の設定を変えることでLCDライブラリ使用可能
 *                     "LCD_lib_Sunlike.h"は変えなくてよい
 *
 *           mainプログラムでは"LCD_lib_Sunlike.h"のみをインクルードする
 *
 *        ※このライブラリの全てのファイルはmainファイルと同じディレクトリに配置する
 *
 ******************************************************************************/

/**********************************************
*  ユーザーが主に使用する関数は以下
* void lcd_init();					----- 初期化
* void lcd_clear();					----- 全消去
* void lcd_cur_home();				----- カーソルをHome(1行目)へ移動
* void lcd_first_line()				----- 1行目へ移動(多分lcd_cur_homeと同じ効果だがこちらはより高速)
* void lcd_second_line();			----- 2行目へ移動
* void lcd_third_line();			----- 3行目へ移動(4行LCDのみ)
* void lcd_fourth_line();			----- 4行目へ移動(4行LCDのみ)
* void lcd_print_text(char *);		----- 文字列表示(例:lcd_print_text("Hello PIC!");
* void LCD_xprintf(const char*,...);----- 文字列表示(例:LCD_xprintf("%d\n%d", 1, 2);
************************************************/

#ifndef LCD_LIB_SUNLIKE_H		//重複回避
#define LCD_LIB_SUNLIKE_H

#include 
#include "HardwareProfile_LCD.h"			// 各種マイコンへの移植用設定(ピンなど)を格納

/*****
 実行時間( 5.0V, 3.3V駆動の16字×2行, 20字×4行の計4種のLCD全てで動作するのに最低限必要な時間)
Tcyce	1200[ns]		// イネーブルサイクル時間
PWeh	460	[ns]		// イネーブルパルス幅
Ter,Tef	25	[ns]		// イネーブル立ち上がり,立下り時間(MIN)
Tas		140	[ns]		// セットアップ時間
Tah		10	[ns]		// アドレスホールド時間
Tdsw	195	[ns]		// データセットアップ時間
Th		10	[ns]		// データホールド時間

reset, home		1.64[ms]	// カーソルリセット,ホーム移動時間
DataSend		40  [us]	// データ送信後の待ち時間
*****/

/************************************************/
/* ChaNさんのLCD_xprintfモジュール              */
/************************************************/
#include 
#define	LCD_CR_CRLF		0	/* 1: Convert \n ==> \r\n in the output char */
void (*LCD_xfunc_out)(unsigned char);	/* Pointer to the output stream */
static char *LCD_outptr;
#define LCD_xdev_out(func) LCD_xfunc_out=(void(*)(unsigned char))(func)
void LCD_xputc (char c);
void LCD_xputs (const char* str);
void LCD_xfputs (void (*func)(unsigned char), const char* str);
void LCD_xprintf (const char* fmt, ...);
void LCD_xsprintf (char* buff, const char* fmt, ...);
void LCD_xfprintf (void (*func)(unsigned char), const char*	fmt, ...);
void LCD_put_dump (const void* buff, uint32_t addr, int16_t len, int16_t width);
#define LCD_DW_CHAR		sizeof(char)
#define LCD_DW_SHORT	sizeof(int16_t)
#define LCD_DW_LONG		sizeof(uint32_t)

unsigned char LCD_lib_line_num;

/******** 全消去関数 (初期化コマンド出力) *********/
#define		lcd_clear()			lcd_cmd(0x01)

/******** カーソルをHome(1行目)に移動 *********/
#define		lcd_cur_home()		lcd_cmd(0x02)

/******** 1行目へアドレス移動 *********/
#define		lcd_first_line()	lcd_cmd(0x80 | 0x00)

/******** 2行目へアドレス移動 *********/
#define		lcd_second_line()	lcd_cmd(0x80 | 0x40)

/******** 3行目へアドレス移動(4行LCDのみ) *********/
#define		lcd_third_line()	lcd_cmd(0x80 | 0x14)

/******** 4行目へアドレス移動(4行LCDのみ) *********/
#define		lcd_fourth_line()	lcd_cmd(0x80 | 0x54)

/********* データ出力サブ関数 **************/
void lcd_out(unsigned char code, unsigned char flag)
{
	//上位4ビット
	if( (code>>7) & 0x01) {LCD_DataBit7_HIGH;}  else  {LCD_DataBit7_LOW;}
	if( (code>>6) & 0x01) {LCD_DataBit6_HIGH;}  else  {LCD_DataBit6_LOW;}
	if( (code>>5) & 0x01) {LCD_DataBit5_HIGH;}  else  {LCD_DataBit5_LOW;}
	if( (code>>4) & 0x01) {LCD_DataBit4_HIGH;}  else  {LCD_DataBit4_LOW;}
	if (flag == 0){
		LCD_RS_HIGH;	//表示データの場合
	} else {
		LCD_RS_LOW;		//コマンドデータの場合
	}
	LCD_DELAY_300ns;	// over 200us
	LCD_Enable_HIGH;	//strobe out
	LCD_DELAY_1us;		// over 800us
	LCD_Enable_LOW;		//reset strobe
	LCD_DELAY_300ns;	// over 200us
}

/******** 1文字表示関数 **********/
void lcd_data(unsigned char asci)
{
	lcd_out(asci, 0);		//上位4ビット出力
	lcd_out(asci << 4, 0);	//下位4ビット出力
	LCD_DELAY_50us;			//40us以上wait
}

/******** コマンド出力関数 ********/
void lcd_cmd(unsigned char cmd)
{
	lcd_out(cmd, 1);		//上位4ビット出力
	lcd_out(cmd << 4, 1);	//下位4ビット出力
	if( (cmd & 0xFC) == 0){
		LCD_DELAY_2ms;		// Clear_DisplayかClear At Homeのとき (over 1.64[ms])
	} else {
		LCD_DELAY_50us;		//その他の場合(over 40[us])
	}
}

/******** LCD_xprintf用関数 **********/
void lcd_StringData(unsigned char asci)
{
	if(asci == '\n')
	{
		if(LCD_lib_line_num == 1) {
			LCD_lib_line_num++;
			lcd_second_line();
		} else if(LCD_lib_line_num == 2) {
			LCD_lib_line_num++;
			lcd_third_line();
		} else if(LCD_lib_line_num == 3) {
			LCD_lib_line_num++;
			lcd_fourth_line();
		} else {
			LCD_lib_line_num = 1;
			lcd_first_line();
		}
		return;
	}
	if(asci == '')
	{
		LCD_lib_line_num = 1;
		lcd_first_line();
	}
	lcd_out(asci, 0);		//上位4ビット出力
	lcd_out(asci << 4, 0);	//下位4ビット出力 	LCD_DELAY_50us;			//40us以上wait } /******** 初期化関数 *********/ void lcd_init(void) { #ifdef LCD_PIN_STATE_SETTING_ON 	//ピンの入出力設定 	LCD_Enable_Output; 	LCD_RS_Output; 	LCD_DataBit4_Output; 	LCD_DataBit5_Output; 	LCD_DataBit6_Output; 	LCD_DataBit7_Output; #endif // LCD_PIN_STATE_SETTING_ON 	 	 	LCD_DELAY_100ms;		//wait more than 15ms(40ms) after Vcc rises to 4.5V(2.7V) 	lcd_out(0x30, 1);		//8bit mode set 	LCD_DELAY_15ms;			//wait more than 4.1ms 	lcd_out(0x30, 1);		//8bit mode set 	LCD_DELAY_1ms;			//wait more than 100us 	lcd_out(0x30, 1);		//8bit mode set 	LCD_DELAY_1ms; 	lcd_out(0x20, 1);		//4bit mode set 	LCD_DELAY_1ms; 	 	lcd_cmd(0x2E);		//DL=0 4bit mode 	LCD_DELAY_1ms; 	lcd_cmd(0x80);		//display off C=D=B=0 	LCD_DELAY_1ms; 	lcd_cmd(0x0D);		//display on C=D=1 B=0 	LCD_DELAY_1ms; 	lcd_cmd(0x06);		//entry I/D=1 S=0 	LCD_DELAY_1ms; 	lcd_cmd(0x02);		//cursor home 	LCD_DELAY_1ms; 	 	lcd_clear(); 	 	LCD_xdev_out(lcd_StringData);	// LCD_xprintfをLCDに関連付け } /******** 文字列表示関数 **********/ void lcd_print_text(char *char_array) { 	while(*char_array != '') 	{ 		lcd_data(*char_array);	//ポインタで示すアドレス内のデータを引数に 		char_array++;			//ポインタの値を一つ増やして次のデータへ 	} } /************************************************/ /************************************************/ /* ChaNさんのLCD_xprintfモジュール              */ /************************************************/ /************************************************/ /*----------------------------------------------*/ /* Put a character                              */ /*----------------------------------------------*/ void LCD_xputc (char c) { 	if (LCD_CR_CRLF && c == '\n') LCD_xputc('\r');		/* CR -> CRLF */

	if (LCD_outptr) {
		*LCD_outptr++ = (unsigned char)c;
		return;
	}

	if (LCD_xfunc_out) LCD_xfunc_out((unsigned char)c);
}

/*----------------------------------------------*/
/* Put a null-terminated string                 */
/*----------------------------------------------*/

void LCD_xputs (					/* Put a string to the default device */
	const char* str				/* Pointer to the string */
)
{
	while (*str)
		LCD_xputc(*str++);
}

void LCD_xfputs (					/* Put a string to the specified device */
	void(*func)(unsigned char),	/* Pointer to the output function */
	const char*	str				/* Pointer to the string */
)
{
	void (*pf)(unsigned char);

	pf = LCD_xfunc_out;		/* Save current output device */
	LCD_xfunc_out = func;	/* Switch output to specified device */
	while (*str)		/* Put the string */
		LCD_xputc(*str++);
	LCD_xfunc_out = pf;		/* Restore output device */
}

/*----------------------------------------------*/
/* Formatted string output                      */
/*----------------------------------------------*/
/*  LCD_xprintf("%d", 1234);			"1234"
	LCD_xprintf("%6d,%3d%%", -200, 5);	"  -200,  5%"
	LCD_xprintf("%-6u", 100);			"100   "
	LCD_xprintf("%ld", 12345678L);		"12345678"
	LCD_xprintf("%04x", 0xA3);			"00a3"
	LCD_xprintf("%08LX", 0x123ABC);		"00123ABC"
	LCD_xprintf("%016b", 0x550F);		"0101010100001111"
	LCD_xprintf("%s", "String");		"String"
	LCD_xprintf("%-4s", "abc");			"abc "
	LCD_xprintf("%4s", "abc");			" abc"
	LCD_xprintf("%c", 'a');				"a"
	LCD_xprintf("%f", 10.0);			<LCD_xprintf lacks floating point support>
*/

static
void LCD_xvprintf (
	const char*	fmt,	/* Pointer to the format string */
	va_list arp			/* Pointer to arguments */
)
{
	uint16_t r, i, j, w, f;
	uint32_t v;
	char s[16], c, d, *p;

	for (;;) {
		c = *fmt++;					/* Get a char */
		if (!c) break;				/* End of format? */
		if (c != '%') {				/* Pass through it if not a % sequense */
			LCD_xputc(c); continue;
		}
		f = 0;
		c = *fmt++;					/* Get first char of the sequense */
		if (c == '0') {				/* Flag: '0' padded */
			f = 1; c = *fmt++;
		} else {
			if (c == '-') {			/* Flag: left justified */
				f = 2; c = *fmt++;
			}
		}
		for (w = 0; c >= '0' && c <= '9'; c = *fmt++)	/* Minimum width */ 			w = w * 10 + c - '0'; 		if (c == 'l' || c == 'L') {	/* Prefix: Size is long int */ 			f |= 4; c = *fmt++; 		} 		if (!c) break;				/* End of format? */ 		d = c; 		if (d >= 'a') d -= 0x20;
		switch (d) {				/* Type is... */
		case 'S' :					/* String */
			p = va_arg(arp, char*);
			for (j = 0; p[j]; j++) ;
			while (!(f & 2) && j++ < w) LCD_xputc(' ');
			LCD_xputs(p);
			while (j++ < w) LCD_xputc(' '); 			continue; 		case 'C' :					/* Character */ 			LCD_xputc((char)va_arg(arp, int16_t)); continue; 		case 'B' :					/* Binary */ 			r = 2; break; 		case 'O' :					/* Octal */ 			r = 8; break; 		case 'D' :					/* Signed decimal */ 		case 'U' :					/* Unsigned decimal */ 			r = 10; break; 		case 'X' :					/* Hexdecimal */ 			r = 16; break; 		default:					/* Unknown type (passthrough) */ 			LCD_xputc(c); continue; 		} 		/* Get an argument and put it in numeral */ 		v = (f & 4) ? va_arg(arp, int32_t) : ((d == 'D') ? (int32_t)va_arg(arp, int16_t) : (int32_t)va_arg(arp, uint16_t)); 		if (d == 'D' && (v & 0x80000000)) { 			v = 0 - v; 			f |= 8; 		} 		i = 0; 		do { 			d = (char)(v % r); v /= r; 			if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
			s[i++] = d + '0';
		} while (v && i < sizeof(s));
		if (f & 8) s[i++] = '-';
		j = i; d = (f & 1) ? '0' : ' ';
		while (!(f & 2) && j++ < w) LCD_xputc(d);
		do LCD_xputc(s[--i]); while(i);
		while (j++ < w) LCD_xputc(' ');
	}
}

void LCD_xprintf (			/* Put a formatted string to the default device */
	const char*	fmt,	/* Pointer to the format string */
	...					/* Optional arguments */
)
{
	va_list arp;

	LCD_lib_line_num = 1;	// 1行目に移動
	va_start(arp, fmt);
	LCD_xvprintf(fmt, arp);
	va_end(arp);
}

void LCD_xsprintf (			/* Put a formatted string to the memory */
	char* buff,			/* Pointer to the output buffer */
	const char*	fmt,	/* Pointer to the format string */
	...					/* Optional arguments */
)
{
	va_list arp;

	LCD_outptr = buff;		/* Switch destination for memory */

	va_start(arp, fmt);
	LCD_xvprintf(fmt, arp);
	va_end(arp);

	*LCD_outptr = 0;		/* Terminate output string with a  */
	LCD_outptr = 0;			/* Switch destination for device */
}

void LCD_xfprintf (					/* Put a formatted string to the specified device */
	void(*func)(unsigned char),	/* Pointer to the output function */
	const char*	fmt,			/* Pointer to the format string */
	...							/* Optional arguments */
)
{
	va_list arp;
	void (*pf)(unsigned char);

	pf = LCD_xfunc_out;		/* Save current output device */
	LCD_xfunc_out = func;	/* Switch output to specified device */

	va_start(arp, fmt);
	LCD_xvprintf(fmt, arp);
	va_end(arp);

	LCD_xfunc_out = pf;		/* Restore output device */
}

/*----------------------------------------------*/
/* Dump a line of binary dump                   */
/*----------------------------------------------*/

void LCD_put_dump (
	const void* buff,		/* Pointer to the array to be dumped */
	uint32_t addr,		/* Heading address value */
	int16_t len,				/* Number of items to be dumped */
	int16_t width				/* Size of the items (DF_CHAR, DF_SHORT, DF_LONG) */
)
{
	int16_t i;
	const unsigned char *bp;
	const uint16_t *sp;
	const uint32_t *lp;

	LCD_xprintf("%08lX ", addr);		/* address */

	switch (width) {
	case LCD_DW_CHAR:
		bp = buff;
		for (i = 0; i < len; i++)		/* Hexdecimal dump */
			LCD_xprintf(" %02X", bp[i]);
		LCD_xputc(' ');
		for (i = 0; i < len; i++)		/* ASCII dump */ 			LCD_xputc((bp[i] >= ' ' && bp[i] <= '~') ? bp[i] : '.');
		break;
	case LCD_DW_SHORT:
		sp = buff;
		do								/* Hexdecimal dump */
			LCD_xprintf(" %04X", *sp++);
		while (--len);
		break;
	case LCD_DW_LONG:
		lp = buff;
		do								/* Hexdecimal dump */
			LCD_xprintf(" %08LX", *lp++);
		while (--len);
		break;
	}

	LCD_xputc('\n');
}

#endif // LCD_LIB_SUNLIKE_H

コメントを残す