📄 ixdp2400i2c.c
字号:
/*ixdp2400I2c.c - I2c protocol driver*//*modification history--------------------rev, 5apr02, vgd - creation*/#include "ixdp2400I2c.h"#include "ixdp2400.h"/*Function prototypes*/static void I2C_CLK(unsigned char x);static void I2C_DATA(unsigned char x);static void i2c_start(void);static void i2c_stop(void);static unsigned char i2c_ReadBit(void);static void i2c_WriteBit(unsigned char x);static void i2c_writebyte(unsigned char data);static unsigned char i2c_readbyte(void);unsigned char i2c_device_busy(unsigned char);/*i2c_ack_stat is 0 if there is no error. *bit 0 is 1 if ack is not recd after writing slave address in write mode. *bit 1 is 1 if ack is not recd after writing word address, *bit 2 is 1 if ack is not recd after writing slave address in read mode, *bit 3 is 1 if ack not recd after sending a data byte. *//*************************************************************************Function Name : I2C_CLKInput : HIGH or LOWOutPut : NoneDesc : sets the SCL pin low or high**************************************************************************/static void I2C_CLK(unsigned char x){ int i = 5000; int temp; FAST int locKey; locKey = intLock (); switch(x) { /*To drive the clock high, set the direction as input i.e., write to * the direction clear register */ case HIGH: IXP2400_REG_WRITE(IXP2400_GPIO_PDCR,CLOCK); IXP2400_REG_READ(IXP2400_GPIO_PDCR, temp); /*read PLR until it is high*/ while(!(*(volatile UINT32*) IXP2400_GPIO_PLR & CLOCK) && i--); break; /*To drive the clock low, set the direction as output i.e., write to * the direction set register */ case LOW: IXP2400_REG_WRITE(IXP2400_GPIO_PDSR,CLOCK); IXP2400_REG_READ(IXP2400_GPIO_PDSR, temp); break; } intUnlock (locKey);}/*************************************************************************Function Name : I2C_DATAInput : High or LowOutPut : NoneDesc : Sets the SDA pin Low or High**************************************************************************/static void I2C_DATA(unsigned char x){ FAST int locKey; int temp; locKey = intLock (); switch(x) { case HIGH: IXP2400_REG_WRITE(IXP2400_GPIO_PDCR,DATA); IXP2400_REG_READ(IXP2400_GPIO_PDCR, temp); break; case LOW: IXP2400_REG_WRITE(IXP2400_GPIO_PDSR,DATA); IXP2400_REG_READ(IXP2400_GPIO_PDSR, temp); break; } intUnlock (locKey);}/*************************************************************************Function Name : i2c_startInput : NoneOutPut : NoneDesc : generate i2c start condition.Start Condition: High to Low transition of SDA when SCL is high**************************************************************************/ static void i2c_start(void){ /*SDA=1, SCL=1 */ I2C_DATA(HIGH); I2C_CLK(HIGH); I2C_DELAY(CLOCK_HIGH_TIME); /*SCL=1, SDA=0*/ I2C_DATA(LOW); I2C_DELAY(START_CONDITION_HOLD_TIME); /*SCL=0 SDA=0*/ I2C_CLK(LOW); I2C_DELAY(CLOCK_LOW_TIME);}/*****************************************************************************Function name : i2c_stopInput : NoneOutPut : NoneDesc : Generate i2c stop condition:LOW to High transition of SDA when SCL is high*******************************************************************************/static void i2c_stop(void){ /*SCL=0, SDA=0 */ I2C_DATA(LOW); I2C_DELAY(CLOCK_LOW_TIME*2); /*SCL=1, SDA=0*/ I2C_CLK(HIGH); I2C_DELAY(CLOCK_HIGH_TIME*2); /*SCL=1 SDA=1*/ I2C_DATA(HIGH); I2C_DELAY(STOP_CONDITION_HOLD_TIME); }/***************************************************************************Function Name : i2c_ReadBit()Input : noneOutPut : returns the read bitDesc : read bit on sda*****************************************************************************/static unsigned char i2c_ReadBit(void){ unsigned char x; FAST int locKey; I2C_CLK(LOW); I2C_DELAY(CLOCK_LOW_TIME ); I2C_CLK(HIGH); I2C_DELAY(CLOCK_LOW_TIME ); locKey = intLock (); x= (unsigned char)((*(unsigned int*)(IXP2400_GPIO_PLR)) & DATA); intUnlock (locKey); I2C_CLK(LOW); I2C_DELAY(CLOCK_LOW_TIME); return ( (x & DATA) ? 1 : 0); }/****************************************************************************Function Name : i2c_WriteBit()Input : bit to be writtenOutPut : noneDesc : output a bit onto sda******************************************************************************/static void i2c_WriteBit(unsigned char x){ I2C_CLK(LOW); I2C_DELAY(CLOCK_LOW_TIME/2); if (x & 0x80) /* the MSB is sent out first*/ I2C_DATA(HIGH); else I2C_DATA(LOW); I2C_DELAY(CLOCK_LOW_TIME); I2C_CLK(HIGH); I2C_DELAY(CLOCK_HIGH_TIME); I2C_CLK(LOW); I2C_DELAY(CLOCK_LOW_TIME); I2C_DATA(HIGH); }/******************************************************************************Function Name : i2c_writebyteInput : byte to be writtenOutPut : NoneDesc : write a byte onto i2c ********************************************************************************/static void i2c_writebyte(unsigned char data){ int i; for(i=0;i<8;i++){ i2c_WriteBit(data); data<<=1; } I2C_DATA(HIGH);/*release SDA*/}/****************************************************************************Function Name : i2c_readbyteInput : noneOutPut : returns the byte read from the i2c deviceDesc : read a byte from i2c ******************************************************************************/static unsigned char i2c_readbyte(void){ unsigned char bit; unsigned char data=0x0; /*The MSB is read first*/ for(data=0,bit=0;bit<7;bit++) { data|=i2c_ReadBit(); data<<=1; } data|=i2c_ReadBit(); return data; }void i2c_init0(void){ FAST int locKey; locKey = intLock (); IXP2400_REG_WRITE((unsigned int *)IXP2400_GPIO_PDSR, (I2C_INIT_BIT)); /*drive this pin high*/ IXP2400_REG_WRITE((unsigned int *)IXP2400_GPIO_POSR, (I2C_INIT_BIT)); intUnlock (locKey); i2c_init();}/****************************************************************************Function Name : i2c_initInput : noneOutPut : noneDesc : configures the GPIO 2 and 3 for output******************************************************************************/void i2c_init(void){ int i; FAST int locKey; int temp; locKey = intLock (); /* initially at power up SDA has pull down because it is used as strap pin. * the PCI_ARB strap pin which is GPIO 2 should be driven high inorder to * have a pull up on SDA line. This is required by this board design */ /*configure pin 7 and 6 to be output*/ IXP2400_REG_WRITE((unsigned int *)IXP2400_GPIO_PDSR, (CLOCK|DATA)); /*make the output level on pins gpio 6 and 7 low*/ IXP2400_REG_WRITE((unsigned int *)IXP2400_GPIO_POCR, (CLOCK|DATA)); /*make pins 6 and 7 as input during init*/ IXP2400_REG_WRITE((unsigned int *)IXP2400_GPIO_PDCR, (CLOCK)); for(i=0;i<10;i++); IXP2400_REG_WRITE((unsigned int *)IXP2400_GPIO_PDCR, (DATA)); IXP2400_REG_READ(IXP2400_GPIO_PDCR, temp); intUnlock (locKey);}/******************************************************************************Function Name : i2c_readInput : Address of slave device to be read, location to be read ptr where read data has to be storedOutPut : noneDesc : read a byte of data(random read) on to i2c device******************************************************************************/void i2c_read(unsigned char slave, unsigned char addr, unsigned char *x){ unsigned char data = 0; unsigned char ack1, ack2, i2c_ack_stat; i2c_ack_stat=0x0; if(!i2c_device_busy(slave)) { i2c_writebyte(addr); ack1=i2c_ReadBit(); /*read ack from slave*/ if(ack1!=0) i2c_ack_stat |= 0x2; i2c_start(); i2c_writebyte(slave|I2C_READ); ack2=i2c_ReadBit(); if(ack2!=0) i2c_ack_stat |= 0x3; data = i2c_readbyte(); i2c_WriteBit(0x80); i2c_stop(); } *x=data; return ;}/******************************************************************************Function Name : i2c_seq_readInput : Address of slave device to be read, starting location to be read, no.of locations to be read ptr where the read data has to be storedOutPut : noneDesc : read a byte of data(random read) on to i2c device******************************************************************************/void i2c_seq_read(unsigned char slave, unsigned char addr, unsigned char *data, unsigned char count){ int i; unsigned char ack1, ack2, i2c_ack_stat; i2c_ack_stat=0x0; if(!i2c_device_busy(slave)) { i2c_writebyte(addr); ack1=i2c_ReadBit(); /*read ack from slave*/ if(ack1!=0) i2c_ack_stat |= 0x2; i2c_start(); i2c_writebyte(slave|I2C_READ); ack2=i2c_ReadBit(); if(ack2!=0) i2c_ack_stat |= 0x4; for(i=0;i<count;i++) { data[i] = i2c_readbyte(); if(i != (count-1)) i2c_WriteBit(0x0); /*send ack*/ else i2c_WriteBit(0x80); /*send nack after reading the last byte*/ } i2c_stop(); } return ;}/******************************************************************************Function Name : i2c_writeInput : Address of the slave device to be written, location to be wriiten, data to be writtenOutPut : noneDesc : Write a byte of data on to i2c device******************************************************************************/void i2c_write(unsigned char slave, unsigned char addr, unsigned char data){ unsigned char ack1, ack2, i2c_ack_stat; i2c_ack_stat=0x0; if(!i2c_device_busy(slave)) { i2c_writebyte(addr); ack1=i2c_ReadBit(); if(ack1!=0) i2c_ack_stat |= 0x2; i2c_writebyte(data); ack2=i2c_ReadBit(); if(ack2!=0) i2c_ack_stat |= 0x8; i2c_stop(); } }/******************************************************************************Function Name : i2c_page_writeInput : Address of the slave device to be written, location to be wriiten, ptr to data array to be writtenOutPut : noneDesc : Write a byte of data on to i2c device******************************************************************************/void i2c_page_write(unsigned char slave, unsigned char addr, unsigned char * data, unsigned char count){ int i; unsigned char ack1, ack2, i2c_ack_stat; i2c_ack_stat=0x0; if(count>16) count=16; if(!i2c_device_busy(slave)) { i2c_writebyte(addr); ack1=i2c_ReadBit(); if(ack1!=0) i2c_ack_stat |= 0x2; for(i=0;i<count;i++) { i2c_writebyte(data[i]); ack2=i2c_ReadBit(); if(ack2!=0) i2c_ack_stat |= 0x8; } i2c_stop(); }}/*once the stop condition is issued to indicate the end of the host's write *operation, the NM24c02/03 initialtes the internal write cycle. ACK polling *can be initiated immediately. This involves issuing the strat condition *followed by the slave address for write operation. if the i2c device is still *busy, no ack is returned. if the device completed its internal write *operation, an ack will be returned and the master can then proceed with next *read or write operation. the following function implements the ACLk polling. */unsigned char i2c_device_busy(unsigned char slave){ unsigned char busy=1; int i=0; while((busy!=0) && (i<100)) { i2c_start(); i2c_writebyte(slave); busy=i2c_ReadBit(); if(busy) i2c_stop(); i++; } return busy; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -