您的位置:首页 > 其它

瑞萨CPU平台的GPIO模拟I2C之一:开始、停止、写数据

2010-10-15 00:07 567 查看
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条件
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: