TOP > MPLAB XC8編(PIC16F886) > I2CでEEPROMを使う(PIC16F886 XC8)
I2CでEEPROMを使う
(PIC16F886 XC8)
ここでは、シリアルインタフェースの一つである、
I2C(Inter-Integrated Circuit、アイ・スクエア・シー)でEEPROMを使ってみます。
使用するPICはPIC16F886です。
PIC16F886が保有するI2Cのマスタモードを使用します。
-
このページの目次-
1.I2Cの使い方
(1) I2Cの概要
(2) I2Cで使用するレジスタ
(3) データの送信方法
(4) データの受信方法
2.実験回路
3.プログラムの仕様
・プログラムの流れ
・EEPROMへの書き込み
・EEPROMからの読み出し
・DEVICE ADDRESS
・EEPROMのメモリアドレス指定
4.プログラム全体
|
1.I2Cの使い方
|
|
I2Cは、フィリップス社により開発されたシルアル通信の規格です。
シリアル通信には、RS-232、IEEE 1394、シリアルATAなど多くの規格がありますが、I2Cは主に近距離のデバイス(PICやEEPROMなどのIC)間通信に利用されています。
- (1) I2Cの概要
-
I2Cは、下図のようにSCL(シリアルクロックライン)とSDA(シリアルデータライン)という2本のバスライン上に複数のデバイスを接続した構成になっています。
SCL/SDAともに抵抗でプルアップします。
-
各デバイスの動作モードには、マスタモードとスレーブモードがあります。
通信を開始するデバイスがマスタとなり、通信先として選択されたデバイスがスレーブとなって、同時には1対1で通信を行います。
通常は、PICなどのマイクロコンピュータがマスタとなって、EEPROMなどのデバイスをスレーブとして制御します。
各デバイスには、バス上で一意になるアドレスを付与し、マスタはこのアドレスを指定して通信先のデバイスを選択します。
今回は、PICでEEPROMを使用しますので、PICをマスタモード、EEPROMをスレーブモードとして動作させます。
I2Cのバス制御やデータフォーマットなどについては、I2Cをプログラムで実装を参照して下さい。
- (2) I2Cで使用するレジスタ
-
PIC16F886には、MSSP(Master Synchronous Serial Port)モジュールが内蔵されています。
このMSSPモジュールでI2Cをサポートしています。
I2Cの動作は、マスタモード/スレーブモードの両方をサポートしていますが、ここではマスタモードのみ使用します。
I2Cで使用するレジスタは以下の通りです。マスタモードの動作を中心に記述します。
具体的な使い方は、(3) データの送信方法/(4) データの受信方法で例示します。
レジスタ | 概要
| SSPSTAT | 同期シリアルポートステータスレジスタ I2Cの状態などが設定される。
| SSPCON | 同期シリアルポートコントロールレジスタ I2Cの動作モードなどを設定する。
| SSPCON2 | 同期シリアルポートコントロールレジスタ2 I2Cの動作を制御する。
| SSPADD | SSP アドレスレジスタ マスタモードの場合は、クロック設定のパラメータとして使われる。
| SSPBUF | シリアル受信/送信バッファ 送信するデータを格納する。または、受信したデータが格納される。
|
この他に、SSP(I2C)の割込み機能を使う場合は、割込み関連のレジスタ(INTCON、PIR1、PIE1)も影響します。
割込み機能を使わない場合でも、PIR1レジスタのSSPIFビットの判定やクリアが必要です。
SSPSTAT-
bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0
| SMP | CKE | D/^A | P | S | R/^W | UA | BF
| RW | RW | R | R | R | R | R | R
|
RW:読み書き可能、R:参照専用
SMP | サンプルビット 1=標準速度モード(100kHz および1MHz)、スルーレート制御は行わない 0=高速モード(400kHz)、スルーレート制御を行う
| CKE | 0 (I2Cでは未使用)
| D/^A | データ/アドレスビット 1=最後に受信または送信したバイトはデータであった 0=最後に受信または送信したバイトはアドレスであった
| P | ストップビット 1=最後に検出されたのはストップビットであったことを示す(このビットはリセット時には「0 」になる) 0=最後に検出されたのはストップビットではなかった
| S | スタートビット 1=最後に検出されたのはスタートビットであったことを示す(このビットはリセット時には「0」になる) 0=最後に検出されたのはスタートビットではなかった
| R/^W | リード/ ライトビット情報 1=送信中 0=送信していない
| UA | アドレス更新(10 ビットアドレスのI2Cモードのみ) 1=SSPADD レジスタのアドレスを更新する必要があることを示す 0=アドレスを更新する必要はない
| BF | バッファフルステータスビット 受信時 1=受信完了、SSPBUF はフル 0=受信は未終了、SSPBUF は空 送信時 1=データ送信中(ACKおよびストップビットは除く)、SSPBUF はフル 0=データ送信完了(ACKおよびストップビットは除く)、SSPBUF は空
|
SSPCON-
bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0
| WCOL | SSPOV | SSPEN | CKP | SSPM3 | SSPM2 | SSPM1 | SSPM0
|
WCOL | ライト衝突検出ビット マスタモードの場合 1=I2Cの状態が有効でないときに、SSPBUFへのライトを実行した。 0=衝突なし
| SSPOV | 受信オーバーフロー表示ビット 1=受信モードのとき、SSPBUF が以前のバイトを保持しているときにバイトを受信した。 (ソフトウエアでクリアする必要がある) 0=オーバーフローなし
| SSPEN | 同期シリアルポート有効ビット 1=シリアルポートを動作させ、SDAとSCLピンをシリアルポートピンにする。 0=シリアルポートを停止して、上記のピンをI/O ポートピンにする。
| CKP | クロック極性選択ビット マスタモードでは未使用
| SSPM3 | SSPM0 |
0000 = SPI マスターモード、クロック= FOSC/4
0001 = SPI マスターモード、クロック= FOSC/16
0010 = SPI マスターモード、クロック= FOSC/64
0011 = SPI マスターモード、クロック= TMR2 出力/2
0100 = SPI スレーブモード、クロック= SCK ピン。SS ピン制御を動作させる
0101 = SPI スレーブモード、クロック= SCK ピン。SS ピン制御は停止。SS はI/O ピンとして使用可能。
0110 = I2C スレーブモード、7 ビットアドレス
0111 = I2C スレーブモード、10 ビットアドレス
1000 = I2C マスターモード、クロック= FOSC / (4 * (SSPADD+1) ) ===今回はこれを使用
1011 = I2C ファームウエア制御のマスターモード(スレーブはアイドル)
1110 = I2C スレーブモード、7 ビットアドレス、スタートおよびストップビット割り込み発生あり
1111 = I2C スレーブモード、10 ビットアドレス、スタートおよびストップビット割り込み発生あり
|
SSPCON2-
bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0
| GCEN | ACKSTAT | ACKDT | ACKEN | RCEN | PEN | RSEN | SEN
|
GCEN | ゼネラル・コールイネーブルビット(I2Cスレーブモードのみ) 1=ゼネラル・コールアドレス(0000h)を受信したとき割込み発生させる 0=ゼネラル・コールアドレスは発生させない
| ACKSTAT | アクノレッジステータスビット(I2Cマスターモードのみ) 1=アクノレッジをスレーブから受信しなかった 0=アクノレッジをスレーブから受信した
| ACKDT | 受信応答データビット(I2Cマスターモードの受信時のみ) 受信の終わりで応答シーケンスを開始するときに送信する値。 1=NO-ACK 0=ACK
| ACKEN | アクノレッジシーケンスイネーブルビット(I2Cマスターモードの受信時のみ) 1=SDA およびSCL ピンでアクノレッジシーケンスを開始して、ACKDT データビットを送信する。 ハードウエアで自動的にクリアされる。 0=アクノレッジシーケンスがアイドル中
| RCEN | 受信イネーブルビット(I2Cマスターモードのみ) 1=I2C 受信モードを動作させる 0=受信がアイドル中
| PEN | ストップコンディションイネーブルビット(I2Cマスターモードのみ) 1=SDAおよびSCLピンのストップコンディションを開始する。ハードウエアで自動的にクリアされる。 0=ストップコンディションがアイドル中
| RSEN | 繰り返しスタートコンディションイネーブルビット(I2Cマスターモードのみ) 1=SDAおよびSCLピンの繰り返しスタートコンディションを開始する。ハードウエアで自動的にクリアされる。 0=繰り返しスタートコンディションがアイドル中
| SEN | スタートコンディションイネーブルビット(I2Cマスターモードのみ) 1=SDAおよびSCLピンのスタートコンディションを開始する。ハードウエアで自動的にクリアされる。 0=スタートコンディションがアイドル中
|
SSPADD-
bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0
| - | クロックパラメータ(マスタモードの場合)
|
クロックパラメータは、I2Cのクロック(SCL)を設定します。
クロック= FOSC / (4 * (SSPADD+1) )
SSPBUF-
bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0
| 送受信データ
|
送信時は、送信するデータを格納します。
受信時は、受信したデータが格納されます。
- (3) データの送信方法
-
I2Cでデータを送信するときの手順は以下のようになります。(1バイト送信の場合)
- I2Cの初期化
- スタートビット送信
- スレーブアドレス送信、writeモード
- ACK受信チェック
- データ送信
- ACK受信チェック
- ストップビット送信
No | 処理 | コーディング例 | 備考
| 1 | I2Cの初期化 |
TRISC = 0x3F;
PORTC = 0x00;
SSPCON = 0x28;
SSPADD = 0x03;
| SDA/SCL:input
SSP enable & I2C Master mode, clock = FOSC / (4 * (SSPADD+1))
| 2 | スタートビット送信 |
SEN = 1;
while (SEN) {}
|
| 3 | スレーブアドレス送信 |
SSPIF = 0;
SSPBUF = addr;
while (!SSPIF) {}
| addrの上位7ビットにスレーブアドレスを設定する。 最下位の1ビットには0(write)を設定する。
| 4 | ACK受信チェック |
if (ACKSTAT) {
NO-ACK受信時処理;
} else {
ACK受信時処理;
}
|
| 5 | データ送信 |
SSPIF = 0;
SSPBUF = send_data;
while (!SSPIF) {}
|
| 6 | ACK受信チェック |
if (ACKSTAT) {
NO-ACK受信時処理;
} else {
ACK受信時処理;
}
|
| 7 | ストップビット送信 |
SSPIF = 0;
PEN = 1;
while (PEN) {}
SSPIF = 0;
|
|
- (4) データの受信方法
-
I2Cでデータを受信するときの手順は以下のようになります。(1バイト受信の場合)
- I2Cの初期化
- スタートビット送信
- スレーブアドレス送信、readモード
- ACK受信チェック
- データ受信
- NO-ACK送信
- ストップビット送信
No | 処理 | コーディング例 | 備考
| 1 | I2Cの初期化 |
TRISC = 0x3F;
PORTC = 0x00;
SSPCON = 0x28;
SSPADD = 0x03;
| SDA/SCL:input
SSP enable & I2C Master mode, clock = FOSC / (4 * (SSPADD+1))
| 2 | スタートビット送信 |
SEN = 1;
while (SEN) {}
|
| 3 | スレーブアドレス送信 |
SSPIF = 0;
SSPBUF = addr;
while (!SSPIF) {}
| addrの上位7ビットにスレーブアドレスを設定する。 最下位の1ビットには1(read)を設定する。
| 4 | ACK受信チェック |
if (ACKSTAT) {
NO-ACK受信時処理;
} else {
ACK受信時処理;
}
|
| 5 | データ受信 |
SSPIF = 0;
RCEN = 1;
while (RCEN) {}
read_data = SSPBUF;
|
| 6 | NO-ACK送信 |
ACKDT = 1;
ACKEN = 1;
while (ACKEN) {}
|
| 7 | ストップビット送信 |
SSPIF = 0;
PEN = 1;
while (PEN) {}
SSPIF = 0;
|
|
|
2.実験回路
|
・ |
今回の実験回路です。
EEPROMは、AT24C1024B(128KByte)を使用しました。
-
- こちらは、ブレッドボードに組んだ状態。
-
|
3.プログラムの仕様
|
|
今回のプログラムは、I2CでEEPROMにアクセスする事だけを目的としました。
- プログラムの大まかな流れは以下の通りです。
-
1. PICとLCDを初期化する。
2. LCDに0xAAを表示する。
3. EEPROMの0x00A100番地に0xAAを書き込む。
4. LCDに0xBBを表示する。
5. EEPROMの0x01A100番地に0xBBを書き込む。
6. EEPROMの0x00A100番地のデータを読み込みLCDに表示する。
7. EEPROMの0x01A100番地のデータを読み込みLCDに表示する。
EEPROMへの1バイト書込みは、以下のデータフォーマットになります。
-
AT24C1024Bのデータシートより抜粋。
|
(1) DEVICE ADDRESSにより、通信先としてEEPROMを選択する。R/WはWRITEを設定。
(2) P0,上位バイトアドレス,下位バイトアドレスにより、EEPROMのメモリアドレスを指定する。
(3) 書き込むDATAを送る。
EEPROMから1バイト読み込むときのデータフォーマットは以下の通りです。
-
AT24C1024Bのデータシートより抜粋。(2番目のSTARTは、Repeated Start)
|
(1) DEVICE ADDRESSにより、通信先としてEEPROMを選択する。R/WはWRITEを設定。
(2) P0,上位バイトアドレス,下位バイトアドレスにより、EEPROMのメモリアドレスを指定する。
(3) DEVICE ADDRESSにより、通信先としてEEPROMを選択する。R/WはREADを設定。
(4) EEPROMから1バイト読み込む。(DATAn)
DEVICE ADDRESS-
- 今回使用した、AT24C1024Bではデバイスアドレスを以下のよう設定します。(ビット表記)
-
1010 | : 固定
| aa | : A1/A2ピンの状態。今回の回路では共にGND接続しているため、00とする。
| P | : EEPROMのメモリアドレス上位1ビット(下記を参照)
|
EEPROMのメモリアドレス指定-
AT24C1024Bは、128KByteのメモリを保有しています。従って、全てのメモリにアクセスするためには、アドレスとして17ビットが必要になります。
この17ビットを、デバイスアドレスの下位1ビット+上位バイトアドレス8ビット+下位バイトアドレス8ビットで表現しています。
デバイスアドレスの下位1ビットは、上のデータフォーマットではP0と表現しています。
|
4.プログラム全体
|
|
プログラム内のI2C関連関数は、「1.I2Cの使い方」の「(3) データの送信方法/(4) データの受信方法」で例示した内容とほぼ同じです。
|