您的位置:首页 > 其它

IIC&EEPROM

2016-09-17 22:50 253 查看
1.IIC 时序的重要特点是在时钟SCK为高电平期间SDA作出各种变化来表示起始,终止,应答,非应答,发送数据时是在时钟为高电平期间让SDA稳定,读数据是在SCK为高电平期间采样从设备的数据,所以起始,终止,应答,非应答,发送数据都要先操作SDA,再操作SCK,如果先操作SCK,则会导致起始,终止,应答,非应答,发送数有干扰。

以START信号为例:

写成这样是对的

void IIC_START()

{

    SDA = 1;

SCK = 1;

delay_us(1);

SDA = 0;

delay_us(1);

 

SCK = 0;    

}

 

这样是有问题的

void IIC_START()

{

SCK = 1;

    SDA = 1;

delay_us(1);

SDA = 0;

delay_us(1);

 

SCK = 0;    

}

 

 

2.接收数据为读SDA线的数据,不会有这个问题。

 

3.IIC 时序的数据传送从高位开始

 

4.从本质上理解IIC,主机给从机发送数据,从机是在时钟的下降沿采集SDA的数据,所以主机给出的8个时钟是有讲究的,你要给出有8个下降沿的时钟,应当是这样的:

 

 


 

而不是这样的

 


所以代码这样写是对的:

void IIC_SendByte(unsigned char byte)

{

 unsigned char i;

 unsigned char temp;

 temp = byte;

 for(i = 0; i < 8; i++)

 {

    SDA = temp & 0x80;

  SCK = 1;

  delay_us(1);

  SCK = 0;

  delay_us(1);

  temp <<= 1;

 }

}

这样写会少了一个下降沿,丢掉一个数据位

void IIC_SendByte(unsigned char byte)

{

 unsigned char i;

 unsigned char temp;

 temp = byte;

 for(i = 0; i < 8; i++)

 {

  SCK = 0;

  delay_us(1);

    SDA = temp & 0x80;

  SCK = 1;

  delay_us(1);

  temp <<= 1;

 }

}

 

 

 

 

5.主机从从机读取数据,本质上是从机检测主机发出的时钟信号有8个上升沿

 


所以你的读数据代码一定要写出有8个上升沿

unsigned char IIC_ReceiveByte()

{

unsigned char temp = 0;

unsigned char i;

 

SDA = 1;              

for(i = 0; i < 8; i++)

{

SCK = 0;

delay_us(1);

SCK = 1;

temp <<= 1;

if(SDA)  temp = temp + 1;

delay_us(1);

}

 

SCK = 0;

return temp;

}

仔细体会其中奥妙,同样是8个时钟,发送接收数据对于时钟有不同的要求 

 

6.很多人会遇到这样一个现象:连续从EEPROM读取数据,第一个读出来的是对的,往后读出来的都是0,原因是当读取第一个字节时,主机给从机的应答信号将SDA拉低,即SDA线被钳住,从从机读取数据时,SDA给出的高电平无法将SDA线拉高,导致读出来的数据都为0,所以在读取一个新的字节时,一定要将SDA拉高,才可以正常接收EEPROM的数据。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: