guochl 发表于 2025-11-4 11:09:39

17-I2C从机中断模式与IO口模拟I2C主机进行自发自收

按照下载的这个程序测试,发现采用主机模拟方式的iic,从机无法接收;换成了主机硬件方式的iic可以,那位研究过给个解释,我用了两块开发板进行的验证。

DebugLab 发表于 2025-11-4 12:31:04

可以用逻辑分析仪或示波器对比一下波形有何区别
软件I2C程序:
void        I2C_Delay(void)
{
        u16        dly;
        dly = 8;                //取1对应SCL H为0.5us,L为1.5us,读写仍正常.为了可靠,取8
        while(--dly)        ;
}

void I2C_Start(void)               //start the I2C, SDA High-to-low when SCL is high
{
        P_I2C_SDA = 1;        //SDA = 1;
        I2C_Delay();
        P_I2C_SCL = 1;        //SCL = 1;
        I2C_Delay();
        I2C_Delay();
        I2C_Delay();
        I2C_Delay();
        P_I2C_SDA = 0;        //SDA = 0;
        I2C_Delay();
        I2C_Delay();
        I2C_Delay();
        P_I2C_SCL = 0;        //SCL = 0;
        I2C_Delay();
}


void I2C_Stop(void)                                        //STOP the I2C, SDA Low-to-high when SCL is high
{
        P_I2C_SCL = 0;        //SCL = 0;
        I2C_Delay();
        P_I2C_SDA = 0;        //SDA = 0;
        I2C_Delay();
        P_I2C_SCL = 1;        //SCL = 1;
        I2C_Delay();
        I2C_Delay();
        I2C_Delay();
        P_I2C_SDA = 1;        //SDA = 1;
        I2C_Delay();
}

u8 I2C_Check_ACK(void)         //Check ACK, If status=0: right, if status=1:error
{
        u8        status;
        P_I2C_SDA = 1;        //SDA = 1;
        I2C_Delay();
        P_I2C_SCL = 1;        //SCL = 1;
        I2C_Delay();
        status = 0;
        if(P_I2C_SDA)
                status = 1;
        P_I2C_SCL = 0;        //SCL = 0;
        I2C_Delay();
        return        status;
}

guochl 发表于 2025-11-5 13:29:59

通过软硬件的iic程序比较,软件是有检测从机应答信号的,但是硬件虽然也检测,但是忽略了从机的应答信号,这是主机软硬iic程序的不同点。
主机软件IIC
//========================================================================
// 函数: void SI2C_WriteNbyte(u8 dev_addr, u8 mem_addr, u8 *p, u8 number)
// 描述: I2C写入数据函数.
// 参数: dev_addr: 设备地址, mem_addr: 存储地址, *p写入数据存储位置, number写入数据个数.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void SI2C_WriteNbyte(u8 dev_addr, u8 mem_addr, u8 *p, u8 number)/*DeviceAddress,WordAddress,First Data Address,Byte lenth*/
{
        I2C_Start();
        I2C_WriteAbyte(dev_addr);
        I2C_Check_ACK();
        if(!F0)                                           //F0=0,right, F0=1,error
        {
                I2C_WriteAbyte(mem_addr);
                I2C_Check_ACK();
                if(!F0)
                {
                        do
                        {
                                I2C_WriteAbyte(*p); p++;
                                I2C_Check_ACK();
                                if(F0)break;
                        }
                        while(--number);
                }
        }
        I2C_Stop();
}

主机硬件iic
//========================================================================
// 函数: void I2C_WriteNbyte(u8 dev_addr, u8 mem_addr, u8 *p, u8 number)
// 描述: I2C写入数据函数.
// 参数: dev_addr: 设备地址, mem_addr: 存储地址, *p写入数据存储位置, number写入数据个数.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void I2C_WriteNbyte(u8 dev_addr, u8 mem_addr, u8 *p, u8 number)/*DeviceAddress,WordAddress,First Data Address,Byte lenth   */
{
        Start();                              //发送起始命令
        SendData(dev_addr);                     //发送设备地址+写命令
        RecvACK();
        SendData(mem_addr);                     //发送存储地址
        RecvACK();
        do
        {
                SendData(*p++);
                RecvACK();
        }
        while(--number);
        Stop();                                 //发送停止命令
}

差异点在,硬件iic虽然检测从机应答信号,但是是忽略的,软件iic检测从机应答信号,必须有才能下一步。

guochl 发表于 2025-11-5 13:37:42

guochl 发表于 2025-11-5 13:29
通过软硬件的iic程序比较,软件是有检测从机应答信号的,但是硬件虽然也检测,但是忽略了从机的应答信号, ...

主机软件iic检测应答信号:
void I2C_Check_ACK(void)   //Check ACK, If F0=0, then right, if F0=1, then error
{
        SDA = 1;
        I2C_Delay();
        SCL = 1;
        I2C_Delay();
        F0= SDA;
        SCL = 0;
        I2C_Delay();
}
其中的F0就是从机应答信号的标识;

以下是硬件iic的ack检测信号程序,只接受不处理
//========================================================================
// 函数: void RecvACK (void)
// 描述: I2C获取ACK函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void RecvACK()
{
        I2CMSCR = 0x03;                         //发送读ACK命令
        Wait();
}

我很想知道,从机是怎么发送出应答信号的?

guochl 发表于 2025-11-12 17:38:13

硬件从机自动发送应答信号,可以初始化设置好,已经验证完毕。
页: [1]
查看完整版本: 17-I2C从机中断模式与IO口模拟I2C主机进行自发自收