トマト栽培の育苗で、丸1日分の時刻データ、3か所の地温データ、温度データをEEPROMに記録していました。それを約一か月間続けても、データはきちんととれていました。その時のEEPROMドライバーです。
Q43に新しく追加された機能、Timerを使ったタイムアウト処理で、通信失敗の場合、バスを解放します。
今回はTimer4を割り振っています。
EEPROM24LCxxx.h
/*
* File: 24LCxxx.h
* Created on 2023/01/04, 18:05
*/
#ifndef EEPROM24LCxxx_H
#define EEPROM24LCxxx_H
#ifdef __cplusplus
extern "C" {
#endif
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "Q_peripheral27Q43.h"
#define EEPROMdeviceAdd 0xAC
#define EEPROM24LC256 0xAC
#define EEPROM_PAGE_SIZE 32
extern uint8_t eepromPageBuffer[EEPROM_PAGE_SIZE];
extern uint8_t eeprom_b1Write(uint8_t _deviceAdd, uint16_t _address, uint8_t _data);
extern uint8_t eeprom_b1Read(uint8_t _deviceAdd,uint16_t _address);
extern uint8_t eeprom_bnWrite(uint8_t _deviceAdd,uint16_t _address, uint8_t *_dataArray);
extern uint8_t eeprom_bnRead(uint8_t _deviceAdd, uint16_t _address, uint8_t *_dataArray);
#ifdef __cplusplus
}
#endif
#endif /* 24LCXXX_H */
EEPROM24LCxxx.c
#include "EEPROM_24LCxxx.h"
#include "Q_I2C1.h"
uint8_t eeprom_b1Write(uint8_t _deviceAdd, uint16_t _address, uint8_t _data)
{
uint8_t _addH, _addL;
_addH=(uint8_t)(_address>>8);
_addL=(uint8_t)(_address);
PIE11bits.TMR4IE=1;
T4CONbits.TMR4ON=1;
I2C1CON0bits.EN=1;
I2C1ADB1 = _deviceAdd;
I2C1CNT=3;
I2C1TXB=_addH;
I2C1CON0bits.S=1;
while(!I2C1STAT0bits.BFRE)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
while(I2C1STAT1bits.TXBE!=1)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
I2C1TXB=_addL;
while(I2C1STAT1bits.TXBE!=1)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
I2C1TXB=_data;
while(I2C1STAT1bits.TXBE!=1)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
while(I2C1PIRbits.PC1IF==0)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
I2C1PIRbits.PC1IF=0;
I2C1CON0bits.S=0;
while(I2C1STAT0bits.MMA)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
//Set Clear Buffer Flag
I2C1STAT1bits.CLRBF = 1;
PIE11bits.TMR4IE=0;
T4CONbits.TMR4ON=0;
__delay_ms(10);
return true;
}
uint8_t eeprom_b1Read(uint8_t _deviceAdd,uint16_t _address)
{
uint8_t ret;
uint8_t _addH, _addL;
_addH=(uint8_t)(_address>>8);
_addL=(uint8_t)(_address);
PIE11bits.TMR4IE=1;
T4CONbits.TMR4ON=1;
I2C1CON0bits.EN=1;
I2C1ADB1 = _deviceAdd;
I2C1CNT=2;
I2C1TXB=_addH;
I2C1CON0bits.S=1;
while(!I2C1STAT0bits.BFRE)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return 0xE0;
}
};
while(I2C1STAT1bits.TXBE!=1)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return 0xE1;
}
};
I2C1TXB=_addL;
while(I2C1STAT1bits.TXBE!=1)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return 0xE2;
}
};
I2C1PIRbits.PC1IF=0;
//リスタート
I2C1CON0bits.RSEN=1;
while(!I2C1CON0bits.MDR)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return 0xE3;
}
};
I2C1CON0bits.S=1;
I2C1ADB1 = _deviceAdd|0x01;
I2C1CNT=1;
while(!I2C1STAT1bits.RXBF)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return 0xE4;
}
};
ret=I2C1RXB;
I2C1CON0bits.RSEN=0;
I2C1CON0bits.S=0;
I2C1PIR=0x00;
while(I2C1STAT0bits.MMA)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return 0xE5;
}
};
//Set Clear Buffer Flag
I2C1STAT1bits.CLRBF = 1;
PIE11bits.TMR4IE=0;
T4CONbits.TMR4ON=0;
return ret;
}
uint8_t eepromPageBuffer[EEPROM_PAGE_SIZE];
uint8_t eeprom_bnWrite(uint8_t _deviceAdd, uint16_t _address, uint8_t *_dataArray)
{
uint8_t cnt;
uint8_t _addH, _addL;
_addH=(uint8_t)(_address>>8);
_addL=(uint8_t)(_address);
PIE11bits.TMR4IE=1;
T4CONbits.TMR4ON=1;
I2C1CON0bits.EN=1;
I2C1ADB1 = _deviceAdd;
I2C1CNT=2+EEPROM_PAGE_SIZE;
I2C1TXB=_addH;
I2C1CON0bits.S=1;
while(!I2C1STAT0bits.BFRE)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
while(I2C1STAT1bits.TXBE!=1)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
I2C1TXB=_addL;
while(I2C1STAT1bits.TXBE!=1)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
do{
I2C1TXB=_dataArray[cnt++];
while(I2C1STAT1bits.TXBE!=1)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
}while(I2C1CNT!=0);
while(I2C1PIRbits.PC1IF==0)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
I2C1PIRbits.PC1IF=0;
I2C1CON0bits.S=0;
while(I2C1STAT0bits.MMA)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
//Set Clear Buffer Flag
I2C1STAT1bits.CLRBF = 1;
PIE11bits.TMR4IE=0;
T4CONbits.TMR4ON=0;
return true;
}
uint8_t eeprom_bnRead(uint8_t _deviceAdd, uint16_t _address, uint8_t *_dataArray)
{
uint8_t cnt,ret;
uint8_t _addH, _addL;
_addH=(uint8_t)(_address>>8);
_addL=(uint8_t)(_address);
PIE11bits.TMR4IE=1;
T4CONbits.TMR4ON=1;
I2C1CON0bits.EN=1;
I2C1ADB1 = _deviceAdd;
I2C1CNT=2;
I2C1TXB=_addH;
I2C1CON0bits.S=1;
while(!I2C1STAT0bits.BFRE)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return 0xE0;
}
};
while(I2C1STAT1bits.TXBE!=1)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return 0xE1;
}
};
I2C1TXB=_addL;
while(I2C1STAT1bits.TXBE!=1)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return 0xE2;
}
};
I2C1PIRbits.PC1IF=0;
//リスタート
I2C1CON0bits.RSEN=1;
while(!I2C1CON0bits.MDR)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return 0xE3;
}
};
I2C1CON0bits.S=1;
I2C1ADB1 = _deviceAdd|0x01;
I2C1CNT=EEPROM_PAGE_SIZE;//32bytes
cnt=0;
do{
while(!I2C1STAT1bits.RXBF)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return 0xE4;
}
};
_dataArray[cnt++]=I2C1RXB;
}while(I2C1CNT!=0);
I2C1CON0bits.RSEN=0;
I2C1CON0bits.S=0;
I2C1PIR=0x00;
while(I2C1STAT0bits.MMA)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return 0xE5;
}
};
//Set Clear Buffer Flag
I2C1STAT1bits.CLRBF = 1;
PIE11bits.TMR4IE=0;
T4CONbits.TMR4ON=0;
return 1;
}
Q_I2C1.h
#ifndef Q_I2C1_H
#define Q_I2C1_H
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "Q_peripheral27Q43.h"
extern void I2C1_Init(void);
extern bool I2C1_b1Write(uint8_t _deviceAdd, uint8_t _data1);
extern uint8_t I2C1_b2Write(uint8_t _deviceAdd, uint8_t _data1, uint8_t _data2);
extern uint8_t I2C1_b1Read(uint8_t _deviceAdd,uint8_t _address);
extern uint8_t I2C1_b2Read(uint8_t _deviceAdd,uint8_t _address ,uint8_t* buf);
extern void I2C_TimeOUT_OP(void);
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* Q_I2C1_H */
QI2C1.c
#include <pic18f27q43.h>
#include "Q_I2C1.h"
uint8_t i2c1Cnt;
//*************************************************//
//** I2C1初期化
//*************************************************//
void I2C1_Init(void)
{
//Set Clear Buffer Flag
I2C1STAT1bits.CLRBF = 1;
I2C1CON0bits.MODE=0b100;//master mod, 7bits address
I2C1CON1bits.ACKCNT=1;
I2C1CON2bits.ABD=0;//I2C1ADB0/1use
I2C1CON2bits.BFRET=0b11;//64clocks
I2C1CLK=0b0011;//MFINTOSC500kHz
I2C1PIR=0x00;
//Bus Time out
I2C1BTO=0b0010;//Timer4
I2C1ERRbits.BTOIE=1;
I2C1ERRbits.BTOIF=0;
I2C1CON0bits.EN=1;
}
//*************************************************//
//** I2C1 1バイト送信
//*************************************************//
bool I2C1_b1Write(uint8_t _deviceAdd, uint8_t _data1)
{
PIR11bits.TMR4IF=0;
PIE11bits.TMR4IE=1;
T4CONbits.TMR4ON=1;
I2C1CON0bits.EN=1;
I2C1ADB1 = _deviceAdd;
I2C1CNT=1;
I2C1TXB=_data1;
I2C1CON0bits.S=1;
while(!I2C1STAT0bits.BFRE)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
while(!I2C1STAT1bits.TXBE)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
while(I2C1PIRbits.PC1IF==0)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
I2C1PIRbits.PC1IF=0;
I2C1CON0bits.S=0;
while(I2C1STAT0bits.MMA)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
//Set Clear Buffer Flag
I2C1STAT1bits.CLRBF = 1;
PIE11bits.TMR4IE=0;
T4CONbits.TMR4ON=0;
TMR4=0;
return true;
}
//*************************************************//
//** I2C1 2バイト送信
//*************************************************//
uint8_t I2C1_b2Write(uint8_t _deviceAdd, uint8_t _data1, uint8_t _data2)
{
PIE11bits.TMR4IE=1;
T4CONbits.TMR4ON=1;
I2C1CON0bits.EN=1;
I2C1ADB1 = _deviceAdd;
I2C1CNT=2;
I2C1TXB=_data1;
I2C1CON0bits.S=1;
while(!I2C1STAT0bits.BFRE)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
while(I2C1STAT1bits.TXBE!=1)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
//while(!I2C1CON1bits.ACKSTAT);
I2C1TXB=_data2;
while(I2C1STAT1bits.TXBE!=1)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
while(I2C1PIRbits.PC1IF==0)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
I2C1PIRbits.PC1IF=0;
I2C1CON0bits.S=0;
while(I2C1STAT0bits.MMA)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
//Set Clear Buffer Flag
I2C1STAT1bits.CLRBF = 1;
PIE11bits.TMR4IE=0;
T4CONbits.TMR4ON=0;
return true;
}
//*************************************************//
//** I2C1 1バイト受信
//*************************************************//
uint8_t I2C1_b1Read(uint8_t _deviceAdd,uint8_t _address)
{
uint8_t ret;
PIE11bits.TMR4IE=1;
T4CONbits.TMR4ON=1;
I2C1ADB1 = _deviceAdd;
I2C1CNT=1;
I2C1TXB=_address;
I2C1CON0bits.S=1;
while(!I2C1STAT0bits.BFRE)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
while(I2C1STAT1bits.TXBE!=1)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
I2C1PIRbits.PC1IF=0;
//リスタート
I2C1CON0bits.RSEN=1;
while(!I2C1CON0bits.MDR)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
I2C1CON0bits.S=1;
I2C1ADB1 = _deviceAdd|0x01;
I2C1CNT=1;
while(!I2C1STAT1bits.RXBF)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
ret=I2C1RXB;
I2C1CON0bits.RSEN=0;
I2C1CON0bits.S=0;
I2C1PIR=0x00;
while(I2C1STAT0bits.MMA)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
//Set Clear Buffer Flag
I2C1STAT1bits.CLRBF = 1;
PIE11bits.TMR4IE=0;
T4CONbits.TMR4ON=0;
return ret;
}
//*************************************************//
//** I2C1 2バイト受信
//*************************************************//
uint8_t I2C1_b2Read(uint8_t _deviceAdd,uint8_t _address ,uint8_t* buf)
{
uint8_t ret;
PIE11bits.TMR4IE=1;
T4CONbits.TMR4ON=1;
I2C1ADB1 = _deviceAdd;
I2C1CNT=1;
I2C1TXB=_address;
I2C1CON0bits.S=1;
while(!I2C1STAT0bits.BFRE)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
while(I2C1STAT1bits.TXBE!=1)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
I2C1PIRbits.PC1IF=0;
//リスタート
I2C1CON0bits.RSEN=1;
while(!I2C1CON0bits.MDR)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
I2C1CON0bits.S=1;
I2C1ADB1 = _deviceAdd|0x01;
I2C1CNT=2;
while(!I2C1STAT1bits.RXBF)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
I2C1CON1bits.ACKDT=0;
buf[0]=I2C1RXB;
while(!I2C1STAT1bits.RXBF)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
//I2C1CON1bits.ACKDT=0;
//I2C1CON1bits.ACKCNT=0;
buf[1]=I2C1RXB;
//I2C1CON1bits.ACKDT=0;
I2C1CON0bits.RSEN=0;
I2C1CON0bits.S=0;
I2C1PIR=0x00;
while(I2C1STAT0bits.MMA)
{
if(I2C1ERRbits.BTOIF)
{
I2C_TimeOUT_OP();
return false;
}
};
//Set Clear Buffer Flag
I2C1STAT1bits.CLRBF = 1;
PIE11bits.TMR4IE=0;
T4CONbits.TMR4ON=0;
return ret;
}
void I2C_TimeOUT_OP(void)
{
I2C1ERRbits.BTOIF=0;
PIE11bits.TMR4IE=0;
T4CONbits.TMR4ON=0;
TMR4=0x00;
I2C1CON0bits.S=0;
I2C1STAT1bits.CLRBF = 1;
I2C1CON0bits.EN=0;
}