本帖最后由 chen~chen 于 2018-8-30 15:48 编辑
场景:stm32用I2C对一外设模块通信,外设模块要求:1)通信速度最大100Kbps,2)外设工作于slaver模式,IIC从机地址0x30.
程序运行正常,通信正常,但是在用示波器查I2C的SCL,SDA线的波形是发现在读数据时(如图1所示的1是开始读),
外设向单片机通信时的第一个SCL信号应是先低电平4us,再高电平4us,但实际上高电平只有2us,。(波形如图2所示)
u8 IIC_Wait_Ack1(void)//等待应答。
{
u8 ucErrTime=0;
SDA_IN_FMS();
IIC_SDA_FMS=1;delay_us(3);
IIC_SCL_FMS=1;delay_us(3);
while(READ_SDA_FMS)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop1();
return 1;
}
}
IIC_SCL_FMS=0;
return 0;
}
u8 IIC_Read_Byte1(u8 ack)//读操作
{
unsigned char i,receive=0;
SDA_IN_FMS();
for(i=0;i<8;i++ )
{
IIC_SCL_FMS=0;
delay_us(4);
IIC_SCL_FMS=1;
receive<<=1;
if(READ_SDA_FMS)receive++;
delay_us(4);
}
if (!ack)
IIC_NAck1();
else
IIC_Ack1();
return receive;
}
u8 FMS_Read_data(u8 ReadAddr )//读数据
{
u8 temp=0;
IIC_Start1();
IIC_Send_Byte1(0X30); //从机地址写
IIC_Wait_Ack1();
IIC_Send_Byte1(ReadAddr);//寄存器地址
IIC_Wait_Ack1();
IIC_Start1();
IIC_Send_Byte1(0X31); //从机地址读
IIC_Wait_Ack1();
temp=IIC_Read_Byte1(0);
IIC_Stop1();
return temp;
}
当我在 temp=IIC_Read_Byte1(0); 前面加一个延时delay_us(3)时,读的第一个脉冲就基本上完整了。(图三)
我对u8 FMS_Read_data(u8 ReadAddr)程序进行分析,在等待应答时SCL先置高,等待SDA输入低电平,应答成功,则SCL置低电平。而后紧接着就进入IIC_Read_Byte1(0)函数,SCL被置低4us(实际运行时间大于4us),而后置高4us,但是实际上只有2us,而其后的第二个读脉冲的低电平为4.8us与其他的都一样,所以收到影响的只是第一个读脉冲信号。可能是外设模块在反应需要几us的时间,虽然IIC_Read_Byte1(0)在操作,但是信号被无视。等外设模块准备好输出时,IIC_Read_Byte1(0)后面的波形才被正常显示出来,也没有影响到其他波形。这只是我自己的假设,请大佬指点一二,谢谢。
|