📄 i2c.c
字号:
/*********************************************************************
* i2c.c - I2c Function.
*
* This file contain all the functions about I2C bus. This function
* include:
* (1) Initialize the PPC885 's I2C controller
* (2) Initialize the real time clock chip - DS1307
* (3) eeprom read function
* (4) eeprom write function
* (5) DS1307 read function
* (6) DS1307 write function
*
**********************************************************************/
#include "vxWorks.h"
#include "stdio.h"
#include "string.h"
#include "drv/multi/ppc860Siu.h"
#include "drv/sio/ppc860Sio.h"
#include "ads88x.h"
#include "i2c.h"
#include "config.h"
#define I2C_TXBD_OFF 0x600
#define I2C_RXBD_OFF (I2C_TXBD_OFF + 0x10)
#define I2C_TXBUF_OFF 0x700
#define I2C_RXBUF_OFF (I2C_TXBUF_OFF + 0x50)
#ifdef AT24C256
#define EEPROM_MEM_SIZE 0x4000
#define PAGE_SIZE 64
#define PAGE_NUM_MAX (EEPROM_MEM_SIZE/PAGE_SIZE)
#endif
#ifdef AT24C16
#define EEPROM_MEM_SIZE 0x800
#define PAGE_SIZE 16
#define PAGE_NUM_MAX (EEPROM_MEM_SIZE/PAGE_SIZE)
#endif
#define EEPROM_DELAY_TIME 25000
#define RTC_DELAY_TIME 6000
I2C_DEV *pChan;
extern UINT32 vxImmrIsbGet(void);
void delay(int n);
/**********************************************************************
* readAddrVerify - verify the read address of slave device
*
* For read operation, the lsb bit of device address is '1'.
*
* RETURN: OK or ERROR
**********************************************************************/
STATUS readAddrVerify(UCHAR deviceAddr)
{
if((deviceAddr & 0x01) == 0x00)
{
printf("It's not a valid read address\n");
return(ERROR);
}
return(OK);
}
/**********************************************************************
* writeAddrVerify - verify the write address of slave device
*
* For write operation, the lsb bit of device address is '0'.
*
* RETURN: OK or ERROR
**********************************************************************/
STATUS writeAddrVerify(UCHAR deviceAddr)
{
if((deviceAddr & 0x01) == 0x01)
{
printf("It's not a valid write address\n");
return(ERROR);
}
return(OK);
}
/**********************************************************************
* I2cInit - initialize the MPC885's i2c controller
*
* Initialize the MPC885's i2c controller including:
* (1) set PB26 PB27 as I2CSCL and I2CSDA
* (2) initialize the i2c's parameter RAM
* (3) initialize the i2c's registers
* (4) initialize the i2c's BD. There has one RXBD and one TXBD
* If you want detail information about this, please see the MPC885's
* User Manual in detail.
*
* RETURN: none
**********************************************************************/
STATUS I2cInit(void)
{
UINT32 regBase;
/* get the registers' base address */
regBase = vxImmrIsbGet ();
/* set PB26 PB27 as I2CSCL and I2CSDA */
*PBODR(regBase) |= (PB26 | PB27);
*PBPAR(regBase) |= (PB26 | PB27);
*PBDIR(regBase) |= (PB26 | PB27);
/* get the parameter RAM address */
pChan->i2cParam = (I2C_PARAM *) PPC860_DPR_I2C (MPC860_DPRAM_BASE(regBase));
pChan->i2cParam->rbase = (UINT16) (I2C_RXBD_OFF);
pChan->i2cParam->tbase = (UINT16) (I2C_TXBD_OFF);
/* set the parameter RAM */
pChan->i2cParam->rfcr = 0x10;
pChan->i2cParam->tfcr = 0x10;
pChan->i2cParam->mrblr = 0x50; /* maximum receive buffer length is 64 bytes */
*CPCR(regBase) = 0x11; /* initialize i2c RX and TX parameter RAM */
*I2MOD(regBase) = 0x00;
*I2BRG(regBase) = 0x20; /* set the i2c baudrate */
*I2ADD(regBase) = 0x80; /* set the i2c controller's address */
*I2CER(regBase) = 0x17; /* clear all interrupt pending bit */
*I2CMR(regBase) = 0x00; /* mask all interrupt */
*I2COM(regBase) = 0x01; /* set i2c as master */
*I2MOD(regBase) = 0x01; /* enable i2c controller */
/* get the transmit and receive BD address */
pChan->i2cRxBuf = (I2C_BUF *)(MPC860_DPRAM_BASE(regBase) + I2C_RXBD_OFF);
pChan->i2cTxBuf = (I2C_BUF *)(MPC860_DPRAM_BASE(regBase) + I2C_TXBD_OFF);
/* initialize the RXBD */
pChan->i2cRxBuf->statusMode = 0xb000;
pChan->i2cRxBuf->dataLength = 0x0;
pChan->i2cRxBuf->dataPointer = (u_char *)(MPC860_DPRAM_BASE(regBase) + I2C_RXBUF_OFF);
/* initialize the TXBD */
pChan->i2cTxBuf->statusMode = 0x3c00;
pChan->i2cTxBuf->dataPointer = (u_char *)(MPC860_DPRAM_BASE(regBase) + I2C_TXBUF_OFF);
/*
if (eepromWriteEnable() == ERROR)
{
return (ERROR);
}
*/
return (OK);
}
/**********************************************************************
* I2cStart - generate a start operation and sending data
*
* RETURN: none
**********************************************************************/
void I2cStart(UINT32 regBase)
{
*I2COM(regBase) |= 0x80;
}
/**********************************************************************
* eepromWriteEnable - be enable to write eeprom
*
* RETURN: OK or ERROR
**********************************************************************/
STATUS eepromWriteEnable(void)
{
UCHAR intStat;
u_char *txPtr;
UINT32 regBase = vxImmrIsbGet();
txPtr = pChan->i2cTxBuf->dataPointer;
txPtr[0] = 0xa0;
txPtr[1] = 0xff;
txPtr[2] = 0xff;
txPtr[3] = 0x02;
pChan->i2cTxBuf->statusMode = 0x3c00;
pChan->i2cTxBuf->dataLength = 0x04;
pChan->i2cTxBuf->statusMode |= 0x8000;
I2cStart (regBase);
while((pChan->i2cTxBuf->statusMode) & 0x8000);
if (pChan->i2cTxBuf->statusMode & 0x0004 )
{
*I2CER(regBase) = 0x17;
printf ("eepromWriteEnable: no ACK\n");
return (ERROR);
}
intStat = *I2CER(regBase);
if (intStat & 0x10)
{
*I2CER(regBase) = 0x17;
return(ERROR);
}
*I2CER(regBase) = 0x17;
delay (EEPROM_DELAY_TIME);
return(OK);
}
/**********************************************************************
* eepromWriteDisable - be disable to write eeprom
*
* RETURN: OK or ERROR
**********************************************************************/
STATUS eepromWriteDisable(void)
{
UCHAR intStat;
u_char *txPtr;
UINT32 regBase = vxImmrIsbGet();
txPtr = pChan->i2cTxBuf->dataPointer;
txPtr[0] = 0xa0;
txPtr[1] = 0xff;
txPtr[2] = 0xff;
txPtr[3] = 0x00;
pChan->i2cTxBuf->statusMode = 0x3c00;
pChan->i2cTxBuf->dataLength = 0x04;
pChan->i2cTxBuf->statusMode |= 0x8000;
I2cStart (regBase);
while((pChan->i2cTxBuf->statusMode) & 0x8000);
if (pChan->i2cTxBuf->statusMode & 0x0004 )
{
*I2CER(regBase) = 0x17;
printf ("eepromWriteDisable: no ACK\n");
return (ERROR);
}
intStat = *I2CER(regBase);
if (intStat & 0x10)
{
*I2CER(regBase) = 0x17;
return(ERROR);
}
*I2CER(regBase) = 0x17;
delay (EEPROM_DELAY_TIME);
return(OK);
}
/**********************************************************************
* eepromByteWrite - write a byte to eeprom
*
* RETURN: OK or ERROR
**********************************************************************/
STATUS eepromByteWrite(UCHAR deviceAddr, UCHAR wordAddrH, UCHAR wordAddrL, char data)
{
UCHAR intStat;
UCHAR count = 0;
u_char *txPtr;
UINT32 regBase = vxImmrIsbGet();
UINT16 offset;
if (writeAddrVerify(deviceAddr) == ERROR)
{
return (ERROR);
}
offset = wordAddrH * 256 + wordAddrL;
if (offset >= EEPROM_MEM_SIZE)
{
printf ("Invalid address\n");
return (ERROR);
}
txPtr = pChan->i2cTxBuf->dataPointer;
#ifdef AT24C16
deviceAddr &= (~0x0e);
deviceAddr |= (wordAddrH<<1);
txPtr[0] = deviceAddr;
txPtr[1] = wordAddrL;
txPtr[2] = data;
pChan->i2cTxBuf->statusMode = 0x3c00;
pChan->i2cTxBuf->dataLength = 0x03;
pChan->i2cTxBuf->statusMode |= 0x8000;
#else
txPtr[0] = deviceAddr;
txPtr[1] = wordAddrH;
txPtr[2] = wordAddrL;
txPtr[3] = data;
pChan->i2cTxBuf->statusMode = 0x3c00;
pChan->i2cTxBuf->dataLength = 0x04;
pChan->i2cTxBuf->statusMode |= 0x8000;
#endif
I2cStart (regBase);
while((pChan->i2cTxBuf->statusMode) & 0x8000);
if (pChan->i2cTxBuf->statusMode & 0x0007)
{
*I2CER(regBase) = 0x17;
return (ERROR);
}
intStat = *I2CER(regBase);
if (intStat & 0x10)
{
*I2CER(regBase) = 0x17;
return(ERROR);
}
*I2CER(regBase) = 0x17;
delay (EEPROM_DELAY_TIME);
/*
do
{
pChan->i2cTxBuf->statusMode = 0x3c00;
pChan->i2cTxBuf->dataLength = 0x03;
pChan->i2cTxBuf->statusMode |= 0x8000;
I2cStart (regBase);
while((pChan->i2cTxBuf->statusMode) & 0x8000);
if ((count++) >100)
{
*I2CER(regBase) = 0x17;
printf ("polling timeout\n");
return (ERROR);
}
delay (EEPROM_DELAY_TIME);
} while (pChan->i2cTxBuf->statusMode & 0x0004 );
*I2CER(regBase) = 0x17;
delay (EEPROM_DELAY_TIME);
*/
return(OK);
}
/**********************************************************************
* eepromPageWrite - page write to eeprom
*
* This function is used to write a page to eeprom. A page is 64 byte.
* You can write less number, but cannot write more than 64 byte, or
* it will roll over the page head and destroy the exsiting data.
*
* RETURN: the number that you write to eeprom or ERROR if failed
**********************************************************************/
STATUS eepromPageWrite(UCHAR deviceAddr, int pageNum, UCHAR offset, char *buf, int number)
{
UCHAR wordAddrH;
UCHAR wordAddrL;
UINT16 address;
UCHAR intStat;
UCHAR count = 0;
u_char *txPtr;
UINT32 regBase = vxImmrIsbGet();
printf ("deviceAddr = %x\n", deviceAddr);
printf ("pageNum = %x\n", pageNum);
printf ("offset = %x\n", offset);
printf ("number = %x\n", number);
printf ("buf: %s\n", buf);
if ((buf == NULL) ||(number < 0) || (number > PAGE_SIZE))
{
return(ERROR);
}
if((pageNum >= PAGE_NUM_MAX) || (offset >= PAGE_SIZE))
{
printf("Invalid address\n");
return(ERROR);
}
if (writeAddrVerify(deviceAddr) == ERROR)
{
return (ERROR);
}
txPtr = pChan->i2cTxBuf->dataPointer;
#ifdef AT24C16
deviceAddr &= (~0x0e);
deviceAddr |= (pageNum<<1);
txPtr[0] = deviceAddr;
txPtr[1] = offset;
memcpy((txPtr + 2), buf, number);
pChan->i2cTxBuf->statusMode = 0x3c00;
pChan->i2cTxBuf->dataLength = (number + 2);
pChan->i2cTxBuf->statusMode |= 0x8000;
#else
address = (pageNum * PAGE_SIZE) + offset;
wordAddrL = (UCHAR) (address & 0xff);
wordAddrH = (UCHAR) ((address & 0xff00) >> 8);
txPtr[0] = deviceAddr;
txPtr[1] = wordAddrH;
txPtr[2] = wordAddrL;
memcpy((txPtr + 3), buf, number);
pChan->i2cTxBuf->statusMode = 0x3c00;
pChan->i2cTxBuf->dataLength = (number + 3);
pChan->i2cTxBuf->statusMode |= 0x8000;
#endif
I2cStart (regBase);
while((pChan->i2cTxBuf->statusMode) & 0x8000);
if (pChan->i2cTxBuf->statusMode & 0x0007)
{
*I2CER(regBase) = 0x17;
return (ERROR);
}
intStat = *I2CER(regBase);
if (intStat & 0x10)
{
*I2CER(regBase) = 0x17;
return(ERROR);
}
*I2CER(regBase) = 0x17;
delay (EEPROM_DELAY_TIME);
/*
do
{
pChan->i2cTxBuf->statusMode = 0x3c00;
pChan->i2cTxBuf->dataLength = 0x03;
pChan->i2cTxBuf->statusMode |= 0x8000;
I2cStart (regBase);
while((pChan->i2cTxBuf->statusMode) & 0x8000);
if ((count++) >100)
{
*I2CER(regBase) = 0x17;
printf ("polling timeout\n");
return (ERROR);
}
delay (EEPROM_DELAY_TIME);
} while (pChan->i2cTxBuf->statusMode & 0x0004 );
*I2CER(regBase) = 0x17;
delay (EEPROM_DELAY_TIME);
*/
return(OK);
}
/**********************************************************************
* eepromCurrentRead - read a byte of current address from eeprom
*
* RETURN: the number that you write to eeprom or ERROR if failed
**********************************************************************/
STATUS eepromCurrentRead(UCHAR deviceAddr, char *data)
{
UCHAR *txPtr;
UCHAR *rxPtr;
UINT32 regBase;
UCHAR intStat;
if(readAddrVerify(deviceAddr) == ERROR)
{
return(ERROR);
}
regBase = vxImmrIsbGet();
txPtr = pChan->i2cTxBuf->dataPointer;
txPtr[0] = deviceAddr;
pChan->i2cTxBuf->statusMode = 0x3c00;
pChan->i2cTxBuf->dataLength = 2;
pChan->i2cTxBuf->statusMode |= 0x8000;
I2cStart(regBase);
while((pChan->i2cTxBuf->statusMode) & 0x8000);
if (pChan->i2cTxBuf->statusMode & 0x0007)
{
*I2CER(regBase) = 0x17;
return (ERROR);
}
intStat = *I2CER(regBase);
if (intStat & 0x10)
{
*I2CER(regBase) = 0x17;
return(ERROR);
}
*I2CER(regBase) = 0x12;
while((pChan->i2cRxBuf->statusMode) & 0x8000);
intStat = *I2CER(regBase);
if ((intStat & 0x01) != 0x01) {
*I2CER(regBase) = 0x17;
return(ERROR);
}
rxPtr = pChan->i2cRxBuf->dataPointer;
*data = *rxPtr;
pChan->i2cRxBuf->statusMode = 0xb000;
pChan->i2cRxBuf->dataLength = 0x0;
delay (EEPROM_DELAY_TIME);
return(OK);
}
/*********************************************************************
* eepromRandomRead - random read from eeprom.
*
* RETURN: OK or ERROR.
*/
STATUS eepromRandomRead (UCHAR deviceAddr, UCHAR wordAddrH, UCHAR wordAddrL, char *data)
{
UCHAR intStat;
UCHAR count = 0;
u_char *txPtr;
u_char *rxPtr;
UINT32 regBase = vxImmrIsbGet();
UINT16 offset;
if (readAddrVerify(deviceAddr) == ERROR)
{
return (ERROR);
}
offset = wordAddrH * 256 + wordAddrL;
if (offset >= EEPROM_MEM_SIZE)
{
printf ("Invalid address\n");
return (ERROR);
}
txPtr = pChan->i2cTxBuf->dataPointer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -