LoginSignup
0
0

PIC18F27Q43 外付けEEPROM(I2C)ドライバー

Last updated at Posted at 2024-05-10

トマト栽培の育苗で、丸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;
}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0