ルネサスエレクトロニクス社製のマイコンRX210を使用してI2C通信を行うプログラムのサンプルです。
- #include "iodefine.h"
- #include <stdio.h>
- #include <machine.h>
- #include "rs232c.h"
- /*
- Interface 2011年6月号を参考にして作成したIIC通信プログラム
- 割込みを使用しない
- */
- /*
- RIICの初期化
- 引数 無し
- 戻り値 無し
- */
- void initRIIC0(void)
- {
- SYSTEM.PRCR.WORD = 0xA502; /* Enables writing to the registers */
- MSTP(RIIC0) = 0; // モジュールスタンバイ解除
- SYSTEM.PRCR.WORD = 0xA500; /* Disables writing to the registers */
- /* Set the pins */
- PORT1.PDR.BIT.B2 = 0; /* SCL: input */
- PORT1.PDR.BIT.B3 = 0; /* SDA: input */
- PORT1.PMR.BIT.B2 = 0; /* SCL: general I/O port */
- PORT1.PMR.BIT.B3 = 0; /* SDA: general I/O port */
- MPC.PWPR.BIT.B0WI = 0; /* Writing to the PFSWE bit is enabled */
- MPC.PWPR.BIT.PFSWE = 1; /* Writing to the PFS register is enabled */
- MPC.P12PFS.BIT.PSEL = 0x0F; /* SCL */
- MPC.P13PFS.BIT.PSEL = 0x0F; /* SDA */
- MPC.PWPR.BIT.PFSWE = 0; /* Writing to the PFS register is disabled */
- MPC.PWPR.BIT.B0WI = 1; /* Writing to the PFSWE bit is disabled */
- /* Set the pins */
- PORT1.PMR.BIT.B2 = 1; /* SCL: peripheral function */
- PORT1.PMR.BIT.B3 = 1; /* SDA: peripheral function */
- /* RIIC disable for RIIC initial */
- RIIC0.ICCR1.BIT.ICE = 0;
- while(RIIC0.ICCR1.BIT.ICE != 0); /* Confirm that the ICCR1.ICE bit is 0 */
- RIIC0.ICCR1.BIT.IICRST = 1; /* RIICリセット */
- RIIC0.ICCR1.BIT.ICE = 1; /* 内部リセット */
- /* Set transfer bit rate : 100kbps (PCLK = 25MHz) */
- RIIC0.ICMR1.BIT.CKS = 2; /* Internal Reference Clock: PCLK/4 clock */
- RIIC0.ICBRH.BIT.BRH = 24; /* Set the High-level period of SCL clock */
- RIIC0.ICBRL.BIT.BRL = 29; /* Set the Low-level period of SCL clock */
- /* disable all address detection. Master mode only. */
- RIIC0.ICSER.BYTE = 0x00;
- /* ACKWP is protect bit for ACKBT */
- RIIC0.ICMR3.BIT.ACKWP = 1; /* disable protect for ACKBT */
- RIIC0.ICCR1.BIT.IICRST = 0; /* 内部リセット解除 */
- }
- /*
- バスフリーの確認
- 引数 無し
- 戻り値 無し
- */
- inline void i2cBusFree(void)
- {
- while(RIIC0.ICCR2.BIT.BBSY == 1);
- }
- /*
- バス・スタートを実行
- 引数 無し
- 戻り値 無し
- */
- inline void i2cStart(void)
- {
- RIIC0.ICCR2.BIT.ST = 1;
- while(RIIC0.ICSR2.BIT.START != 1);
- RIIC0.ICSR2.BIT.START = 0;
- }
- /*
- バスがBusy中にバス・スタート
- 引数 無し
- 戻り値 無し
- */
- inline void i2cReStart(void)
- {
- RIIC0.ICCR2.BIT.RS = 1;
- while(RIIC0.ICSR2.BIT.START != 1);
- RIIC0.ICSR2.BIT.START = 0;
- }
- /*
- バス・ストップを実行
- 引数 無し
- 戻り値 無し
- */
- inline void i2cStop(void)
- {
- RIIC0.ICSR2.BIT.STOP = 0;
- RIIC0.ICCR2.BIT.SP = 1;
- while(RIIC0.ICSR2.BIT.STOP != 1);
- RIIC0.ICSR2.BIT.STOP = 0;
- RIIC0.ICSR2.BIT.NACKF = 0;
- }
- /*
- デバイスに1byteデータ転送
- 引数 送信データ
- 戻り値 無し
- */
- inline void i2cSendByte(unsigned char data)
- {
- while(RIIC0.ICSR2.BIT.TDRE != 1);
- RIIC0.ICDRT = data;
- }
- /*
- データの転送完了を確認
- 引数 無し
- 戻り値 無し
- */
- inline void i2cCheckTEND(void)
- {
- while(RIIC0.ICSR2.BIT.TEND != 1);
- }
- /*
- デバイスから1byte読み取りバスストップを実行
- 引数 無し
- 戻り値 デバイスから読み取ったデータ
- */
- unsigned char i2cReceiveByteStop(void)
- {
- unsigned char rdt;
- while(RIIC0.ICSR2.BIT.RDRF != 1);
- RIIC0.ICMR3.BIT.WAIT = 1;
- RIIC0.ICMR3.BIT.ACKBT = 1;
- rdt = RIIC0.ICDRR; //dummy read
- while(RIIC0.ICSR2.BIT.RDRF != 1);
- RIIC0.ICSR2.BIT.STOP = 0;
- RIIC0.ICCR2.BIT.SP = 1; //stop
- rdt = RIIC0.ICDRR; //data read
- RIIC0.ICMR3.BIT.WAIT = 0;
- while(RIIC0.ICSR2.BIT.STOP != 1);
- RIIC0.ICSR2.BIT.STOP = 0;
- RIIC0.ICSR2.BIT.NACKF = 0;
- return rdt;
- }
- /*
- スレーブ・アドレスを指定してデバイスのレジスタ・メモリにデータを書き込む
- 引数 sadr : スレーブ・アドレス
- madr : レジスタ・メモリアドレス 8bit
- data : 書き込むデータ
- 戻り値 無し
- */
- void i2cDevWrite8(unsigned char sadr, unsigned char madr, unsigned char data)
- {
- i2cBusFree();
- i2cStart();
- i2cSendByte(sadr);
- i2cSendByte(madr);
- i2cSendByte(data);
- i2cCheckTEND();
- i2cStop();
- }
- /*
- スレーブアドレスとデバイスのレジスタ・アドレスを指定してデバイスからデータを読み込む
- 引数 sadr : スレーブ・アドレス
- madr : レジスタ・メモリアドレス 8bit
- 戻り値 読み込んだデバイスのデータ
- */
- unsigned char i2cDevRead8(unsigned char sadr, unsigned char madr)
- {
- unsigned char rdt;
- i2cBusFree();
- i2cStart();
- i2cSendByte(sadr);
- i2cSendByte(madr);
- i2cCheckTEND();
- i2cReStart();
- i2cSendByte(sadr | 0x01);
- rdt = i2cReceiveByteStop();
- return rdt;
- }
- /*
- スレーブアドレスを指定して複数byteのデータを送信する
- 引数 sadr : スレーブアドレス
- databuff: 送信するデータの入った配列
- datanum : 送信するデータ数
- 戻り値 0 : 送信完了 -1 : 送信エラー
- */
- int i2cSendData(unsigned char sadr, const unsigned char databuff[], int datanum)
- {
- int senddata=-1,ret=-1;
- i2cBusFree();
- i2cStart();
- while(senddata<datanum) {
- if(RIIC0.ICSR2.BIT.NACKF != 0) goto sendstop; //送信エラー
- if(RIIC0.ICSR2.BIT.TDRE != 1) continue;
- if(senddata < 0) {
- RIIC0.ICDRT = sadr; //最初にアドレスを送信
- } else {
- RIIC0.ICDRT = databuff[senddata];
- }
- senddata++;
- }
- i2cCheckTEND();
- ret = 0; //送信完了
- sendstop:
- i2cStop();
- return ret;
- }
- /*
- スレーブアドレスを指定して複数byteのデータを受信する
- 引数 sadr : スレーブアドレス
- databuff: 受信したデータを入れる配列
- datanum : 受信するデータ数
- 戻り値 0 : 受信完了 -1 : 受信エラー
- */
- int i2cReceiveData(unsigned char sadr, unsigned char databuff[], int datanum)
- {
- int recvdata=0,ret=-1;
- unsigned char dummy;
- i2cBusFree();
- i2cStart();
- i2cSendByte(sadr | 0x01); // アドレス送信 受信設定(|0x01)
- i2cCheckTEND();
- if(datanum == 1 ) {
- databuff[0] = i2cReceiveByteStop();
- return 0;
- }
- if(RIIC0.ICSR2.BIT.NACKF == 0) {
- /* データ受信処理 */
- dummy = RIIC0.ICDRR; //dummy read
- while(recvdata < datanum) {
- if(RIIC0.ICSR2.BIT.RDRF != 1) continue;
- if(recvdata == (datanum-2) ) break;
- if(recvdata == (datanum-3) ) {
- RIIC0.ICMR3.BIT.WAIT = 1;
- }
- databuff[recvdata++] = RIIC0.ICDRR;
- }
- RIIC0.ICMR3.BIT.ACKBT = 1;
- databuff[recvdata++] = RIIC0.ICDRR;
- while(RIIC0.ICSR2.BIT.RDRF != 1);
- RIIC0.ICSR2.BIT.STOP = 0;
- RIIC0.ICCR2.BIT.SP = 1;
- databuff[recvdata++] = RIIC0.ICDRR;
- RIIC0.ICMR3.BIT.WAIT = 0;
- ret = 0;
- } else {
- /* 受信エラー */
- RIIC0.ICSR2.BIT.STOP = 0;
- RIIC0.ICCR2.BIT.SP = 1;
- dummy = RIIC0.ICDRR; //dummy read
- }
- while(RIIC0.ICSR2.BIT.STOP != 1);
- RIIC0.ICSR2.BIT.STOP = 0;
- RIIC0.ICSR2.BIT.NACKF = 0;
- return ret;
- }
- /*
- スレーブ・アドレスを指定してデバイスのレジスタ・メモリにデータを書き込む
- 引数 sadr : スレーブ・アドレス
- madr : レジスタ・メモリアドレス 16bit
- data : 書き込むデータ
- 戻り値 無し
- */
- void i2cDevWrite16(unsigned char sadr, unsigned short madr, unsigned char data)
- {
- unsigned char buf[3];
- buf[0] = madr >> 8;
- buf[1] = madr & 0xFF;
- buf[2] = data;
- i2cSendData(sadr,buf,3);
- /*
- i2cBusFree();
- i2cStart();
- i2cSendByte(sadr);
- i2cSendByte(madr >> 8);
- i2cSendByte(madr & 0xFF);
- i2cSendByte(data);
- i2cCheckTEND();
- i2cStop();
- */
- }
- /*
- スレーブアドレスとデバイスのレジスタ・アドレスを指定してデバイスからデータを読み込む
- 引数 sadr : スレーブ・アドレス
- madr : レジスタ・メモリアドレス 16bit
- 戻り値 読み込んだデバイスのデータ
- */
- unsigned char i2cDevRead16(unsigned char sadr, unsigned short madr)
- {
- unsigned char rdt;
- i2cBusFree();
- i2cStart();
- i2cSendByte(sadr);
- i2cSendByte(madr >> 8);
- i2cSendByte(madr & 0xFF);
- i2cCheckTEND();
- i2cReStart();
- i2cSendByte(sadr | 0x01);
- rdt = i2cReceiveByteStop();
- return rdt;
- }
疑問に思ったのですが、
i2cSendData()関数でI2C送信後、最後のバイトのACKを検出しなかった場合、200行目のNACKチェックせずに正常0でリターンしてしまいます。
意図したソースコードですか?
適宜修正してください。