神原です.
初投稿となりますがよろしくお願いします.
秋月などで売っている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