主机主动释放I2C_SDA,为读ack做准备。为什么主机要释放SDA线呢?
因为主机和从机将的SDA线连接是通过&,所以从机在操作总线时,主机要释放总线。(从机在什么时候需要操作总线?1.从机应答2.主机读数据(从机写))
如主机不释放总线的话,那么SDA线上可能是0,也可能是1,假设现在SDA线上是0,那么不论从机是想拉高或拉低SDA线,SDA线都只会为0,因为两器件间是线与(&)的关系。所以在从机要操作总线时,主机要将SDA线释放(即拉高),这样从机就可以根据需要来拉高和拉低SDA线
1 void i2cstart()//SCL在高电平期间,SDA由高变低表示起始信号 2 { 3 I2C_SCL = 1; 4 I2C_SDA = 1;//空闲时,scl和sda为1 5 6 I2CDelay();//I2C_SCL延时4.7us,然后拉低I2C_SDA,产生起始信号 7 I2C_SDA = 0; 8 I2CDelay();//I2C_SDA拉低后,要保持4.7us 9 10 I2C_SCL = 0;//拉低I2C_SCL,为下一次做准备 11 } 12 13 void i2cWriteByte(unsigned char dat)//这个函数是紧跟在start函数的,所以I2C_SCL为0,即I2C_SDA允许变化 14 { 15 unsigned char temp; 16 for(temp = 0x80; temp != 0; temp++){//操作dat的高位 17 if((temp & dat) == 0) 18 I2C_SDA = 0; 19 else 20 I2C_SDA = 1; 21 I2CDelay(); //I2C_SCL为低电平期间,I2C_SDA允许变化 22 23 I2C_SCL = 1;//主机将I2C_SCL拉高,并保持4.7us,告诉从机从I2C_SDA上读数据 24 I2CDelay(); 25 26 I2C_SCL = 0;//拉低I2C_SCL,为下一次做准备 27 } 28 } 29 30 unsigned char i2cReadByte()//这个函数紧跟在读应答函数后,所以I2C_SCL为0,即I2C_SDA允许变化 31 { 32 unsigned char dat = 0,temp; 33 I2C_SDA = 1;//主机主动释放I2C_SDA,让从机往SDA线上放数据。为什么要释放呢?如上 34 for(temp = 0x80; temp != 0; temp++){//操作dat的高位 35 I2CDelay(); //i2cRecAck函数将I2C_SCL拉低,这里是保持I2C_SCL为为4.7us,是叫从机往SDA线上放数据 36 I2C_SCL = 1; 37 if(I2C_SDA == 1) 38 dat |=temp; 39 else 40 dat &= ~temp; 41 I2CDelay(); //SCL高电平期间,主机就能将SDA线上的数据放到dat变量中 42 I2C_SCL = 0;//拉低I2C_SCL,为下一次做准备 43 } 44 } 45 46 void sendAck(bit ack)//这个函数紧跟在i2cReadByte函数后,所以I2C_SCL为0,即I2C_SDA允许变化 47 { 48 I2C_SDA = ack;//在SCL低电平期间,SDA允许变化 49 I2CDelay(); 50 51 I2C_SCL = 1;//主机将SCL拉高,并在高电平期间将主机将ack发给从机 52 I2CDelay(); 53 I2C_SCL = 0;//拉低I2C_SCL,为下一次做准备 54 } 55 56 unsigned char i2cRecAck() 57 { 58 unsigned char ack; 59 I2C_SDA = 1;//主机主动释放I2C_SDA,为读ack做准备。为什么要释放呢?等下解答 60 I2CDelay();//这个函数紧跟在write函数,所以最后I2C_SCL = 0;,这个是让I2C_SCL保持4.7us 61 62 I2C_SCL = 1;//拉高I2C_SCL,看SDA线上是高还是低(即是否应答) 63 ack = I2C_SDA; 64 I2CDelay(); 65 66 I2C_SCL = 0;//拉低I2C_SCL,为下一次做准备 67 return ack; 68 } 69 70 void i2cStop()//SCL在高电平期间,SDA有低电平变为高电平为停止信号 71 { 72 I2C_SCL = 0; 73 I2C_SDA = 0; 74 I2CDelay(); 75 76 I2C_SCL = 1;//I2C_SCL拉高4.7us 77 I2CDelay(); 78 I2C_SDA = 1;//再将I2C_SDA拉高,并且保持4.7us 79 I2CDelay(); 80 }
标签:SCL,temp,主机,SDA,iic,I2C,I2CDelay From: https://www.cnblogs.com/zj-studyrecoding/p/17891297.html