コメントがあればこちらから
sorry. japanese only.

[YES!AVR!へ戻る]

ATtiny2313を使った1チップI2C&シリアルインターフェイスマルチ機能アダプタ

多機能I2Cスレーブ: キャラクタ型液晶(HD44780互換インターフェイス)の2LCD対応表示 4スイッチ入力 + 4LED出力 シリアルEEPROM(128バイト) シリアルSRAM(64バイト) + LEDドットマトリクス表示

ハードの概要

今更ですが,AVRのATtiny2313をI2CスレーブにしてI2CインターフェイスでLCD表示と4スイッ チ入力と4LEDの表示と幾ばくかのEEPROMとSRAMを備えたアダプタを作ってみました。
the I2C I/O board in debugging I2C経由で5ms毎に(200Hzで)時刻と1msカウンタの内容を表示する耐久テストの様子
一般的なHD44780互換コントローラを使ったキャラクタ表示型LCDをI2Cインターフェイス やUSARTシリアルインターフェイスで使用できるようにするためのアダプタです。 最近の低電圧マイコンでも手持ちの5V品汎用LCDが使えるよう,表示電圧バイアスをチャー ジポンプで生成して使用しています。 MCUにはATtiny2313Vを使用して電源は2.7〜5.0Vで使えるようになっています。 液晶表示器は一般的なHD44780互換コントローラーのモノが最大2つ接続できます。または 40文字x4行の液晶表示器が使えます。 キャラクタ表示型LCDだけではなく,4スイッチの入力, 4LED表示出力と,シリアルメモリ (128バイトEEPROM+64バイトSRAM)の機能も備えています。 LCD表示器をデュアルにする場合や秋月の40文字x4行LCD用にtiny2313のPB6ピンをE2信号 出力として機能するように設定していますので,これを使いALT LCDとして操作すること が可能です。aitendoの40x4LCD(SC404A)でもいけます。 メインのインターフェイスは,I2Cバスでファストモードのクロックストレッチ制御あり です。ついでにUSART(38400bps8N1)でシリアルによる入出力も行えます。 (LCD側の処理速度を超えるためクロックストレッチされて待ちが無駄なのと,バスのプルアップ 抵抗絡みで同じバスに同居するバスドライブの貧弱なデバイスが誤動作するので,その場合には, 標準モード(100kHz以内)での動作を推奨)
demo screen w/40x4 LCD 40字x4行の液晶表示モジュール(SC404A)での表示例
容量は小さいですが,シリアルEEPROM(128バイト)やシリアルSRAM(64バイト)として も使えます。 シリアルSRAMの方は,書き込んだ内容をLEDドットマトリクス表示することもできます。 多分,秋月で扱ってるLEDドットマトリクス表示器でも使えると思います。
Initiall display demo screen LEDドットマトリクスでの初期表示と動作中の様子(youtube動画)

I2Cインターフェイスでの使用について

このアダプタは,I2Cのスレーブデバイスアドレスを複数持っており,それぞれごとに個別 の制御モードがあります。 スレーブアドレスによって,HD44780のR/S信号やE信号を選択するようにしたため,余計 なセレクト用の制御バイトを送る必要がありません(秋月と苺エミュレートの場合を除く) ついでにUSARTシリアルでの制御と秋月苺(ST7032i系)のI2CインターフェイスLCDの エミュレートやEEPROMとSRAMの領域を活用できるようになっています。 スレーブアドレス毎の機能は以下のようになっています。スレーブアドレスの変更について (0x51) → I2C透過型HD44780モード(R/S=L コマンドの書き込み&ステータス読み込み) (0x52) → 4LED + 4keypad のI/O (0x53) → I2C透過型HD44780モード(R/S=H DDRAM/CGRAMの書き込み&読み込み) (0x56) → I2Cシリアルメモリ(EEPROM&SRAM) (0x50) → 秋月I2C LCDモード (+ステータス&RAM読み込み機能) (0x3e) → 苺I2C LCDモード (+ステータス&RAM読み込み機能) (0x55) → ALT LCD I2C透過型HD44780モード(R/S=L コマンドの書き込み&ステータス読み込み) (0x57) → ALT LCD I2C透過型HD44780モード(R/S=H DDRAM/CGRAMの書き込み&読み込み) (0x54) → ALT LCD 秋月I2C LCDモード (+ステータス&RAM読み込み機能) 液晶表示器に表示する場合(0x51, 0x53, 0x55, 0x57 :I2C透過型HD44780モード) 簡単に言えば,HD44780のコマンド(R/S=L)レジスタへ書き込む場合にはスレーブアドレス の0x51(ALT LCDの場合には0x55)へバイト列をそのまま書き込みます。同様にDDRAMなどへ 書き込む場合には0x53(ALT LCDの場合には0x57)にだらだらと書き込むだけです。 それぞれのアドレスから読み込むとLCDのステータスやDDRAM/CGRAMなどの内容を読出せる ようになっています。 LED出力およびボタン入力を行う場合(0x52 :4LED + 4keypad のI/O) LEDへ出力するには,0x52へ書き込むと下位4ビット分のビットが1となっている位置のLED が点灯します(上位4ビットは無視されます)。 LED4がbit3,LED3がbit2,LED2がbit1,LED1がbit0の位置になります。 また,0x52から読み込むと上位4ビットには現在のLEDの状態と下位4ビットにはSWの押下 状態(ビットが1の場合に押下されている)が読み出せます。 SW4がbit3,SW3がbit2,SW2がbit1,SW1がbit0の位置になります。 シリアルメモリを使用する場合(0x56 :EEPROM&SRAMI2Cシリアルメモリ) シリアルメモリは24LC01(のA2,A1ピンをHにした状態)とほぼ同じ機能を持っています。 ただし,アドレスは8ビットで指定でき前半の0x00-0x7fはEEPROMの内容を参照できます。 アドレスの後半,すなわち0x80-0xffは64バイトのSRAM領域(0xc0-0xffはイメージ)をアド レスします。 アドレスは自動インクリメントで同じメモリ領域内,つまり0x00-0x7fの範囲と0x80^0xff の範囲でそれぞれラップアラウンドします。 秋月や苺のI2C LCDのエミュレートを使う場合(0x50, 0x54, 0x3e :エミュレータモード) 前述の通り,秋月や苺で扱っているI2C LCDをエミュレートできる様にしてありますので, それら用に作成したプログラムの再利用もしやすいと思います。 秋月のI2C液晶ならば0x50(ALT_LCDの場合には0x54),苺のモノ(ST7032i系コントローラ) ならば0x3eをそれぞれスレーブアドレスにして書き込みます。 このエミュレータには読み込んだ場合の処理も拡張機能として搭載してあり,読み込むと LCDのステータスを先頭に続けてDDRAM/CGRAMの内容をだらだらと読出すことができます。 液晶表示器の初期化について LCDの初期化もアダプタの方で行うため無用ですが,実行しても問題ありません。 複数行表示構成の液晶表示器を対象として初期化しますので,1行構成(ファンクションセット でDL=0とする必要がある)の液晶表示器の場合には,その初期化用のファンクションセットを 行ってください。 なおファンクションセットコマンドによる8ビットバス指定は無視されます。 初期化が完了すると表示をクリアして,メインLCDには"I2C I/O"と, ALT LCDには"ALT LCD"と 表示します。 アダプタのリセットについて アダプタをリセットする場合にはLED(スレーブアドレス0x52)に対して'/'(0x2f),'R'(0x52) の順序で書き込むことでリセットできます。またSDAをLにしたままSCLをH→Lとして0.25秒 以上保持してもリセットできます。

シリアル(USART)インターフェイスでの使用について

簡易にではありますがUSART経由での制御も実装してあります。通信条件は38400bps8N1で 以下のエスケープシーケンスをサポートしています。 0x00-0x07と0x20以降の文字で0xa0と0xfeを除く文字はそのままLCDに出力されます。 0x08(ctrl+H):バックスペース(カーソルを1つ左に移動,ホームポジションストップ) 0x09(ctrl+I):水平タブ(カーソルを1つ右に移動) 0x0a(ctrl+J):改行(次の行にカーソル移動) 0x0b(ctrl+K):ホーム(ホームポジションにカーソル移動&カーソル消去) 0x0c(ctrl+L):画面消去(ホームポジションにカーソル移動&カーソル消去) 0x0d(ctrl+M):復帰(行頭にカーソル移動) 0x0e(ctrl+N):カーソル表示ON(ブリンク+カーソル) 0x0f(ctrl+O):SW状態を1文字の16進数文字'[0-9A-F]'で返す 0x10-0x1f:LEDの状態を設定する(下位ニブルでLEDの状態を表す) 0xa0: 操作対象をALT LCDに変更する 0xfe: 操作対象をメインLCDに変更する(デフォルト)

ALT LCDの機能について

このアダプタは液晶表示器を2つ接続して独立に動作させることができます。 LCDのE信号線以外を同じように接続して,メインLCDのEにはATtiny2313のPD6ピンを接続し ALT_LCDのEの方にはPB6ピンを接続するようにします。 40文字x4行LCDにもこれを使って上2行と下2行をそれぞれのLCDとして扱うことで使用する ことができます。(E1にPD6,E2にPB6を接続する) 応用的には,I2Cでの表示対象をメインLCDに,シリアルの表示対象をALT LCDとすることで 1つのアダプタを2つの機器から使うことも可能です。 または,ALT LCDの代わりにLEDドットマトリクスモジュール(32x16ドット)を接続して対応 するファームウェアを適用することで,電光掲示板的な表示もできます。 ソースのinc/config.incファイル中のにある#define I2C_LEDMATRIXのコメントアウトを取り 除いてビルドすれば対応するファームができます。 LEDに表示する内容は,ビットがセットされたシリアルSRAMの位置が点灯します。 (↓に対応するビットマップとさらに↓↓に接続するアダプタの回路図を示します) Bitmap layout: SRAM bitmap VS. LED display bitmap addr: +0x30 +0x20 +0x10 +0x00 +0x00: 76543210 76543210 76543210 76543210 +0x01: 76543210 76543210 76543210 76543210 +0x02: 76543210 76543210 76543210 76543210  : +0x0f: 76543210 76543210 76543210 76543210

留意事項:

低電圧環境で使用していたものを,5V環境へ移行して使用する場合には,そのまま移行を するとLCDに過剰なバイアス電圧がかかる場合がありますので,予めコントラスト調整Voを 中点に設定するなどして絞ってから移行してください。 シリアルメモリのうちEEPROM部分は書き込み後に十分時間を空けて(数ms以上待って)参照 するようにしてください(内部の書き込み完了以前にアクセスするとデータが化けます)。

余禄:他のI2Cスレーブデバイスとのアドレスのバッティングを回避するには

恒常的にアドレスを変える場合には,ソースのconfig.incにある#defineされた各アドレス を変更して再ビルドしたファームに更新すべきです。 ただ一時的に他のI2Cスレーブとのアドレスのバッティングを回避したいという場合には, 簡易機能として,起動時ランプテストのLEDが順次点灯/消灯しているときにボタンを押下 していると,その押されているボタンに当るビット位置を反転させたスレーブアドレスに 切替えができます。 つまりSW4が押されているとアドレスのビット6,SW3ならビット5などのように,ビット3まで 上位4ビット分について切り替えができます。 この切り替えで本来のアドレスから切り替えがあった場合には,起動時にLCD2行目にその ビットマスク列が7ビット分表示されます。
initial screen shot of LCD (normal)initial screen shot of LCD (slave addr. chg.) 初期表示(左:通常 右:SW1,2を押したまま起動) ↑ 40x4 LCDなので上2行がメインLCD表示,下2行がALT LCD表示となっている。
この切り替えで, たとえばSW1を押したまま起動すると,以下のようにスレーブアドレスが切り替わります。 (0x5a) → 4LED + 4keypad (0x59) → I2C透過型HD44780モード(R/S=L) (0x5b) → I2C透過型HD44780モード(R/S=H) (0x5e) → I2Cシリアルメモリ (0x58) → 秋月I2C LCDモード (0x36) → 苺I2C LCDモード (0x5d) → ALT LCD I2C透過型HD44780モード(R/S=L) (0x5f) → ALT LCD I2C透過型HD44780モード(R/S=H) (0x5c) → ALT LCD 秋月I2C LCDモード たとえばSW2とSW3を押したまま起動すると,以下のようにスレーブアドレスが切り替わり ます。 (0x62) → 4LED + 4keypad (0x61) → I2C透過型HD44780モード(R/S=L) (0x63) → I2C透過型HD44780モード(R/S=H) (0x66) → I2Cシリアルメモリ (0x60) → 秋月I2C LCDモード (0x0e) → 苺I2C LCDモード (0x65) → ALT LCD I2C透過型HD44780モード(R/S=L) (0x67) → ALT LCD I2C透過型HD44780モード(R/S=H) (0x64) → ALT LCD 秋月I2C LCDモード

プログラムやその他リソース

↓にソースアーカイブをおいておきます。(稿末にビルドログと設計メモをおいておきます) ソースアーカイブ:これ(2013/02/16更新) 回路図やアダプタボードレイアウトは,下図の通りです(クリックで拡大)。
scematic graph of the I2C I/O board LCDのみのシンプル版I/Oアダプタの回路図
scematic graph of CLCD to LED dot matrix module ALT_LCDにLEDドットマトリクスモジュールを接続するアダプタの回路図
SWとLED付のフル機能版の回路図はココ
アダプタボードのレイアウトはココ
PCBs of the I2C I/O board こしらえた基板の写真
the I2C I/O board 基板の組立て例(3mmのLEDが揃わなかったので5mmので...)

部品リスト

 MCU部分 MCU ATtiny2313V  LCD制御基本部分 C3,C4,C5 1uF(1608) R1 10KR(1608) R2,R3 2K-100KR(1608) (SCLクロックをファストモードにするなら5KR以下) R6 1KR(1608) R7 100K-330KR(1608) D1,D2 RB520SなどSBD か又は DA1 HN2S01FU C6,C7 1uF(1608) Vo 10K-50KR(TrimmerReg.)  LED&SW入出力部分 Q1 2SC2712(SC-59/SOT-23) Q2,Q3,Q4,Q5 2SA1586(SC-59/SOT-23) R4 1KR(1608) R5 100K-330KR(1608) R8,R12,R16,R20 100K-330KR(1608) R9,R13,R17,R21 10KR(1608) R10,R11,R14,R15,R18,R19,R22,R23 1KR(1608) SW1,SW2,SW3,SW4 TACTICAL-SW LED1,LED2,LED3,LED4 3mmLED(Vfが電源電圧-1.0V以下のもの) (SW,LEDは秋月のLED内蔵自照型SMD-SWでも代用可能)  他コネクタ用ピンヘッダ/ピンフレーム/ジャンパーなど

ビルドログ:

# make clean all write rm -f bin/*.elf bin/*.hex bin/*.eep obj/*.o *~ *.map *.list avr-gcc -mmcu=attiny2313 -mtiny-stack -msize -DF_CPU=8000000 -DRELEASE=1 -I. -Iinc -c -o obj/00start.o src/00start.S avr-gcc -mmcu=attiny2313 -mtiny-stack -msize -DF_CPU=8000000 -DRELEASE=1 -I. -Iinc -c -o obj/10main.o src/10main.S avr-gcc -mmcu=attiny2313 -mtiny-stack -msize -DF_CPU=8000000 -DRELEASE=1 -I. -Iinc -c -o obj/11usart_proc.o src/11usart_proc.S avr-gcc -mmcu=attiny2313 -mtiny-stack -msize -DF_CPU=8000000 -DRELEASE=1 -I. -Iinc -c -o obj/12i2c_proc.o src/12i2c_proc.S avr-gcc -mmcu=attiny2313 -mtiny-stack -msize -DF_CPU=8000000 -DRELEASE=1 -I. -Iinc -c -o obj/14ledmatrix_proc.o src/14ledmatrix_proc.S avr-gcc -mmcu=attiny2313 -mtiny-stack -msize -DF_CPU=8000000 -DRELEASE=1 -I. -Iinc -c -o obj/20sub.o src/20sub.S avr-gcc -mmcu=attiny2313 -mtiny-stack -msize -DF_CPU=8000000 -DRELEASE=1 -I. -Iinc -c -o obj/CLCD.o src/CLCD.S avr-gcc -mmcu=attiny2313 -mtiny-stack -msize -DF_CPU=8000000 -DRELEASE=1 -I. -Iinc -c -o obj/SW_LED.o src/SW_LED.S avr-gcc -mmcu=attiny2313 -mtiny-stack -msize -DF_CPU=8000000 -DRELEASE=1 -I. -Iinc -c -o obj/i2c_s.o src/i2c_s.S avr-ld -Map AVR_I2C_IO.map -nostartfiles -nostdlib -o bin/AVR_I2C_IO.elf obj/00start.o obj/10main.o obj/11usart_proc.o obj/12i2c_proc.o obj/14ledmatrix_proc.o obj/20sub.o obj/CLCD.o obj/SW_LED.o obj/i2c_s.o avr-objdump -h -S bin/AVR_I2C_IO.elf > AVR_I2C_IO.list awk '((($1<=9)&&($1>=0))&&($2~/\.text/||$2~/\.data/||$2~/\.bss/||$2~/\.eeprom/|| $0~/^Idx Name/)){print $0}' AVR_I2C_IO.list 0 .text 00000692 00000000 00000000 00000074 2**1 1 .bss 00000043 00800060 00000692 00000706 2**0 2 .eeprom 0000003e 00810000 00810000 00000706 2**0 avr-objcopy -j .text -j .data -O ihex bin/AVR_I2C_IO.elf bin/AVR_I2C_IO.hex avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex bin/AVR_I2C_IO.elf bin/AVR_I2C_IO.eep /cygdrive/y/warez/Hard/Atmel/AVR/HIDaspx/hidspx-2010-0823/bin/hidspx -ph:SN04 -d8 -fL0xe4 -fH0xdb -fX0xff bin/AVR_I2C_IO.hex bin/AVR_I2C_IO.eep Detected device is ATtiny2313. Erase Flash memory. Flash memory... Writing [##################################################] 1682, 2.92s Verifying [##################################################] 1682, 2.83s Passed. EEPROM... Writing [##################################################] 62, 0.72s Verifying [##################################################] 62, 0.52s Passed. Fuse Low byte was programmed (0xE4). Fuse High byte was programmed (0xDB). Fuse Extend byte was programmed (0x01). Total read/write size = 3488 B / 7.70 s (0.44 kB/s) #

設計メモ:

s:start condition p:stop condition 1,0:master send a constatnt bit x: master send a bit H,L:slave send a constant bit X: slave send a bit a,n: master reply acknowledge/NAK A,N: slave reply acknowledge/NAK Data format: 4LED/4BTN CTRL 押しボタン/LED状態取得/設定モード s 10100100A 0000xxxxA p addr=0x52 write LED status s 10100101A XXXXXXXXa p addr=0x52 read LED/BTN status(LED:=upper_nibble, BTN:=lower_nibble) Native LCD control s 10100010A xxxxxxxxA xxxxxxxxA ... p s 10100010A xxxxxxxxA p addr=0x51 write LCD RS=L(command) Bytes s 10100011A XXXXXXXXa p s 10100011A XXXXXXXXn p addr=0x51 read LCD RS=L(status) Byte Native LCD data transfer s 10100110A xxxxxxxxA xxxxxxxxA ... p s 10100110A xxxxxxxxA p addr=0x53 write LCD RS=H(CGRAM/DDRAM) Bytes s 10100111A XXXXXXXXa XXXXXXXXa ... p s 10100111A XXXXXXXXa p s 10100111A XXXXXXXXn p addr=0x53 read LCD RS=H(CGRAM/DDRAM) Bytes 24LC01 like serial memory s 10101010A xxxxxxxxA p memory address(0x00-0x7f:EEPROM 0x80-0xff:SRAM) s 10101010A xxxxxxxxA xxxxxxxxA ... p memory address + write data(automatic increment) addr=0x55 write address and data following s 10101011A XXXXXXXXa XXXXXXXXa ... p read data(automatic increment) s 10101011A XXXXXXXXa p s 10101011A XXXXXXXXn p addr=0x55 read data auto increment address register cyclic on same memory(0x00-0x7f:EEPROM / 0x80-0xff:SRAM) 秋月I2CLCDコンパチライトモード slave addr=0x50(write) CTRLbyte: CTRL byte:= 0x00:CMD,0x80:DATA CMD/DATA byte s 10100000A x0000000A xxxxxxxxA p ^R/S bit data 苺I2CLCDコンパチライトモード slave addr=0x3e(write) CTRLbyte: CTRL byte:= 0x00:CMD,0x40:DATA,0x80:Continous other command >> for detail see ST7032i datasheet CMD/DATA byte s 10100000A 1x000000A xxxxxxxxA p s 10100000A 0x000000A xxxxxxxxA xxxxxxxxA ... p s 10100000A 1x000000A xxxxxxxxA 0x000000A xxxxxxxxA xxxxxxxxA ... p s 10100000A 0x000000A xxxxxxxxA xxxxxxxxA ... p ^ Co,R/S bit data 秋月I2CLCD拡張リードモード (苺I2CLCD拡張リードモードも同じ) slave addr=0x50(read) slave addr=0x3e(read) STATUSbyte: DATAbyte: s 10100001A XXXXXXXXa XXXXXXXXa ... p s 10100001A XXXXXXXXa XXXXXXXXn p s 10100001A XXXXXXXXn p ^statusByte ^DDRAM/CGRAMdata ... State machine: To Be Determined [ご注意] ・このページの記載事項については,一切無保証です。
    inserted by FC2 system