接続試験用マスタソース
I2C接続LCDの試験用プログラムです。最初に "hello" と"stand by"を表示します。バックライトの点滅、LED
の表示、などのテストも行います。(注:コマンド設計にバグがあり、コマンドとスレーブプログラムを変更しました。プログラムテストはこのマスターソースでは実行していませんから不具合があるかもしれません)
//////////////////////////////////////////////////
// I2Cマスターテストプログラム //
//LCD制御
//I2Cデバイスアドレスは0x74
//コマンド 1:文字列、2:文字列、3:クリア
//ポートB、A0 をLED表示(動作確認用)
#include <16f88.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT
#use delay(clock = 4000000)
#use i2c(MASTER,slow,sda=PIN_B1,scl=PIN_B4)
#use fast_io(B)
#use fast_io(A)
//メイン関数/////////////////////////////////////////
#define lcddva 0x74
#define Leddva 0x64
#define seg6dva 0x62
#include <string.h>
int i,val;
int tm,num;
int loopcnt;
char moji1[]="Hello";
char moji2[]="stand by";
void main(){
val=0;
tm=0;
loopcnt=0;
//set_tris_c(0x99); //RB 7-4:IN 3-0:OUT
output_float(PIN_B1); //I2C pin float
output_float(PIN_B4);
//Cポートに出力する場合、set_tris_c()が必要
set_tris_a(0xF0); //RB 7-4:IN 3-0:OUT
set_tris_b(0xED);
delay_ms(100); //wait for Client up
while(1){
output_bit(PIN_A3,tm);//動作確認
tm = ~tm;
i2c_start();
i2c_write(lcddva);
i2c_write(1);//番地コマンド
i2c_write(1);
i2c_write(2);//行
i2c_write(0);
i2c_stop();
delay_ms(1);
i2c_start();
i2c_write(lcddva);
i2c_write(2);//文字
for(i=0;i<=strlen(moji1);i++){
i2c_write(moji1[i] );
}
i2c_stop();
delay_ms(1);
i2c_start();
i2c_write(lcddva);
i2c_write(1);
i2c_write(1);
i2c_write(1);//1行
i2c_write(0);
i2c_stop();
delay_ms(1);
i2c_start();
i2c_write(lcddva);
i2c_write(2);//文字
for(i=0;i<=strlen(moji2);i++){
i2c_write(moji2[i] );
}
i2c_stop();
loopcnt++;
delay_ms(500);
}
}
I2C接続スレーブソース
割り込みで、0 がクルまで chbuf[] に受信し、0 を受信したら、main 側で、コマンド種別に対応する処理を行います。
(バグ発見:バックライトの設定で 0 を受信すると、次の文字は受信していません。コマンド種別1,2 以外は、固定長としコマンドの最後の0は不要とするよう変更する必要があります。)
//I2C Slave
//Display to LCD
//SD1602:16chara * 2
//LCD data:DB7 RA3,DB6 RA2,DB5 RA1,DB4 RA0
//LCD E:RB3,RW:RB7,RS:RB6,
//CN2: GND,+5V,SCL,SDA
//CN1:VPP,VDD,GND,PDA,PCL
//LED1:RA0,LED2:RA1,LED3:RA2,BackLight:RA3,COMON:RA4
//SW1:RA1,SW2:RA2,SW3:RA3 COMMON RB0
//setcursor :<lcdda><1><x+1><y> x=1-10 y=1,2
//string:<2><char_1>..<char_n><0>
//clear lcd:<lcdda><3><0>
//send command(No effect):<lcdda><4><command><para><0>
//backlight :<lcdda><5><2/1><0>
//set led :<lcdda><6><led_Pat+1><0>
//wait after command send
//問題
//LCDのみ出力してもLEDが点滅する
//2行目のデータが1行目に表示される
#include <16F88.h>
#include <stdlib.h>
#fuses HS,NOWDT,NOLVP,NOBROWNOUT
#use delay(clock = 4000000)
#use I2c(slave,sda=PIN_B1,scl=PIN_B4,address=0x74,FORCE_HW)//address must be EvenNumber
#use fast_io(B)
#use fast_io(A)
#define LineMax 16
//LCD connection
#byte db = 5 // PORTA address
#define Amode 0xE0 //Aport I/O
#define rs PIN_B6 //chip select
#define rw PIN_B7 //read/write
#define stb PIN_B3 //E strobe
void outchbuf(int i);
void lcd_init();//-------- initialize
void lcd_ready();//------- busy check
void lcd_cmd(cmd);//------ send command
void lcd_data(string);//-- display string
void lcd_clear(); //------ clear display
int lcd_status(); //
int ch2;
int state,done;
int cp;
int alt;
char chbuf[17]={2,'h','e','l','l','o','\0'};
int backLight=2;
int ledPat=0;
int ddcm;
#INT_SSP
void ssp_interupt (){
state=i2c_isr_state();
//output_high(PIN_A3);//backLight on
if(state>=0x80){//addrs match with master read
set_tris_a(0x07);
output_low(PIN_B0);
i2c_write((input_a()>>1) & 0x7);//return sw value
set_tris_a(0xE0);
}
else if(state >0){//adrs match with master write
ch2=i2c_read();
chbuf[cp++]=ch2;
if(cp > LineMax) cp--;
if (ch2=='\0') {
//output_toggle(PIN_A3);//check
cp=0;
done=1;
}
}
}
void main (){
set_tris_b(0x36);
set_tris_a(0xE0);
cp=0;
alt=0;
//lpcnt=0;
output_float(PIN_B4); //I2C pin float
output_float(PIN_B1); //I2C pin float
set_tris_b(0x36);
output_low(stb);
output_low(rs);
lcd_init();//set 4bit mode
lcd_clear();
lcd_cmd(0xC0);
lcd_data("stand by");
lcd_cmd(0x80);
enable_interrupts(GLOBAL); //全ての割り込みを許可
enable_interrupts(INT_SSP); //SSP割り込みを許可
//delay_ms(1000);
set_tris_a(0xE0);
done=1;
output_bit(PIN_A4,1);
while (1) {
if(done){
switch(chbuf[0]){
case 1:ddcm=0x80 + chbuf[1]-1;//firstLine
if (chbuf[2]==2) ddcm += 0x40;//second line
lcd_cmd(ddcm);
break;
case 2 :outchbuf(1);//string
break;
case 3:lcd_cmd(0x1);//clear
break;
case 4://lcd_cmd(chbuf[1]);
//outchbuf(2);
break;
case 5:backLight=chbuf[1]-1;
break;
case 6:ledPat=chbuf[1]-1;//LED
break;
}
done=0;
}
output_bit(PIN_A0,bit_test(ledPat,0));//LED
output_bit(PIN_A1,bit_test(ledPat,1));
output_bit(PIN_A2,bit_test(ledPat,2));
output_bit(PIN_A4,0);
//delay_ms(10);
output_bit(PIN_A4,1);
output_bit(PIN_A3,bit_test(backLight,0));//backLight
//lpcnt++;
//delay_ms(50);
}
}
void outchbuf(int i){
while(chbuf[i] != 0){
lcd_data(chbuf[i]);
i++;
//delay_us(10);
}
}
//lcd command out for init
void lcd_incmd(int cmd){
db = cmd; //mode command
output_low(rw); //set write
output_low(rs); //set rs low
output_high(stb);//strobe
output_low(stb);
delay_us(100);
}
//initialize LCD
//set 4bit mode
void lcd_init(){
delay_ms(15);
lcd_incmd(0x30); //8bit mode set
delay_ms(5);
lcd_incmd(0x30); //8bit mode set
delay_ms(5);
lcd_incmd(0x30); //8bit mode set
delay_ms(5);
lcd_incmd(0x20); //4bit mode set
delay_ms(5);
lcd_cmd(0x2C); //DL=0 4bit mode
lcd_cmd(0x08); //display off C=D=B=0
lcd_cmd(0x0C); //display on C=D=1 B=0
lcd_cmd(0x06); //entry I/D=1 S=0
//delay_ms(2);
//while(bit_test(lcd_status(),7));
}
//send data to LCD
void lcd_data(int asci){
db = asci>>4 | 0x10; //set upper data
output_low(rw); //set write
output_high(rs); //set rs high
output_high(stb); //strobe
output_low(stb);
db = (asci & 0xF) | 0x10; //set lower data
output_high(stb); //strobe
output_low(stb);
//delay_us(200);//busy check しないとき200必要
while(bit_test(lcd_status(),7));//check busy
}
//read status
int lcd_status(){
int high,low;
output_bit(PIN_A4,1);
set_tris_a(Amode | 0x0F); //set input mode
output_low(rs);
output_high(rw);
//read mode
output_high(stb);
high=db & 0xF; //input A ,read upper
output_low(stb);
//delay_us(10);
output_high(stb);
low=db & 0xF; //inputA ,read lower
output_low(stb);
set_tris_a(Amode);
return(high<<4 | (low)); //return status
}
//send command
void lcd_cmd(int cmd){
//set upper data to PORTA & set PA4=0(LED common)
output_low(rw); //set write
output_low(rs); //set rs low
output_high(stb); //strobe
db = cmd>>4 | 0x10;
output_low(stb);;
output_high(stb); //strobe
db=(cmd & 0xF) | 0x10;
output_low(stb);
delay_us(5);
//delay_ms(2);
while(bit_test(lcd_status(),7));
}
// clear display clear function
void lcd_clear(){
lcd_cmd(1); //initialize command
delay_ms(10);
lcd_cmd(2);
delay_ms(2);
//delay_ms(2);
//while(bit_test(lcd_status(),7));
}