GPIO模拟I2C是嵌入式中较为常用的一种应用。各个地方有各种不同的做法,按照我自己的个人理解,最好是把I2C的各种状态分割开来,比如起始条件终止条件,读数据和写数据,然后根据具体的使用场合组合起来。
这里需要注意两点:一是SCL的波形并不规律,不能将它理解为方波,它本身只是一段段独立的波形。二是每段操作时,之前和之后的SCL和SDA波形是可以忽略的;通常情况下I2C开始之前和I2C结束之后,两者都是有上拉的高电平,而在正常工作时两者不受控制的情况下都是默认低电平。三是I2C是要默认外部上拉的,但是不能有内部上拉也就是必须内部下拉,否则会出现I2C传输时的错误。
-
(1)基础宏定义
-
-
#define GPIO_SCL S3C2410_GPF3
-
#define GPIO_SDA S3C2410_GPF0
-
#define GPIO_SDA_OUTP S3C2410_GPF0_OUTP //设定SDA输出
-
#define GPIO_SDA_INP S3C2410_GPF0_INP //设定SDA输入
-
#define GPIO_SCL_OUTP S3C2410_GPF3_OUTP //设定SCL输出
-
-
void I2C_SCL_OUTP( void )
-
{
-
s3c2410_gpio_cfgpin(GPIO_SCL,GPIO_SCL_OUTP);
-
}
-
-
void I2C_SCL_Output(u8 value)
-
{
-
if(value)
-
{
-
s3c2410_gpio_setpin(GPIO_SCL,value);
-
}
-
else
-
{
-
s3c2410_gpio_setpin(GPIO_SCL,value );
-
}
-
}
-
-
-
-
void I2C_SDA_Mode(u8 v_mode) //SDA输出方向
-
{
-
if(v_mode)
-
{
-
s3c2410_gpio_cfgpin(GPIO_SDA, GPIO_SDA_OUTP);
-
}
-
else
-
{
-
s3c2410_gpio_cfgpin(GPIO_SDA, GPIO_SDA_INP);
-
}
-
}
-
-
void I2C_SDA_Output(u8 value)
-
{
-
if(value)
-
{
-
s3c2410_gpio_setpin(GPIO_SDA,value);
-
}
-
else
-
{
-
s3c2410_gpio_setpin(GPIO_SDA,value );
-
}
-
}
-
-
u8 I2C_SDA_Read(void) //SDA读数据
-
{
-
return s3c2410_gpio_getpin(GPIO_SDA);
-
}
-
-
(2)基础段
-
-
void I2C_Init(void)
-
{
-
I2C_SDA_Output(1);
-
I2C_SCL_Output(1); //默认拉高
-
}
-
-
void I2C_Wait(void)
-
{
-
u16 i;
-
for(i=0;i<200;i++);
-
}
-
-
void I2C_Start(void)
-
{
-
I2C_SDA_Output(1);
-
I2C_SCL_Output(1);
-
I2C_Wait();
-
I2C_SDA_Output(0);
-
I2C_Wait();
-
I2C_SCL_Output(0);
-
}
-
void I2C_Stop(void)
-
{
-
I2C_SDA_Output(0);
-
I2C_Wait();
-
I2C_SCL_Output(1);
-
I2C_Wait();
-
I2C_SDA_Output(1);
-
}
-
-
(3)读写单个字节的段
-
-
u8 I2C_Send_Byte(u8 bytedata)
-
{
-
u8 i,ack;
-
I2C_SDA_Mode(1); //SDA输出
-
I2C_SCL_OUTP();
-
for (i = 0; i < 8; i++)
-
{
-
if (bytedata & 0x80)
-
{
-
I2C_SDA_Output(1);
-
}
-
else
-
{
-
I2C_SDA_Output(0);
-
}
-
bytedata <<= 1;
-
-
I2C_SCL_Output(1);
-
udelay(3);
-
I2C_SCL_Output(0);
-
udelay(1);
-
}
-
-
I2C_SDA_Output(1); //release
-
udelay(3);
-
-
I2C_SDA_Mode(0); //设定SDA输入
-
I2C_SCL_Output(1);
-
udelay(3);
-
ack = I2C_SDA_Read(); //读应答
-
I2C_SDA_Mode(1);
-
I2C_SCL_Output(0);
-
udelay(3);
-
-
return ack;
-
}
-
-
u8 I2C_Receive_Byte(void)
-
{
-
u8 i;
-
u8 bytedata = 0x00;
-
u8 temp;
-
-
I2C_SDA_Mode(0);
-
for ( i = 0; i < 8; i++)
-
{
-
I2C_SCL_Output(1);
-
udelay(3);
-
-
-
-
bytedata <<= 1;
-
temp = I2C_SDA_Read();
-
printk("reda SDA'value is:%d/n",temp);
-
-
if (temp)
-
bytedata |= 0x01;
-
printk(" bytedata is:%x/n",bytedata);
-
I2C_SCL_Output(0);
-
udelay(1);
-
}
-
I2C_SDA_Mode(1);
-
return bytedata;
-
}
-
-
(4)读写单个字节的I2C应用函数
-
-
u8 I2C_Byte_Write(u8 device_ID,u8 address,u8 bytedata)
-
{
-
u8 ack;
-
printk("device_ID is:%x/n",device_ID);
-
printk("address is:%x/n",address);
-
printk("date is:%x/n",bytedata);
-
I2C_Start();
-
ack=I2C_Send_Byte(device_ID);
-
printk("ack is:%d/n",ack);
-
if(ack)
-
-
I2C_Stop();
-
I2C_Send_Byte(address);
-
I2C_Send_Byte(bytedata);
-
I2C_Stop();
-
I2C_Wait();
-
return 0;
-
}
-
-
u8 I2C_Byte_Read(u8 device_ID,u8 address)
-
{
-
u8 bytedata;
-
-
I2C_Start();
-
I2C_Send_Byte(device_ID);
-
I2C_Send_Byte(address);
-
I2C_Start();
-
I2C_Send_Byte(device_ID+1);
-
bytedata = I2C_Receive_Byte(); //读单个字节,不需要再发应答
-
I2C_Stop();
-
return bytedata;
-
}
-
-
(5)类似可以完成读写多个字节的函数,暂不补充。
第二种方式也可以用
-
#ifdef I2C_USE_GPIO
-
#define GPIO_I2C_DEBUG
-
-
#define GPIO_I2C_SDA_PIN GPIO_I2C1_SCA_PIN
-
#define GPIO_I2C_SCA_PIN GPIO_I2C1_SDA_PIN
-
#define GPIO_SDA_OUTP mt_set_gpio_dir(GPIO_I2C_SDA_PIN,GPIO_DIR_OUT) //设定SDA输出
-
#define GPIO_SDA_INP mt_set_gpio_dir(GPIO_I2C_SDA_PIN,GPIO_DIR_IN) //设定SDA输入
-
#define GPIO_SCL_OUTP mt_set_gpio_dir(GPIO_I2C_SCA_PIN,GPIO_DIR_OUT) //设定SCL输出
-
-
#define I2C_SDA_Output(value) mt_set_gpio_out(GPIO_I2C_SDA_PIN,value)
-
#define I2C_SCL_Output(value) mt_set_gpio_out(GPIO_I2C_SCA_PIN,value)
-
-
#define DELAY_TIME 0xc0
-
-
u8 I2C_SDA_Read(void) //SDA读数据
-
{
-
return mt_get_gpio_in(GPIO_I2C_SDA_PIN);
-
}
-
-
-
void I2C_Init(void)
-
{
-
mt_set_gpio_mode(GPIO_I2C_SDA_PIN,GPIO_MODE_00);
-
mt_set_gpio_mode(GPIO_I2C_SCA_PIN,GPIO_MODE_00);
-
-
GPIO_SDA_OUTP;
-
GPIO_SCL_OUTP;
-
-
I2C_SDA_Output(1);
-
I2C_SCL_Output(1); //默认拉高
-
}
-
-
#define I2C_START_TRANSMISSION
-
{
-
volatile u8 idx;
-
GPIO_SCL_OUTP;
-
GPIO_SDA_OUTP;
-
I2C_SDA_Output(1);
-
for (idx = 0; idx < DELAY_TIME; idx++);
-
I2C_SCL_Output(1);
-
for (idx = 0; idx < DELAY_TIME; idx++);
-
I2C_SDA_Output(0);
-
for (idx = 0; idx < DELAY_TIME; idx++);
-
I2C_SCL_Output(0);
-
}
-
-
#define I2C_STOP_TRANSMISSION
-
{
-
volatile u8 idx;
-
GPIO_SCL_OUTP;
-
GPIO_SDA_OUTP;
-
I2C_SCL_Output(0);
-
I2C_SDA_Output(0);
-
for (idx = 0; idx < DELAY_TIME; idx++);
-
I2C_SCL_Output(1);
-
for (idx = 0; idx < DELAY_TIME; idx++);
-
I2C_SDA_Output(1);
-
}
-
-
static kal_uint8 I2C_Send_Byte(kal_uint8 send_byte)
-
{
-
volatile signed char i = 0;
-
volatile kal_uint16 j = 0;
-
kal_uint8 ack = 0;
-
-
for (i = 7; i >= 0; i--)
-
{
-
if (send_byte&(1 << i))
-
{
-
I2C_SDA_Output(1);
-
}
-
else
-
{
-
I2C_SDA_Output(0);
-
}
-
for (j = 0; j < DELAY_TIME; j++);
-
I2C_SCL_Output(1);
-
for (j = 0; j < DELAY_TIME; j++);
-
GPIO_SDA_OUTP; /* only for delay */
-
for (j = 0; j < DELAY_TIME; j++);
-
I2C_SCL_Output(0);
-
for (j = 0; j < DELAY_TIME; j++);
-
}
-
GPIO_SDA_INP;
-
for (j = 0; j < DELAY_TIME; j++);
-
I2C_SCL_Output(1);
-
for (j = 0; j < DELAY_TIME; j++);
-
ack = I2C_SDA_Read();
-
for (j = 0; j < DELAY_TIME; j++);
-
I2C_SCL_Output(0);
-
for (j = 0; j < DELAY_TIME; j++);
-
GPIO_SDA_OUTP;
-
-
return ack;
-
}
-
-
-
static kal_uint8 I2C_Receive_Byte(void)
-
{
-
volatile signed char i = 0;
-
volatile kal_uint16 j = 0;
-
kal_uint8 get_byte = 0;
-
-
GPIO_SDA_INP;
-
-
for (j = 0; j < DELAY_TIME; j++);
-
-
for (i = 7; i >= 0; i--) { // data bit 7~0
-
I2C_SCL_Output(1);
-
for (j = 0; j < DELAY_TIME; j++);
-
if (I2C_SDA_Read()) {
-
get_byte |= (1 << i);
-
}
-
for (j = 0; j < DELAY_TIME; j++);
-
I2C_SCL_Output(0);
-
for (j = 0; j < DELAY_TIME; j++);
-
}
-
-
// don't care bit, 9th bit
-
GPIO_SDA_OUTP;
-
I2C_SDA_Output(1);
-
for (j = 0; j < DELAY_TIME; j++);
-
I2C_SCL_Output(1);
-
for (j = 0; j < DELAY_TIME; j++);
-
I2C_SCL_Output(0);
-
-
return get_byte;
-
}
-
-
-
-
static kal_uint16 I2C_Receive_word(void)
-
{
-
volatile signed char i = 0;
-
volatile kal_uint32 j = 0;
-
kal_uint16 get_byte = 0;
-
-
for (i = 15; i >= 8; i--)
-
{
-
GPIO_SDA_INP;
-
for (j = 0; j < DELAY_TIME; j++);
-
I2C_SCL_Output(1);
-
for (j = 0; j < DELAY_TIME; j++);
-
if (I2C_SDA_Read()) get_byte |= (1 << i);
-
for (j = 0; j < DELAY_TIME; j++);
-
I2C_SCL_Output(0);
-
for (j = 0; j < DELAY_TIME; j++);
-
}
-
I2C_SDA_Output(0);
-
GPIO_SDA_OUTP;
-
for (j = 0;j < DELAY_TIME; j++);
-
I2C_SCL_Output(1);
-
for (j = 0;j < DELAY_TIME; j++);
-
GPIO_SDA_OUTP; /* just for delay */
-
for (j = 0;j < DELAY_TIME; j++);
-
I2C_SCL_Output(0);
-
for (j = 0;j < DELAY_TIME; j++);
-
for (; i >= 0; i--)
-
{
-
GPIO_SDA_INP;
-
for (j = 0; j < DELAY_TIME; j++);
-
I2C_SCL_Output(1);
-
for (j = 0; j < DELAY_TIME; j++);
-
if (I2C_SDA_Read()) get_byte |= (1 << i);
-
for (j = 0; j < DELAY_TIME; j++);
-
I2C_SCL_Output(0);
-
for (j = 0; j < DELAY_TIME; j++);
-
}
-
I2C_SDA_Output(1);
-
GPIO_SDA_OUTP;
-
for (j = 0;j < DELAY_TIME; j++);
-
I2C_SCL_Output(1);
-
for (j = 0;j < DELAY_TIME; j++);
-
GPIO_SDA_OUTP; /* just for delay */
-
for (j = 0;j < DELAY_TIME; j++);
-
I2C_SCL_Output(0);
-
for (j = 0;j < DELAY_TIME; j++);
-
-
return get_byte;
-
}
-
-
u8 I2C_Byte_Write(u8 * a_puBuff , u8 len , u8 i2c_addr)
-
{
-
kal_uint8 fail_try_no = 4;
-
volatile signed char i = 0 ;
-
u8 ack_flag = 0;
-
while (--fail_try_no > 0)
-
{
-
ack_flag = 0;
-
I2C_START_TRANSMISSION;
-
if (I2C_Send_Byte(i2c_addr)) continue;
-
for(i = 0 ;i < len;i++){
-
if (I2C_Send_Byte(a_puBuff[i])){
-
ack_flag = 1;
-
break;
-
}
-
}
-
if(ack_flag)
-
continue;
-
break;
-
}
-
I2C_STOP_TRANSMISSION;
-
return 0;
-
}
-
-
u8 I2C_Bytes_Read(u8 *a_puBuff, u8 reglen ,u8 *byteget,u8 bytelen,u8 i2c_addr)
-
{
-
-
kal_uint16 get_byte = 0xFFFF;
-
kal_uint8 fail_try_no = 4;
-
volatile kal_uint32 i = 0;
-
u8 ack_flag = 0;
-
-
while (--fail_try_no > 0)
-
{
-
ack_flag = 0;
-
I2C_START_TRANSMISSION;
-
if (I2C_Send_Byte(i2c_addr)) continue;
-
-
//send reg
-
for(i = 0 ;i < reglen;i++){
-
if (I2C_Send_Byte(a_puBuff[i])){
-
ack_flag = 1;
-
break;
-
}
-
}
-
if(ack_flag)
-
continue;
-
-
I2C_START_TRANSMISSION;
-
if (I2C_Send_Byte(i2c_addr | 1)) continue;
-
-
if(bytelen == 1)
-
byteget[0] = get_byte = I2C_Receive_Byte(); //读单个字节,不需要再发应答
-
else if(bytelen > 1)
-
{
-
get_byte=I2C_Receive_word();
-
byteget[1] = get_byte & 0x00ff;
-
byteget[0] = (get_byte & 0xff00) >> 8;
-
}
-
break;
-
}
-
I2C_STOP_TRANSMISSION;
-
-
printk("----%s---read data %x---n",__func__,get_byte);
-
-
return get_byte;
-
-
}
-
-
int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId)
-
{
-
I2C_Byte_Write(a_pSendData,a_sizeSendData,i2cId);
-
return 0;
-
}
-
-
int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId)
-
{
阅读(810) | 评论(0) | 转发(0) |