I2C LCD動作 (SO1602)



SO1602Aは I2C通信の 2行表示 LCDである
動作は 3.3Vになるので、双方向バッファを使う
ATmega328 を使う
I2C通信LCDは アルドィーノ等での 動作プログラムサンプルはネットでよく見かけるが、
直接 AVRでコントロールしている例が見つからないので 自分で作る




回路図






プログラム

aqm_put_str("430M SSB");
aqm_position(2,1);
aqm_put_str("30W");


so16_position(5,1);
so16_put_str("30W");
so16_position(0,0);
so16_put_str("430Mhz SSB ");




//-------SO1602 イニシャル送信----------------------

void SO16_ID(void)
{

/* 開始条件送出*/
TWCR = (1<<TWINT)|(1<<TWSTA) |(1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機

TWDR=0x78; //MBE280 アドレス
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);
TWDR=0x00; //00 コマンド
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);
TWDR=0x01; //clear Disp
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);
TWDR=0x02; //REturn home
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);

TWDR=0x0F; //OSC frecency
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);

TWDR=0x01; //Clear Disp
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);
TWDR=0x2A; //RE-1
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);

TWDR=0x79; //SD=1
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_ms(20);
TWDR=0x81; //contrast
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);

TWDR=0xFF; //輝度MAX
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);

TWDR=0x78; //SD=0
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);
TWDR=0x28; //nomal 文字
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);


/* 停止条件送出*/
TWCR = (1<<TWINT)|(1<<TWSTO) |(1<<TWEN);

//終了したので 受信モードに入る
wait_ms(2);

}


/*-----------------------------------------------------------*/
/* SO1602 LCD 文字列表示 */
/* 引数: char *str : 文字列の先頭ポインタ */
/*-----------------------------------------------------------*/
void so16_put_str(char *str)
{
/* 開始条件送出*/
TWCR = (1<<TWINT)|(1<<TWSTA) |(1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機

TWDR=0x78; //AQM0802A アドレス
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);
TWDR=0x40; //表示 コマンド
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);


while(*str != 0) {
TWDR=*str; //C
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);
str++;
}
/* 停止条件送出*/
TWCR = (1<<TWINT)|(1<<TWSTO) |(1<<TWEN);

wait_ms(2);
}



// SO1602A カーソルポジション ----------------------
void so16_position(char tx ,char ty)
{
switch(ty){
case 0: ty = 0x00; break;
case 1: ty = 0x20; break;
// case 2: ty = 0x14; break;
// case 3: ty = 0x54; break;
}
TWCR = (1<<TWINT)|(1<<TWSTA) |(1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機

TWDR=0x78; //AQM0802A アドレス
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);

TWDR=0x80; //行設定 コマンド
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);

TWDR=(0x80 | (tx + ty)); //2行目  (80|40)=C0
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
wait_us(27);


/* 停止条件送出*/
TWCR = (1<<TWINT)|(1<<TWSTO) |(1<<TWEN);

wait_ms(2);


}