Linux平台上GPIO模拟I2C
GPIO模拟I2C是嵌入式中较为常用的一种应用。各个地方有各种不同的做法,按照我自己的个人理解,最好是把I2C的各种状态分割开来,比如起始条件终止条件,读数据和写数据,然后根据具体的使用场合组合起来。
这里需要注意两点:一是SCL的波形并不规律,不能将它理解为方波,它本身只是一段段独立的波形。二是每段操作时,之前和之后的SCL和SDA波形是可以不用计较的;通常情况下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);
}