概要
最近投稿した下記3つの記事の総まとめです。ARDUINOシリアルモニターからデータ番号入力し、対応するEEPROMメモリデータを読み取り、シリアルモニター、LCDに表示します。
■EEPROM(24FC1025)を使う
■ARUDUINOでI2C接続LCDを使う①
■ARUDUINOでI2C接続LCDを使う②
接続変更
LCDとI2Cスレーブアドレスが重複していました。LCD側アドレスは固定なので、EEPROM接続を一部変更し対応します。LCDはI2Cディジーチェーン接続で変更はありません。
出力結果(表示状態)
結果はシリアルモニターとLCDに出力します。
下図はシリアルモニター出力結果です。
下図はLCD1(16X2行)出力です。16文字を超える文字は破棄されます。2行を超える場合、1行目に戻り上書きします。
下図はLCD2(20X4行)出力です。20文字を超える文字は破棄されます。4行を超える場合、1行目に戻り上書きします。
プログラム
#include <Wire.h>
const int BTN_DN = 9;
const int BTN_UP = 8;
const int inp_swDelay = 50; // 50 ms (SW入力安定待ち時間)
byte dvs_adrs[4] = { 0x51 , 0x55 , 0x50 , 0x3F }; // EEPROM 24FC1025 BLOCK1,2 I2Cアドレス
char MEM[32];
int wrt_blk = 32;
int loop_cnt = 2048 ;
int rd_no = 2045 ;
int wrt_lin[2] = { 0 , 0 };
byte blk = 0x20 ; // スペース
// 初期設定
void setup() {
Serial.begin(9600);
Wire.begin();
pinMode(BTN_UP, INPUT_PULLUP);
pinMode(BTN_DN, INPUT_PULLUP);
lcdinit(0); // LCD初期化(DVS1)
lcdinit(1); // LCD初期化(DVS2)
char myMsg[wrt_blk] ;
Serial.println("PROGRAM START!");
return;
// 文字列単位でアドレス指定し書き込む場合
Serial.println("Memory Writing Start");
for(int ii = 0 ; ii < 2 ; ii++){
for(int jj = 0 ; jj < loop_cnt ; jj++){
sprintf( myMsg, "%s%d,%s%d %s", "BLK:",ii," ADRS:",jj,"$$$$$$$$$$$$$$$" );
//dtostrf( ii , 10 , 0 , myMsg );
writeEEPROM_SER( ii , jj * wrt_blk , myMsg , false);
if(jj%500==0){
Serial.println(myMsg);
}
}
}
Serial.println("Finished");
Serial.println("");
}
// ■連続処理■
void loop() {
if (Serial.available() > 0 ) {
String data = Serial.readStringUntil('\n'); // シリアルデータ受信 (改行まで)
//data.toCharArray(myMessage, sizeof(MEM)); // 受信データ出力
// 文字列の長さが1文字以上の場合
if (data.length() > 0) {
rd_no = data.toInt(); // 文字列を整数に変換する
rd_EEPROM_BY_SER();
}
}
// EEPROM 読み込み(位置アップ)
if(!inp_sw(BTN_UP)){
rd_no++;
rd_EEPROM_BY_SER();
}
// EEPROM 読み込み(位置ダウン)
if(!inp_sw(BTN_DN)){
rd_no--;
rd_EEPROM_BY_SER();
}
}
// *********************************
// ******* EEPROM READ/WRITE *******
// *********************************
// ■関数■
// 書き込み(文字列単位→書込時間短縮)
// ARDUINO I2C送信バッファ32byte
void writeEEPROM_SER(unsigned int block, unsigned int address, byte *data, bool sp_wrt){
if(sp_wrt){
int adr_space = address + 30;
Wire.beginTransmission(dvs_adrs[block]);
Wire.write((int)highByte(adr_space));
Wire.write((int)lowByte(adr_space));
Wire.write(0x20); // スペース
Wire.write(0x20); // スペース
Wire.endTransmission();
delay(5); // 書込サイクル完了待機
}
Wire.beginTransmission(dvs_adrs[block]);
Wire.write((int)highByte(address));
Wire.write((int)lowByte(address));
for(unsigned int i=0; i < wrt_blk; i++){
Wire.write(data[i]);
}
Wire.endTransmission();
delay(5); // 書込サイクル完了待機
}
// 書き込み(1文字づつ)
void writeEEPROM(unsigned int block, unsigned int address, byte data){
Wire.beginTransmission(dvs_adrs[block]);
Wire.write((int)highByte(address));
Wire.write((int)lowByte(address));
Wire.write(data);
Wire.endTransmission();
delay(5); // 書込サイクル完了待機
}
// アドレス指定データ読込(block1、2 連番)
void rd_EEPROM_BY_SER(){
//block1:0-2047,block2:2048-4095
if( rd_no < 0 ){ rd_no = 4095 ; }
else if( rd_no > 4095 ){ rd_no = 0 ; }
int blk_no = (int)(rd_no / loop_cnt) ;
int s_adrs = (int)(rd_no % loop_cnt) ;
for (unsigned int j = 0; j < wrt_blk; j++){
MEM[j] = readEEPROM( blk_no , j + wrt_blk * s_adrs );
}
char MSG[32];
sprintf( MSG , "< %d , %d , %d >", rd_no, blk_no, s_adrs );
Serial.print(MSG);
Serial.println(MEM);
//transDataToLcd( 0 , 0 , 0x01 , 10); // 画面消去(DVS1)
//transDataToLcd( 1 , 0 , 0x01 , 10); // 画面消去(DVS2)
//char* tmp = str_ary1[i];
lcd_DispStrAry( 0, MEM , wrt_lin[0] );
lcd_DispStrAry( 1, MEM , wrt_lin[1] );
wrt_lin[0]++ ;
wrt_lin[1]++ ;
if( wrt_lin[0] > 1 ){ wrt_lin[0] = 0 ; }
if( wrt_lin[1] > 3 ){ wrt_lin[1] = 0 ; }
}
// EEPROM データ読込(block、アドレス指定)
byte readEEPROM(unsigned int block , unsigned int address){
byte data;
byte EEP_AD = dvs_adrs[block];
Wire.beginTransmission(EEP_AD);
Wire.write((int)highByte(address));
Wire.write((int)lowByte(address));
Wire.endTransmission();
Wire.requestFrom( EEP_AD , (byte)1 );
while(Wire.available() == 0);
data = Wire.read();
return data;
}
// ボタンSW入力安定待ち
boolean inp_sw(int pin){
boolean c_st;
boolean p_st;
p_st = digitalRead(pin);
for(int counter = 0; counter < inp_swDelay; counter++){
delay(5);
c_st= digitalRead(pin);
if( c_st != p_st){
counter = 0;
p_st = c_st;
}
}
return c_st;
}
// *********************************
// ********** LCD DISPLAY **********
// *********************************
// 文字表示1(1文を複数行に分けて表示)
// dvs_no(0:DVS1、 1:DVS2)
void lcd_Disp_Str(int dvs_no , char* str){
int l_cnt = 16 ;
int ln_cn = 2 ;
if(dvs_no!=0){
l_cnt = 20 ;
ln_cn = 4 ;
}
for(int j = 0; j < ln_cn ; j++){
pos_cursor( dvs_no , j , 0); //座標指定
for(int i = 0;i < l_cnt ;i++){
if(*str == '\0'){
transDataToLcd( dvs_no , 1 , blk , 0);
}else{
transDataToLcd( dvs_no , 1 , *str++ , 0);
}
}
}
}
// 文字表示2(1文を各行に表示)
// dvs_no(0:DVS1、 1:DVS2)
void lcd_DispStrAry(int dvs_no , char* str , int l_n ){
int l_cnt = 16 ;
if(dvs_no!=0){ l_cnt = 20 ; }
pos_cursor( dvs_no , l_n , 0); //座標指定
for(int i = 0 ; i < l_cnt ; i++){
if(*str == '\0'){
transDataToLcd( dvs_no , 1 , blk , 0);
}else{
transDataToLcd( dvs_no , 1 , *str++ , 0);
}
}
}
// LCD初期化
// dvs_no(0:DVS1、 1:DVS2)
void lcdinit(int dvs_no) {
if(dvs_no == 0){
transDataToLcd( 0 , 0 , 0x01 , 10); //画面消去
transDataToLcd( 0 , 0 , 0x38 , 10); //ファンクション設定
//transDataToLcd( 0 , 0 , 0x0F , 10); //ディスプレイON、CURSOR-ON、blinking-ON
transDataToLcd( 0 , 0 , 0x0C , 10); //ディスプレイON、CURSOR-OFF、blinking-OFF
transDataToLcd( 0 , 0 , 0x06 , 10); //データ書き込み後アドレス加算モード設定
} else {
transDataToLcd( 1 , 0 , 0x01 , 10); //画面消去
transDataToLcd( 1 , 0 , 0x38 , 10); //ファンクション設定
//transDataToLcd( 1 , 0 , 0x0F , 10); //ディスプレイON、CURSOR-ON、blinking-ON
transDataToLcd( 1 , 0 , 0x0C , 10); //ディスプレイON、CURSOR-OFF、blinking-OFF
transDataToLcd( 1 , 0 , 0x06 , 10); //データ書き込み後アドレス加算モード設定
}
}
// LCDデータ送信
// dvs_no(0:DVS1、 1:DVS2)
// typ_d ( 0:コマンド、1:データ )
// trsDat( コマンド、もしくはデータ )
// dTime ( データ送信後、待機時間 )
void transDataToLcd(int dvs_no , int typ_d , byte trsDat , int dTime){
byte typCmd = 0x00 ;
if(typ_d != 0){
if(dvs_no == 0){ typCmd = 0x80 ; }
else{ typCmd = 0x40 ; }
}
Wire.beginTransmission(dvs_adrs[dvs_no + 2]); // ◆LCD DVS アドレス変更対応◆
Wire.write(typCmd);
Wire.write(trsDat);
Wire.endTransmission();
if(dTime>0){ delay(dTime); }
}
// 表示位置指定(カーソル座標指定)
// dvs_no(0:DVS1、 1:DVS2)
// loc_x (0:1行目、1:2行目)
// loc_y (0:最左、15:再右)
void pos_cursor(int dvs_no , int loc_x , int loc_y){
byte p_inf = 0x80 + loc_y;
if(loc_x == 1){ p_inf = 0x80 + 0x40 + loc_y; }
else if(loc_x == 2){ p_inf = 0x80 + 0x14 + loc_y; }
else if(loc_x == 3){ p_inf = 0x80 + 0x54 + loc_y; }
transDataToLcd( dvs_no , 0 , p_inf , 5);
}
まとめ
固定でなく、内容を変化させたかったので試してみました。とりあえず、EEPROM, LCD関連の評価は一旦完了です。