米粒AVRでI2C通信を使ってLCD表示
公開日:
電子工作 | I2C, 米粒AVR(tiny10)
前の記事で紹介したI2Cライブラリを使った、LCDの表示のライブラリ的なもの
LCD
使っているLCDは、ストロベリーリナックスで販売されているミニI2C液晶モジュール(8x2行)[バックライト付] というもの。 同じコントローラーが使われているものなら大抵は使いまわしが効くと思います。
ブレッドボードで使う上で、ピンが沢山出ていて面倒くさいので、VDD,GND,SDA,SCLの4本にまとめています。
I2C接続
米粒AVRのPB0がSDA、PB1がSCLとなっています。
ストロベリーリナックスのLCDの説明書には、プルアップ抵抗は数十kΩ以上を利用するように勧められています。
数十kΩって大きすぎじゃ無いか?と思いながら、僕はとりあえず10kを使って動かしています。
ソース
tiny10softI2C_LCD.h
/*<br /> tiny10softI2C_LCD.h<br /> Software LCD Library for ATTiny10<br /> http://s2jp.com/<br /> <br /> Copyright (c) 2012 Futaba. All Rights Reserved.<br /> */<br /> <br /> #ifndef _S2_TINY10_SOFTI2C_LCD_H_<br /> #define _S2_TINY10_SOFTI2C_LCD_H_<br /> <br /> #include "tiny10softI2C.h"<br /> <br /> #define LCD_ADDR (0x3E)<br /> #define LCD_CONTRAST (40)<br /> <br /> #define LCD_CONTRAST_H (0x5c)<br /> // 5Vで動かす場合<br /> //#define LCD_CONTRAST_H (0x58)<br /> <br /> #define LCD_CURSOR_CMD(x,y) (0x80 | (y*0x40+x))<br /> <br /> void LCD_command(uint8_t data)<br /> {<br /> I2C_start();<br /> I2C_write(LCD_ADDR<<1);<br /> I2C_write(0);<br /> I2C_write(data);<br /> I2C_stop();<br /> <br /> _delay_us(50);<br /> }<br /> <br /> void LCD_write(uint8_t data)<br /> {<br /> I2C_start();<br /> I2C_write(LCD_ADDR<<1);<br /> I2C_write(0x40);<br /> I2C_write(data);<br /> I2C_stop();<br /> <br /> _delay_us(50);<br /> }<br /> <br /> inline static void LCD_init()<br /> {<br /> I2C_init();<br /> _delay_ms(50);<br /> <br /> LCD_command(0b00111000); // ファンクション・セット<br /> LCD_command(0b00111001); // ファンクション・セット<br /> LCD_command(0x14); // カーソル移動・表示シフト<br /> <br /> // Contrast set<br /> LCD_command(0x70 | (LCD_CONTRAST & 0xF));<br /> LCD_command(LCD_CONTRAST_H | ((LCD_CONTRAST >> 4) & 0x3));<br /> <br /> LCD_command(0b01101100); // follower control<br /> _delay_ms(300);<br /> <br /> LCD_command(0b00111000); // ファンクション・セット<br /> LCD_command(0b00001100); // ディスプレイON<br /> <br /> LCD_command(0x01); // LCD clear<br /> _delay_ms(2);<br /> }<br /> <br /> #endif<br />
I2Cライブラリと同じく、ソースはヘッダーファイル用に作っています。
Atmel Studio 6で、tiny10softI2C_LCD.h として保存し、#inlude して利用することを想定してます。
他のコンパイラとかでは動かないかもしれません。
命令説明
void LCD_init();
LCDライブラリの初期化。
void LCD_command(uint8_t data);
LCDモジュールへコマンド送信。
void LCD_write(uint8_t data);
LCDモジュールへ文字書き込み。
LCD_CURSOR_CMD(x,y)
カーソル位置のコマンドを定義するマクロです。
LCD_commandと組み合わせて使います。
例)LCD_command(_LCD_CURSOR_CMD(2,1));
カーソル位置を横2:縦1の位置へ移動させます。
サンプル・プログラム
<br /> #define F_CPU 8000000UL<br /> <br /> #include <avr/io.h><br /> <br /> #include "tiny10softI2C.h"<br /> #include "tiny10softI2C_LCD.h"<br /> <br /> int main(void)<br /> {<br /> CCP = 0xD8;<br /> CLKMSR = 0x00;<br /> CCP = 0xD8;<br /> CLKPSR = 0b00000000;<br /> <br /> LCD_init();<br /> <br /> LCD_write('H');<br /> LCD_write('e');<br /> LCD_write('l');<br /> LCD_write('l');<br /> LCD_write('o');<br /> <br /> LCD_command(LCD_CURSOR_CMD(2,1));<br /> <br /> LCD_write('T');<br /> LCD_write('i');<br /> LCD_write('n');<br /> LCD_write('y');<br /> LCD_write('1');<br /> LCD_write('0');<br /> <br /> while(1)<br /> {<br /> }<br /> }<br />
このサンプルプログラムは、このように「Hello Tiny10」と表示されます。
関連記事
-
-
Arduinoで温湿度計
秋月電子の温湿度モジュールを使って、温湿度計を作ってみました。 以前「パソコンで温度計」と言うもの
-
-
赤外線リモコン受信機(イヤホンジャック接続)のアプリ
前回の赤外線リモコン受信機(イヤホンジャック接続)の回路 を使う為のAndroidア
-
-
米粒AVRでSoftModem的なこと その2
前回は「米粒AVRからAndroidへデータを送る」ことを試しました。 今回はその逆の「And
-
-
Softmodem Terminal 公開しました。
需要がどれほど有るのか疑問に思いつつ、以前のエントリ(AndroidでSoftModemを試してみた
-
-
Androidで一眼レフカメラのシャッターを制御する
またSoftModemネタです。 調子に乗って arms22さんの記事 iPhoneで一眼レフカメ
-
-
Arduino + USBホストシールド で ADK を試す(その2)
前回「Arduino + USBホストシールド で ADK を試す(その1)」では、Androidで
-
-
AndroidでSoftModemを試してみた
今回、ここで言うSoftModemとは、携帯電話のオーディオ端子(イヤホン・マイク端子)を利用し
-
-
赤外線リモコン受信機(イヤホンジャック接続)を作ってみた
最近、このブログ何も書いて無かったので、作成中の物の紹介・・・ これは、Andro
-
-
Arduinoで温湿度計 #2
今回は、前回作った温湿度計にRTCモジュールとSDカードアダプタを取り付けて温湿度データロガーを
- PREV
- 米粒AVRでI2C通信(マスター)
- NEXT
- 米粒AVRで温度計(STTS751使用)
Comment (36件)
質問を取り下げます。LPS331APの1枚の説明書良く見たら書いて有りました。自分で理解して行かなければいけない問題と反省しております。
ストロベリ-リナックスの8文字2行LCDは5V、3Vでも使用できるらしいのですが、3V VDDの
場合digital contrast 調整では、リニアに変化しない事が分りました。
センサ-がVDDが3Vで、AVR,LCD VDDが5V動作の場合、抵抗と、ダイオ-ドでI/Fするのが
良いと思いました。
ATTINY85、LPS331AP,LCD AQM0802A+ボタン電池(CR2032) 3Vで気圧計が出来ました。
3.3V I2C LCD(ACM1602NI)の表示testをしたいと思います。
futabaさんのLCD Programを勉強して、
ようやくACM1602NI-FLW-FBW-M01(i2c-LCD 16ch x 2L)に
表示出来るように成りました。ありがとうございました。
苦労したところは、ATMEGA168Pを8MHzで動作させていましたが、
clockが早すぎるのではと思い1MHzにDownさせたら、一発で動きました。
質問なのですが、i2c.hのI2C_read(uint8_t ACK)が未使用なのですが、clockをdownさせた事と
関係有りますか?
>kawana様
申し訳ないですが、公開しているのは米粒AVR(tiny10)向けなので、ATmega168での動作については、ちょっと分かりません。
ちなみにmega168はハードウェアでi2cに対応しているので、そちらを利用することをお勧めします。
また、I2C_readはi2c機器からデータを受信する為の命令で、LCDで利用する限りはI2C_readは利用されません。
i2c.hの詳細については米粒AVRでI2C通信(マスター)をご覧下さい。
私のi2c LCD(ACM1602I)のトラブル検討にFu tabaさんのi2c LCD programを参考にさせて
頂ました。program は、clockの生成などsoftでやられているので、i2c の理解に大変参考に
成りました。
programは、Strawberry Linuxのsample programを変更して動作させる事を考えましたが
必要変更点のみ変更では動作しませんでした。clockを1/8に落とす事で、不完全ながら表示
出来ている事が確認出来ました。(Futabaさんのproguramでも表示出来る事を確認)、
前の命令が完全に終了していない時に次の命令を送信した時に起こると思い、_delay_ms(1)
を、i2c_write(addr, maddr,db);のdb送出後に入れる事で、無事表示出来ました。
おかげさまで、i2cが少し理解出来ました。ありがとうございました。
futaba様初めまして。
そこのkawanaという者ですが数々の電子工作系の掲示板やブログを
荒らしまわっている非常に悪質な荒らしです。
無視をしてもそのように意味不明の文字列をどんどん書き込んできますので
アクセス禁止等を行い書き込ませない&書き込んできたら即削除を実施するといった
断固たる措置をよろしくお願いいたします。
Futabaさんのi2c LCD Program 勉強の後、futabaさんの勧めでm168系でHard i2cを勉強しました。勉強と言っても
Strawberry LinuxさんのLCD SB1602WGのSample Programをいじっていただけですが、
wait_us(50);の位置を変更するだけで、ACM1602NI(i2c LCD)に文字表示が出来ました事の報告です。
記載不都合が有れば、記載しないで下さい。この結果を得るに当たり、futabaさんのi2c LCD Program(i2c hardを使わずc言語で記述されているprogramを勉強する事で、i2cの理解を深める事が出来た事、改めて感謝する次第です。
//——————————————–
i2c_write(adr, eeadr, dat)
{
.
.
TWDR = dat;
TWCR = _BV(TWINT) | _BV(TWEN);
switch(wait_stat()){
case TW_MT_DATA_ACK:
break;
case TW_MT_ARB_LOST:
goto begin;
case TW_MT_DATA_NACK:
default:
goto quit;
}
wait_us(50);// (2)*****
rv = 1;
quit:
i2c_stop();
// wait_us(50);// (1)*****1命令毎に余裕を見て50us waitさせる。
return rv;
}
まとめて言うと
(1)をやめて、(2)とする事で、ACM1602NIにも対応出来ました。サイト汚しでしたら済みません。
Futaba さんのProgramを下記の様に変更してLCD ACM1602NIに表示出来ました。
変更箇所は、LCD_cmd、LCD_writeに_delay_us(50); // (1) ******を入れる。
//******************************
void LCD_write(uint8_t data)
{
I2C_start();
I2C_write(LCD_ADR<<1); // (101 0000)7 (1010 0000)8
I2C_write(0x80); //data 0x80
I2C_write(data);
_delay_us(50); // (1)*****
I2C_stop();
//_delay_us(50);
}
i2cの基本を理解出来た様なのでFutabaさんの気圧Programをcopyして、動作確認して見ようと思います。
多分、すぐに動作させる事が出来ると思います。 感謝。
tn45V(8Pin)でFutabaさんのi2c Programを勉強しました。Pinを見ると
GND 4 5 PB0(MOSI/SDA) —SDA
PB4 3 6 PB1(MISO/D0)
PB3 2 7 PB2(SCK/SCL) —–SCL
*RESET/PB5 1 8 VCC
SDA,SCLが有るので、i2c functionは使えるのでしょうか?m168用をtn45Vに置き換えた時に該当registerが
見つかりませんでした。
fullのdata sheetの目次にi2cが有るかもう一度見てみます。
P108-P118に、USIとして有りました。
Two-wire Synchronous, Three-wire Synchronousが有るが、i2cと似ているんは、どれか、
研究(勉強)してみよう。出来るかな。?
文字列を連続送信を追加してみました。
//— 文字列を連続送信します。—–
void i2c_puts(unsigned char *s)
{
while(*s)
{
LCD_write(*s++);
}
}
表示codeは
i2c_puts(“1234567890ABCDEZ”);// 16digit
USI通信を行う場合、MaserとしてATTINY45、SlaveとしてATTINY45が必要なのか。
すると、LCD表示する場合、i2c LCDを使用するのがベタ-ではないかと思った。