GPIO模拟I2C在不同的平台上有不同的做法。以下是我在瑞萨DVP-C3平台上经过验证的代码。此种实现方式,较为晦涩,不是很好理解,特记录如下。用pvSDA2和pvSCL2表示I2C两根线的GPIO方向控制(ON输出,OFF输入),poSCL2和poSDA2表示I2C两根线的GPIO数据控制(ON置高,OFF置低)。
SI dtv_i2c_start( U8 OutputData )
{
U8 RoopCt; //计数器,用来对操作进行一定的循环,不成功就返回失败
DTV_IICBusInitial(); //完成I2C的两个GPIO的功能配置
IntDisableWithPush; //后面类似的此种语句全都是临界区操作
pvSDA2 = OFF;
pvSCL2 = OFF;
IntEnableByPop; //后面类似的此种语句全都是临界区操作
for( RoopCt=0; RoopCt<12; RoopCt++ )
{
pvSDA2 = OFF;
pvSCL2 = OFF; //如果设置I2C两根线为输入方向,则默认置高
if((poSDA2 ==ON) && (poSCL2==ON)) //则默认为高的前提下
{
IntDisableWithPush; //拉 低 SDA
pvSDA2 = ON;
poSDA2 = OFF;
IntEnableByPop;
BusWait( _15us );
IntDisableWithPush; //拉 低SCL
pvSCL2 = ON;
poSCL2 = OFF;
IntEnableByPop;
BusWait( _15us ); //以上行程一个I2C START波形
return (dtv_i2c_data( OutputData )); //在start函数中就默认写一个字节
}
}
return (WRONG); //如果没有写字节成功,就返回失败
}
SI dtv_i2c_data( U8 OutputData ) //写字节要收到应答信号
{
U8 RoopCt; //8位计数器
UI I2cCt; //应答延时时限
for( RoopCt=0; RoopCt<8; RoopCt++ )
{
IntDisableWithPush;
poSCL2 = OFF;
pvSCL2 = ON;
IntEnableByPop; //SCL拉低,只有SCL为低时SDA才能改变
if((OutputData&0x80)!=0)
{
pvSDA2 = OFF; /// 1 //SDA输出高,只要把SDA设置成输入方向,即相当于对外部没有控制,即被拉高
}
else
{
IntDisableWithPush;
poSDA2 = OFF;
pvSDA2 = ON; //"0" //SDA输出高
IntEnableByPop;
}
pvSCL2 = OFF; //保持SCL为高,形成一个周期
BusWait( _15us );
OutputData = OutputData << 1; //从MSB向LSB次序输出
}
IntDisableWithPush;
poSCL2 = OFF;
pvSCL2 = ON;
IntEnableByPop;
pvSCL2 = OFF; //开始一个新周期,配置SCL输入
I2cCt = WAIT_5ms;
BusWait( _15us );
pvSDA2 = OFF; //SDA不控制
do
{
if( poSCL2 == ON ) //因为SCL已释放,该条件一定成立
{
if(poSDA2 ==OFF) //SDA为低,才是应答有效
{
IntDisableWithPush;
poSCL2 = OFF;
pvSCL2 = ON;
IntEnableByPop; //说明应答有效,该周期完毕
return (TRUE); //ack ok 写字节成功
}
break;
}
--I2cCt;
}while(I2cCt!=0); //在规定时间内
pvSCL2 = OFF; //释放SCL
return (WRONG); //写字节失败
}
void dtv_i2c_end(void)
{
IntDisableWithPush;
poSCL2 = OFF;
pvSCL2 = ON;
IntEnableByPop; //SCL拉低
IntDisableWithPush;
poSDA2 = OFF;
pvSDA2 = ON;
IntEnableByPop; //SDA拉低
BusWait( _15us );
pvSCL2 = OFF; //if set as input port ,default high
BusWait( _25us );
pvSDA2 = OFF; //if set as input port ,default high 形成STOP条件
}