📄 i2c.c
字号:
/**
* @file i2c.c
* @brief I2C interface driver, define I2C interface APIs.
* This file provides I2C APIs: I2C initialization, write data to I2C & read data from I2C.
* @author Guanghua Zhang
* @date 2004-09-21
* @version 1.0
*/
#include "i2c.h"
#define I2C_DELAY_UNIT 12
#ifdef OS_EMBEDED
/* define GPIO register address */
#ifndef BASE_GPIO_TIMER
#define BASE_GPIO_TIMER 0x20090000 /* GPIO base address */
#define GPIO_DIR 0x00000000 /* input/output select register */
#define GPIO_INTE 0x00000004 /* Interrupt control register */
#define GPIO_INTP 0x00000008 /* Interrupt input polarity select register */
#define GPIO_IN 0x0000000C /* Port input real time data value */
#define GPIO_OUT 0x00000010 /* Port output real time data value */
#define GPIO_EDGE 0x00001008 /* Edge/level select register */
#endif /* end of BASE_GPIO_TIMER */
/* define I2C interface */
#ifndef SDA
#define SDA 0x08000000 /* I2C serial interface data I/O */
#define SCL 0x04000000 /* I2C serial interface clock input */
// #define BUSENABLE 0X00040000 /* I2C bus enable input */
#endif /* end of SDA */
static T_U32 i2c_backup_reg[6];
static T_VOID i2c_init(T_VOID);
static T_VOID i2c_free(T_VOID);
static T_VOID i2c_delay(T_U32 time);
static T_VOID set_i2c_pin(T_U32 pin);
static T_VOID clr_i2c_pin(T_U32 pin);
static T_U8 get_i2c_pin(T_U32 pin);
static T_VOID i2c_begin(T_VOID);
static T_VOID i2c_end(T_VOID);
static T_VOID i2c_write_ask(T_U8 flag);
static T_BOOL i2c_read_ack(T_VOID);
static T_U8 i2c_read_byte(T_VOID);
static T_BOOL i2c_write_byte(T_U8 data);
/**
* @brief receive one byte from I2C interface function
* receive one byte data from I2C bus
* @author Junhua Zhao
* @date 2005-04-05
* @param T_VOID
* @return T_U8: received the data
* @retval
*/
static T_U8 i2c_read_byte(T_VOID)
{
T_U8 i;
T_U8 ret;
ret = 0;
*(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_DIR) &= (~SDA);
for (i=0; i<8; i++)
{
i2c_delay(I2C_DELAY_UNIT << 2);
set_i2c_pin(SCL);
i2c_delay(I2C_DELAY_UNIT << 2);
ret = ret<<1;
if (get_i2c_pin(SDA))
ret |= 1;
i2c_delay(I2C_DELAY_UNIT << 2);
clr_i2c_pin(SCL);
i2c_delay(I2C_DELAY_UNIT << 1);
if (i==7)
*(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_DIR) |= SDA;
i2c_delay(I2C_DELAY_UNIT << 1);
}
return ret;
}
/**
* @brief write one byte to I2C interface function
* write one byte data to I2C bus
* @author Junhua Zhao
* @date 2005-04-05
* @param T_U8 data: send the data
* @return T_BOOL: return write success or failed
* @retval AK_FALSE: operate failed
* @retval AK_TRUE: operate success
*/
static T_BOOL i2c_write_byte(T_U8 data)
{
T_U8 i;
for (i=0; i<8; i++)
{
i2c_delay(I2C_DELAY_UNIT << 2);
if (data & 0x80)
set_i2c_pin(SDA);
else
clr_i2c_pin(SDA);
data <<= 1;
i2c_delay(I2C_DELAY_UNIT << 2);
set_i2c_pin(SCL);
i2c_delay(I2C_DELAY_UNIT << 3);
clr_i2c_pin(SCL);
}
return i2c_read_ack();
}
/**
* @brief I2C interface initialize function
* setup I2C interface
* @author Guanghua Zhang
* @date 2004-09-21
* @param T_VOID
* @return T_VOID
* @retval
*/
static T_VOID i2c_init(T_VOID)
{
T_U32 value;
i2c_backup_reg[0] = *(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_DIR);
i2c_backup_reg[1] = *(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_INTE);
i2c_backup_reg[2] = *(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_INTP);
i2c_backup_reg[3] = *(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_IN);
i2c_backup_reg[4] = *(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_OUT);
i2c_backup_reg[5] = *(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_EDGE);
value = SDA | SCL/* | BUSENABLE*/;
*(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_INTE) &= (~(value));
*(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_DIR) |= value;
*(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_OUT) |= value;
}
static T_VOID i2c_free(T_VOID)
{
*(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_DIR) = i2c_backup_reg[0];
*(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_INTE) = i2c_backup_reg[1];
*(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_INTP) = i2c_backup_reg[2];
*(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_IN) = i2c_backup_reg[3];
*(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_OUT) = i2c_backup_reg[4];
*(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_EDGE) = i2c_backup_reg[5];
}
/**
* @brief write data to I2C device
* write size length data to dab's rab register
* @author Guanghua Zhang
* @date 2004-09-21
* @param T_U8 dab: I2C device address
* @param T_U8 rab: register address
* @param T_U8 *data: write data's point
* @param T_U8 size: write data's length
* @return T_BOOL: return write success or failed
* @retval AK_FALSE: operate failed
* @retval AK_TRUE: operate success
*/
T_BOOL i2c_write_data(T_U8 dab, T_U8 rab, T_U8 *data, T_U8 size)
{
T_U8 i;
i2c_init();
i2c_begin();
if (!i2c_write_byte(dab))
{
i2c_end();
i2c_free();
return AK_FALSE;
}
if (!i2c_write_byte(rab))
{
i2c_end();
i2c_free();
return AK_FALSE;
}
for (i=0; i<size; i++)
{
if (!i2c_write_byte(*data))
{
i2c_end();
i2c_free();
return AK_FALSE;
}
data++;
}
i2c_end();
i2c_free();
return AK_TRUE;
}
//写时是先写起始位,再写地址,读应答位,再写数据,再读应答,至到5个数全部写完,最后写一个停止位。
T_BOOL i2c_write_data2(T_U8 dab, T_U8 *data, T_U8 size)
{
T_U8 i;
i2c_init();
i2c_begin();
if (!i2c_write_byte(dab))
{
i2c_end();
i2c_free();
return AK_FALSE;
}
for (i=0; i<size; i++)
{
if (!i2c_write_byte(data[i]))
{
i2c_end();
i2c_free();
return AK_FALSE;
}
}
i2c_end();
i2c_free();
return AK_TRUE;
}
/**
* @brief read data from I2C device function
* read data from dab's rab register
* @author Guanghua Zhang
* @date 2004-09-21
* @param T_U8 dab: I2C device address
* @param T_U8 rab: register address
* @param T_U8 *data: read output data store address
* @param T_U8 size: read data size
* @return T_BOOL: return write success or failed
* @retval AK_FALSE: operate failed
* @retval AK_TRUE: operate success
*/
T_BOOL i2c_read_data(T_U8 dab, T_U8 rab, T_U8 *data, T_U8 size)
{
T_U8 i;
i2c_init();
i2c_begin();
if (!i2c_write_byte(dab))
{
i2c_end();
i2c_free();
return AK_FALSE;
}
if (!i2c_write_byte(rab))
{
i2c_end();
i2c_free();
return AK_FALSE;
}
i2c_begin();
if (!i2c_write_byte((T_U8)(dab | 1)))
{
i2c_end();
i2c_free();
return AK_FALSE;
}
for(i=0; i<size; i++)
{
*data = i2c_read_byte();
(i<size-1)?i2c_write_ask(0):i2c_write_ask(1);
data++;
}
i2c_end();
i2c_free();
return AK_TRUE;
}
/**
* @brief read data from MCP3221 via I2C
* @MCP3221 is a 12 bits serial AD converter used for battery test
* @author YiRuoxiang
* @date 2006-04-12
* @param T_U8 *data: read output data store address
* @param T_U8 size: read data size
* @return T_BOOL: return write success or failed
* @retval AK_FALSE: operate failed
* @retval AK_TRUE: operate success
*/
T_BOOL i2c_read_data_MCP3221(T_U8 *data, T_U8 size)
{
T_U8 i;
i2c_init();
i2c_begin();
if (!i2c_write_byte(0x9B)) //0x9B = 1001 101 1: 1001 = device bits, 101 = address bits, 1 = read
{
i2c_end();
i2c_free();
return AK_FALSE;
}
for(i=0; i<size; i++)
{
*data = i2c_read_byte();
(i<size-1)?i2c_write_ask(0):i2c_write_ask(1);
data++;
}
i2c_end();
i2c_free();
return AK_TRUE;
}
//读的时候也是一样,写一个开始位,再写地址,再读应答,再读数据,读一个数据送一个应答,读完5个数就写一个停止位。
T_BOOL i2c_read_data2(T_U8 dab, T_U8 *data, T_U8 size)
{
T_U8 i;
i2c_init();
i2c_begin();
if (!i2c_write_byte((T_U8)(dab | 1)))
{
i2c_end();
i2c_free();
return AK_FALSE;
}
for(i=0; i<size; i++)
{
data[i] = i2c_read_byte();
(i<size-1)?i2c_write_ask(0):i2c_write_ask(1);
}
i2c_end();
i2c_free();
return AK_TRUE;
}
/**
* @brief delay function
* delay the time
* @author Guanghua Zhang
* @date 2004-09-21
* @param T_U32 time: delay time
* @return T_VOID
* @retval
*/
static T_VOID i2c_delay(T_U32 time)
{
while(time--)
{
;
}
}
/**
* @brief set input function
* set I2C input: 1
* @author Guanghua Zhang
* @date 2004-09-21
* @param T_U32 pin: pin number
* @return T_VOID
* @retval
*/
static T_VOID set_i2c_pin(T_U32 pin)
{
*(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_OUT) |= pin;
}
/**
* @brief clear I2C input function
* set I2C input: 0
* @author Guanghua Zhang
* @date 2004-09-20
* @param T_U32 pin: pin number
* @return T_VOID
* @retval
*/
static T_VOID clr_i2c_pin(T_U32 pin)
{
*(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_OUT) &= (~pin);
}
/**
* @brief get I2C output function
* get I2C output data
* @author Guanghua Zhang
* @date 2004-09-20
* @param T_U32 pin: pin number
* @return T_U8: get I2C output data
* @retval
*/
static T_U8 get_i2c_pin(T_U32 pin)
{
T_U8 ret;
T_U32 value;
value = *(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_IN);
if ((value & pin) == 0)
ret = 0;
else
ret = 1;
return ret;
}
/**
* @brief I2C interface start function
* start I2C transmit
* @author Junhua Zhao
* @date 2004-04-05
* @param T_VOID
* @return T_VOID
* @retval
*/
static T_VOID i2c_begin(T_VOID)
{
i2c_delay(I2C_DELAY_UNIT << 2);
set_i2c_pin(SDA);
i2c_delay(I2C_DELAY_UNIT << 2);
set_i2c_pin(SCL);
i2c_delay(I2C_DELAY_UNIT << 3);
clr_i2c_pin(SDA);
i2c_delay(I2C_DELAY_UNIT << 3);
clr_i2c_pin(SCL);
i2c_delay(I2C_DELAY_UNIT << 4);
}
/**
* @brief I2C interface stop function
* stop I2C transmit
* @author Junhua Zhao
* @date 2004-05-04
* @param T_VOID
* @return T_VOID
* @retval
*/
static T_VOID i2c_end(T_VOID)
{
i2c_delay(I2C_DELAY_UNIT << 2);
clr_i2c_pin(SDA);
i2c_delay(I2C_DELAY_UNIT << 2);
set_i2c_pin(SCL);
i2c_delay(I2C_DELAY_UNIT << 3);
set_i2c_pin(SDA);
i2c_delay(I2C_DELAY_UNIT << 4);
}
/**
* @brief I2C interface send asknowlege function
* send a asknowlege to I2C bus
* @author Junhua Zhao
* @date 2005-04-05
* @param T_U8
* 0:send bit 0
* not 0:send bit 1
* @return T_VOID
* @retval
*/
static T_VOID i2c_write_ask(T_U8 flag)
{
if(flag)
set_i2c_pin(SDA);
else
clr_i2c_pin(SDA);
i2c_delay(I2C_DELAY_UNIT << 2);
set_i2c_pin(SCL);
i2c_delay(I2C_DELAY_UNIT << 3);
clr_i2c_pin(SCL);
i2c_delay(I2C_DELAY_UNIT << 2);
set_i2c_pin(SDA);
i2c_delay(I2C_DELAY_UNIT << 2);
}
/**
* @brief I2C receive anknowlege
* receive anknowlege from i2c bus
* @author Junhua Zhao
* @date 2005-04-05
* @param T_VOID
* @return T_BOOL: return received anknowlege bit
* @retval AK_FALSE: 0
* @retval AK_TRUE: 1
*/
static T_BOOL i2c_read_ack(T_VOID)
{
T_BOOL ret;
*(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_DIR) &= (~SDA);
i2c_delay(I2C_DELAY_UNIT << 3);
set_i2c_pin(SCL);
i2c_delay(I2C_DELAY_UNIT << 2);
if (!get_i2c_pin(SDA))
{
ret = AK_TRUE;
}
else
{
ret = AK_FALSE;
}
i2c_delay(I2C_DELAY_UNIT << 2);
clr_i2c_pin(SCL);
i2c_delay(I2C_DELAY_UNIT << 2);
*(volatile T_U32 *)(BASE_GPIO_TIMER+GPIO_DIR) |= SDA;
i2c_delay(I2C_DELAY_UNIT << 2);
return ret;
}
T_VOID I2C_Test( T_VOID )
{
T_U16 i;
i2c_init();
while( 1 )
{
if ( i % 2 == 0 )
{
set_i2c_pin( SDA );
//if ( i %10 == 0 )
//set_i2c_pin( SDA );
}
else
{
// clr_i2c_pin( SDA );
//if ( i %5 == 0 )
clr_i2c_pin( SDA );
}
i++;
}
}
#endif
/* end of file */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -