17-I2C从机中断模式与IO口模拟I2C主机进行自发自收
按照下载的这个程序测试,发现采用主机模拟方式的iic,从机无法接收;换成了主机硬件方式的iic可以,那位研究过给个解释,我用了两块开发板进行的验证。可以用逻辑分析仪或示波器对比一下波形有何区别
软件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;
}
通过软硬件的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: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();
}
我很想知道,从机是怎么发送出应答信号的? 硬件从机自动发送应答信号,可以初始化设置好,已经验证完毕。
页:
[1]