2015-06-11 09:42 | カテゴリ:PIC応用回路
並行して進めていたPICプログラミングですが、右往左往しつつも、今度は40文字x4行の液晶パネルのドライブプログラムが出来ました。

この液晶パネルはかなり古い機種のため、インターフェスは最低でも4ビットのデータ(2度の送信で8ビットを送る)と3本のコントロール信号の合計7ビットのポートを使用してPICと接続します。
以前に、この液晶パネルを搭載した、コントロール用の基板を製作していましたので、それをそのまま利用して、C言語のプログラミングの勉強に役立てることにしました。

以前に組み上げていたアセンブラのプログラムとニラメッコして、液晶のコントロールの手順を、C言語に置き換えて、液晶の初期化やBUSY信号の処理、また、文字の表示などの関数を組んでいきました。
悪戦苦闘の3日間の末、予定した液晶のコントロールプログラムが完成しました。

PICは16F876を使用しています。
PICの接続ポートの部分の定義を変更すれば、移植も簡単だと思います。
参考までにXC8のmainプログラムをダウンロードできるようにアップしておきます。
これは、MPLABXで標準で提供されるライブラリだけで動作します。
このmainプログラムをSourceのフォルダーに組み込んでコンパイルすればOKです。

動作状況は、こんな感じです。




XC8言語のソースリストは続きで

下記はSOURCEリストです。
MPLABXのXC8のSOURCEフォルダーに読み込んでコンパイルすれば、動作するはずです。
4ビットのデータポートは、RB0-3に接続してあります。
その他のコントロール信号は、プログラム中に記載してありますので、参考にしてください。


/* ==============================================================
* (注)ネットワークのプロジェクトは、XやYドライブから指定すること。
*  コンパイル時にエラーとなる
* ==============================================================
* RS232通信使用時は、TX・RXの入出力を設定する事
*
*
* LCD表示器(4ビット制御)コントロール用プログラム
* File: newmainV06.c
* Author: Nobuaki
* 40文字 X 4行 表示
* Main以外の関数完成。コンパイルOK(newmainV02)
* Main関数の製作テスト開始(newmainV05)
* 1) LED点滅(確認)
* 2) LCD単独文字表示(確認)2015-06-09 Ver3
* 3) 連続文字表示製作(確認) 2015-06-09 Ver4
* 4) 表示スピード最適化、Busy関数チェック(確認)2015-06-10 ver5
* 5) イニシャライズルーチンの整理簡素化(確認)2015-06-10 ver6
* 6) カーソル設定追加(確認)デモモード繰り返し 2015-06-10 Ver7
*
*
*
* Created on 2015/06/08, 13:01
*/

#include
#include
#include

// PIC16F876 初期設定
#pragma config FOSC = HS //高速オシレーター(4MHz以上)使用
#pragma config WDTE = OFF //ウォッチドッグタイマーOFF
#pragma config CP = OFF //コードプロテクションOFF
#pragma config PWRTE = ON //パワーアップタイマーON
#pragma config LVP = OFF//

//液晶制御信号の出力ポートの定義
#define _XTAL_FREQ 20000000 //PICのクロックをHzで設定(20MHz)
#define LCD_E RA0
#define LCD_RS RA2
#define LCD_RW RA1

//動作確認LEDのポート
#define RED_LED RC6 // HでLEDが点灯
#define YELLOW_LED RC7
#define GREEN_LED RC1



//変数
unsigned char cmd;
unsigned char msg[] = "Programed by";
unsigned char p=0;
unsigned char str[21];


//関数定義領域
void Lcd_cmd_put(unsigned char);
void Lcd_cmd(unsigned char);
void Lcd_data_put(unsigned char);
void Lcd_data(unsigned char);
void Lcd_busy(void);
void Lcd_ini(void);
void PIC_ini(void);
void Lcd_Set(void);
void Lcd_disp (const char *p);
void Lcd_cursor(unsigned char, unsigned char);



main() {


//Initialize PIC
PIC_ini();

//LED Blink Test





//LCD初期化はOK
Lcd_ini(); //LCD startup initialization
Lcd_Set(); //LCD Cursor / blink setting

//繰り返しデモモード
while (1){

RED_LED = 1;
YELLOW_LED = 1;
GREEN_LED = 1;
__delay_ms(1000);
RED_LED = 0;
YELLOW_LED = 0;
GREEN_LED = 0;

Lcd_busy();
Lcd_cmd(0x00 + 0x80); //Set cursor
Lcd_busy();

Lcd_data(0x4F); // Show OK
Lcd_data(0x4B);

__delay_ms(1000);



//デモ サンプル文字表示
Lcd_Set();
Lcd_cmd(0x00 + 0x80);
Lcd_disp("LCD display driver");

Lcd_cmd(0x40 + 0x80);
Lcd_disp(msg);

Lcd_cmd(0x14 + 0x80);
Lcd_disp(" @ Vividhobby");

Lcd_cmd(0x54 + 0x80);
Lcd_disp("with PIC XC8 : 2015");
__delay_ms(1000);

//デモ カーソル移動文字表示
Lcd_Set();
Lcd_cursor(10,3);
Lcd_disp("ABC");

Lcd_cursor(9,2);
Lcd_disp("ABC");

Lcd_cursor(8,1);
Lcd_disp("ABC");

Lcd_cursor(7,0);
Lcd_disp("ABC");

__delay_ms(1000);

}


//ループで待機する
while(1) {
GREEN_LED ^=1;
__delay_ms(50);
}
}

// Message Display
void Lcd_disp(const char *p){
while(*p !='\0'){
Lcd_data(*p);
p++;
Lcd_busy();
}
}

//LCD Cursor set
void Lcd_cursor(unsigned char x, unsigned char y){
unsigned char adrs;
switch (y){
case 0: adrs = 0x00; break;
case 1: adrs = 0x40; break;
case 2: adrs = 0x14; break;
case 3: adrs = 0x54; break;
default: break;
}
adrs = adrs + x + 0x80;
Lcd_cmd(adrs);
}



// LCD Initialize
void Lcd_Set(void){
Lcd_busy;
Lcd_cmd(0x01); //表示クリア
Lcd_busy();
Lcd_cmd(0x0C); //カーソルOFF、ブリンクOFF
}

// Put 4 bit command to LCD
void Lcd_cmd_put(unsigned char cmd4){
PORTB = cmd4;
LCD_RW = 0;
LCD_RS = 0;
LCD_E = 1;
__delay_ms(2); // 1msec is not enough
LCD_E = 0;
}


// Send command to LCD
void Lcd_cmd(unsigned char cmd){
// Lcd_busy();
Lcd_cmd_put((cmd >>4) & 0x0F);
Lcd_cmd_put(cmd & 0x0F);
}


// Put 4 bit data to LCD
void Lcd_data_put(unsigned char dt4){
PORTB = dt4;
LCD_RW = 0;
LCD_RS = 1;
LCD_E = 1;
__delay_ms(2); // 1msec is not enough
LCD_E = 0;
}
// Send Data to LCD
void Lcd_data(unsigned char dt){
// Lcd_busy();
Lcd_data_put((dt >>4) & 0x0F);
Lcd_data_put(dt & 0x0F);
}

// Busy Check
void Lcd_busy(void){
unsigned char BZF=0xFF;
unsigned char dmy;
TRISB = 0xFF;

while((BZF & 0x08) != 0){
RED_LED = 1;
LCD_RS = 0;
LCD_RW = 1;
LCD_E = 1;
BZF = PORTB;
LCD_E = 0;
LCD_E = 1;
dmy = PORTB;
LCD_E = 0;
}
RED_LED = 0;
LCD_RW = 0;
TRISB = 0b11110000;

}
// LCD Start up initialization
void Lcd_ini(void){
GREEN_LED = 1;
__delay_ms(20);
Lcd_cmd_put(3);
__delay_ms(10);
Lcd_cmd_put(3);
__delay_ms(10);
Lcd_cmd_put(3);
__delay_ms(10);
Lcd_cmd_put(2);
Lcd_cmd_put(2);
Lcd_cmd_put(8);
Lcd_cmd_put(0);
Lcd_cmd_put(8);
Lcd_cmd_put(0);
Lcd_cmd_put(1);
Lcd_cmd_put(0);
Lcd_cmd_put(6);
__delay_ms(10);
GREEN_LED = 0;
}

//PIC Initialize
void PIC_ini(void){

TRISA = 0b00000000;
TRISB = 0b11110000;
TRISC = 0b00000000;
ADCON1= 0b00000110;
OPTION_REG = 0b10111111; //Port B pull-up off (bit7)
INTCON = 0b00000000;
}




管理者のみに表示する