⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 提供收音模块的操作代码.可以操作各种收音模块
💻 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 + -