/***************************************************************************** * skI2Clib - I2C関数ライブラリ * このライブラリはI2Cデバイス(RTC/EEPROM等)と接続を行う為の関数集 * * InterI2C - I2C関連の割り込み処理 * InitI2C_Master - I2C通信のマスターモードで初期化を行う処理 * I2C_Start - スレーブにスタートコンディションを発行する処理 * I2C_rStart - スレーブにリピート・スタートコンディションを発行する処理 * I2C_Stop - スレーブにストップコンディションを発行する処理 * I2C_Send - スレーブにデータを1バイト送信する処理 * I2C_Receive - スレーブからデータを1バイト受信する処理 * * メモ:SDA/SCLピンは必ず「デジタル入力ピン」に設定を行って下さい。 * 通信クロックは100/400KHz(CPU8MHz)での初期化です。 * マルチマスター時にバス衝突が発生した場合は、"I2C_Start"から再送する * SSP2を利用する場合は、skI2Clib.hに"#define I2C_MSSP2_USE"を宣言する * ============================================================================ * VERSION DATE BY CHANGE/COMMENT * ---------------------------------------------------------------------------- * 1.00 2012-01-20 きむ茶工房(きむしげ) Create * 1.01 2013-02-16 きむ茶工房(きむしげ) XC8 C Compiler 対応に変更 * 2.00 2014-11-01 きむ茶工房(きむしげ) マルチマスターに対応 * 2.10 2015-03-04 きむ茶工房(きむしげ) 初期化で100/400KHz指定可に変更 * 3.00 2015-04-20 きむ茶工房(きむしげ) SSP1/SSP2両方と16F193xに対応 * ============================================================================ * PIC 12F1822 16F18xx 16F193x 18F25K22 * MPLAB IDE(V8.63) MPLAB X(v2.15) * MPLAB(R) XC8 C Compiler Version 1.00/1.32 * ============================================================================ * * PIC24F用ライブラリに改修 * 2017/1/2 N.Ishii *******************************************************************************/ #include #include "skI2C_PIC24F_lib.h" void IdleI2C(void) { // Wait until I2C Bus is Inactive while(I2C2CONbits.SEN || I2C2CONbits.PEN || I2C2CONbits.RCEN || I2C2CONbits.ACKEN || I2C2STATbits.TRSTAT); } void receive_ack(void) { while(I2C2STATbits.TBF) {;} // Wait TBF'0':TxBuffer Enpty while(I2C2STATbits.ACKSTAT) {;} // Wait ACKSTAT'0':A Response ACK } /******************************************************************************* * ans = I2C_Start(adrs,rw) * スレーブにスタートコンディションを発行する処理 * * adrs : スレーブのアドレスを指定します * rw : スレーブに対する動作の指定をします * 0=スレーブに書込みなさい要求 1=スレーブに送信しなさい要求 * ans : 0=正常 * 1=異常(相手からACKが返ってこない) -1=他のマスターとのバス衝突発生 *============================================================================== * * エラーチェック無し・PIC24F用に改修 N.Ishii *******************************************************************************/ void I2C_Start(int adrs,int rw) { // START Bus Event IdleI2C(); I2C2STATbits.I2COV = 0; // エラークリア I2C2CONbits.SEN = 1; // Set SENbit START Bus Event // Send Slave Address + W/Rbit while(I2C2CONbits.SEN); // Wait SENbit Clear I2C_Send((char)((adrs<<1)+rw)) ; // アドレス + R/Wを送信 } /******************************************************************************* * ans = I2C_rStart(adrs,rw) * スレーブにリピート・スタートコンディションを発行する処理 * * adrs : スレーブのアドレスを指定します * rw : スレーブに対する動作の指定をします * 0=スレーブに書込みなさい要求 1=スレーブに送信しなさい要求 * ans : 0=正常 * 1=異常(相手からACKが返ってこない) -1=他のマスターとのバス衝突発生 *============================================================================== * * エラーチェック無し・PIC24F用に改修 N.Ishii *******************************************************************************/ void I2C_rStart(int adrs,int rw) { // RESTART Bus Event IdleI2C(); I2C2CONbits.RSEN = 1; // Set RSENbit RESTART Bus Event // Send Slave Address + W/Rbit while(I2C2CONbits.RSEN); // リスタート終了待ち Wait RSENbit Clear I2C_Send((char)((adrs<<1)+rw)) ; // アドレス + R/Wを送信 } /******************************************************************************* * ans = I2C_Stop() * スレーブにストップコンディションを発行する処理 * ans : 0=正常 * -1=他のマスターとのバス衝突発生 *============================================================================== * * エラーチェック無し・PIC24F用に改修 N.Ishii *******************************************************************************/ void I2C_Stop() { // Stop Bus Event IdleI2C(); I2C2CONbits.PEN = 1; } /******************************************************************************* * ans = I2C_Send(dt) * スレーブにデータを1バイト送信する処理 * * dt : 送信するデータを指定します * ans : 0=正常 * 1=異常(相手からACKが返ってこない又はNOACKを返した) * -1=他のマスターとのバス衝突発生 *============================================================================== * * エラーチェック無し・PIC24F用に改修 N.Ishii *******************************************************************************/ void I2C_Send(char dt) { IdleI2C(); I2C2TRN = dt; while(I2C2STATbits.TBF); // 送信終了待ち // ACK待ち Receive ACK From Device receive_ack(); } /******************************************************************************* * ans = I2C_Receive(ack) * スレーブからデータを1バイト受信する処理 * * ack : スレーブへの返答データを指定します * 0:ACKを返す 1:NOACKを返す(受信データが最後なら1) * ans : 受信したデータを返す * -1=他のマスターとのバス衝突発生 *============================================================================== * * エラーチェック無し・PIC24F用に改修 N.Ishii *******************************************************************************/ int I2C_Receive(int ack) { int dt ; IdleI2C(); // データの受信 I2C2CONbits.RCEN = 1; // Valid I2C Rec Mode while(I2C2CONbits.RCEN); // 受信待ち→ 受信完了で、RCENビットがクリアされる IdleI2C(); dt= I2C2RCV; IdleI2C(); I2C2CONbits.ACKDT = ack; I2C2CONbits.ACKEN = 1; // Master is Response Sq return (dt) ; }