トップページ > dsPIC入門 > キャラクタLCDの使い方(2)
//********************************************************************
//LCD用ヘッダファイル
//(ROM太郎)
//********************************************************************
//********************************************************************
//ハードウェアについて(変更可)
//********************************************************************
//[LCD側]--->[dsPIC側]
//RB4〜RB7--->PORTBbits.RB0〜PORTBbitsRE3
//RS--->PORTDbits.RF0
//R/W--->常に書き込みだけなのでGNDへ接続。
//E--->PORTDbits.RF1
//********************************************************************
//関数プロトタイプ宣言
//********************************************************************
void lcd_display(char* string,int line);
void set_position(char line,char shift);
void all_erase(void);
void lcd_ini(void);
void send_char(char data);
void send_cmd(char data);
void lcd_wait(void);
void lcd_display_num(int data,int line);
//====================================================================
//LCDへ文字列を書き込む関数
void lcd_display(char* string,int line)
{
//for文用変数
int i;
switch(line)
{
case 1:
set_position(1,0);
for(i=0;i<16;i++)
{
send_char(' ');
}
set_position(1,0);
break;
case 2:
set_position(2,0);
for(i=0;i<16;i++)
{
send_char(' ');
}
set_position(2,0);
break;
}
//文字列の最後(ヌル文字)までループ
while(*string != '\0')
{
//1文字表示関数を呼び出します。
send_char(*string);
//次の文字を読み込みます。(配列はアドレスの値が連続しているから…。)
string++;
}
}
//====================================================================
//カーソル位置を移動する関数
void set_position(char line,char shift)
{
//----------------------------------------------------------------------
//まず、行を決定。
//0x08を送れば1行目、0x0cを送れば2行目です。
switch(line)
{
case 1:
send_cmd(0x08);
break;
case 2:
send_cmd(0x0c);
break;
default:
break;
}
//----------------------------------------------------------------------
//次に、文字位置を決定。
//表示したい位置をそのまま送るだけ。(左から数えて・・・)
send_cmd(shift);
}
//====================================================================
//全消し関数
void all_erase(void)
{
//for文用変数
int i;
set_position(1,0);
for(i=0;i<16;i++)
{
send_char(' ');
}
set_position(2,0);
for(i=0;i<16;i++)
{
send_char(' ');
}
set_position(1,0);
}
//====================================================================
//LCD初期設定関数(4bitモード)
void lcd_ini(void)
{
//----------------------------------------------------------------------
//ポート設定
TRISB=0x00;
TRISD=0x00;
//----------------------------------------------------------------------
//電源投入直後、LCD起動待ち(コメントアウト可)
unsigned int i;
for(i=0;i<60000;i++);
for(i=0;i<60000;i++);
for(i=0;i<60000;i++);
for(i=0;i<60000;i++);
//----------------------------------------------------------------------
//最初は8bitモードに設定。(とりあえずここから始める)
send_cmd(0x03);
send_cmd(0x03);
send_cmd(0x03);
//----------------------------------------------------------------------
//4bitモードに設定。
send_cmd(0x02);
//----------------------------------------------------------------------
//これ以降、8bitデータを2回に分けて送信する感じになります。
//でも、8bitの制御データを送信する関数を作るのも煩雑なので、
//4bit送信関数を使っていきます。
//2桁表示モードに設定。
send_cmd(0x02);
send_cmd(0x08);
//ディスプレイOFF,カーソルOFF,ブリンクOFF
send_cmd(0x00);
send_cmd(0x0c);
//エントリーモード設定。カーソルは右移動、表示内容のシフトは無し。
send_cmd(0x00);
send_cmd(0x06);
//----------------------------------------------------------------------
//とりあえず全消し
set_position(1,0);
for(i=0;i<16;i++)
{
send_char(' ');
}
set_position(2,0);
for(i=0;i<16;i++)
{
send_char(' ');
}
}
//====================================================================
//LCDへ1文字分のデータを書き込む関数
void send_char(char data)
{
//文字データなので、RSを1に。
PORTD=0x01;
//data_tempは下位4bit保存用。
char data_temp = data;
//上位4bitを抜き出します。
data=data>>4;
data&=0x0f;
//下位4bitを抜き出します。
data_temp&=0x0f;
//-------------------------------------------------------------------------------------------------------------------------
//以下、データ送信作業
//上位4bitを送信
PORTB = data;
lcd_wait();
//Eを1にして、待機。そのあとまた0に戻す。
//RSは1のまま。
PORTD=0x01;
lcd_wait();
PORTD=0x03;
lcd_wait();
PORTD=0x01;
//下位4bitを送信
PORTB = data_temp;
lcd_wait();
//Eを1にして、待機。そのあとまた0に戻す。
//RSは1のまま。
PORTD=0x01;
lcd_wait();
PORTD=0x03;
lcd_wait();
PORTD=0x01;
//念のため、待機。
lcd_wait();
}
//====================================================================
//LCDへ制御コードを書き込む関数
void send_cmd(char data)
{
//制御コードなので、RSは0に。
PORTD=0x00;
//データを送信。
PORTB = data;
lcd_wait();
//Eを1にして、待機。そのあとまた0に戻す。
//RSは0のまま。
PORTD=0x00;
lcd_wait();
PORTD=0x02;
lcd_wait();
PORTD=0x00;
//念のため、待機。
lcd_wait();
}
//====================================================================
//ディレイ発生関数
void lcd_wait(void)
{
unsigned int t;
for(t=0;t<1000;t++);
}
//====================================================================
//LCDへ文字列を書き込む関数
void lcd_display_num(int data,int line)
{
//for文用変数
int i;
int j;
int string_index=0;
char num_string[7];
char temp_string[7];
int temp;
int m_flag=0;
int z_flag=0;
temp = data;
if(data<0)
{
data = -data;
m_flag=1;
}
if(data==0)
{
z_flag=1;
}
while(data>0)
{
temp = data%10;
//数値を文字列にする作業…。
switch(temp)
{
case 0:
temp_string[string_index] = '0';
break;
case 1:
temp_string[string_index] = '1';
break;
case 2:
temp_string[string_index] = '2';
break;
case 3:
temp_string[string_index] = '3';
break;
case 4:
temp_string[string_index] = '4';
break;
case 5:
temp_string[string_index] = '5';
break;
case 6:
temp_string[string_index] = '6';
break;
case 7:
temp_string[string_index] = '7';
break;
case 8:
temp_string[string_index] = '8';
break;
case 9:
temp_string[string_index] = '9';
break;
default:
temp_string[string_index] = '?';
break;
}
//次の位へいきます。
data/=10;
string_index++;
}
if(z_flag==0 && m_flag==0)
{
j=string_index;
j--;
for(i=0;i<string_index;i++)
{
num_string[i]=temp_string[j-i];
}
for(i=string_index;i<7;i++)
{
num_string[i]=0;
}
}
if(m_flag==1)
{
num_string[0]='-';
j=string_index;
j--;
for(i=0;i<string_index;i++)
{
num_string[i+1]=temp_string[j-i];
}
for(i=string_index+1;i<7;i++)
{
num_string[i]=0;
}
}
if(z_flag==1)
{
num_string[0]='0';
for(i=1;i<7;i++)
{
num_string[i]=0;
}
}
lcd_display(num_string,line);
}