微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > I2C总线通信 EEPROM实验中遇到的疑问,请大神解答

I2C总线通信 EEPROM实验中遇到的疑问,请大神解答

时间:10-02 整理:3721RD 点击:
请大神帮忙解答一下疑问,这个问题也困扰我很久了,
在郭天祥的那本书中关于I2C总线  EEPROM的试验中,先往AT24C02芯片中写了一个数据write_byte(0xFE)(为了精简我只把主函数拿上来);
void main()
{
        init();
        start();
        write_byte(0xa0);
        respons();
        write_byte(2);
        respons();
        write_byte(0xFE);
        respons();
        stop();        //这里的停止和下一个启动之间要有一个时间间隔
        delay_0(10);
        start();
        write_byte(0xa0);
        respons();
        write_byte(2);
        respons();
        start();
        write_byte(0xa1);
        respons();
        a=read_byte();
        no_respons();
        stop();
        P1=a;
        delay_0(1);
}
那么问题1:先给从器件AT24C02写一个地址write_byte(2)(如上所示);之后再写数据write_byte(0xFE);那么在用keil调试的时候 如何通过从器件AT24C02的RAM来查看这个数据0xFE是否被准确写入地址为2的存储单元中?
还有问题2:在读取地址为2的存储单元中的数据0XFE时,这8位数据是如何被一位一位地读走的?
以下是读数据函数:
uchar readbyte()
{
      uchar i,k;
      scl=0;
     delay();
     sda=1;
     for(i=0;i<8;i++)
{
     scl=1;
    delay();
    k=(k<<1)|sda;
    scl=0;
    delay();
}
   delay();
   return k;
}
       
特别不能理解k=(k<<1)|sda这一行,sda在这里不过是一根数据线,也不是存储单元,那么在这8次的循环中,又如何能够确定每次scl时钟脉冲产生的时候sda的值呢?如何能确定sda在8次所传出的值是0xFE呢?
以上两个问题 特别是第二个问题已经困扰我很久了,特别希望有大神能帮忙指点迷津! 小弟在此先谢过了

是不是写进去了,只能再读出来看看一不一样。
你这个是i2c,是串行数据总线,当然是一位一位的了。

呵呵,正好在读英文的DATASHEET,帮一下你喽,第一个问题不是问题,因为我也不会,第二个完全是因为郭天祥的程序风格问题所导致的,程序风格不好,他自己明白,你未必会明白,IIC读写是同步串行的,遵循由高到低的顺序,也就是8位数据,先发高位,最后发低位,这样写你就明白了
   scl=0;
     delay();
     sda=1
for(mask = 0x80;mask != 0;mask >>= 1)
{
    delay();
    scl=1;
    delay();
    if(SDA == 0)
{
}
}

我晕还没写完
  if(SDA == 0)
{
    k &= ~mask;
}
else
{
   k |= mask;
}
delay();
SCL = 0;

你好,首先谢谢你的回答,你的写法比较新颖,其实道理是一样的,两种写程序的方法我都能理解,我不明白的是理论上的问题,I2C总线在读数据的时候,是不是因为之前8位数据已经写进去了,而且从搞到低位排好序了,这时在读的时候当时钟脉冲一产生,则最高位上的数据就被传送到数据线SDA上去了?

是不是因为之前8位数据已经写进去了,这句话是对的,肯定已经写进去了,从EEPROM里面读数据嘛,After the microcontroller receives a data word, it responds with an
acknowledge. As long as the EEPROM receives an acknowledge, it will continue to increment
the data word address and serially clock out sequential data words,这个是数据手册的原话,你看看,重点是这句 increment the data word address and serially clock out sequential data words,数据地址增加,串行时钟输出数据,高低位已经排好了?我不知道,但是按数据手册的说法,是按照地址的顺序来读的

哈哈,你把我问住了,我回去查看了数据手册的时序图和相关资料,之前一直没往你这个问题上想,EEPROM写数据和读数据都是以字节为单位的,一个一个字节的写,一个一个字节的读,不是按单个的位进行读写的,是一次整体读写,然后呢,你可能会问这8位数据是怎么进入的,又怎么确保数据传输正确,IIC协议规定,先从这个字节的高位开始读或者是写,也就是说,一个SCL传输一个SDA,8个CYCLE之后,数据就传过去了,,读完了的话,如果就这一个字节,不需要在读了,就发送非应答位1,否则发送应答位0,继续读。

嗯是的,我认为从宏观上讲 的确是按字节 读或者写  从微观角度讲 应该是 在每一次时钟线拉高产生脉冲时就会有一位数据被写进去或者读出来   ,非常感谢你的耐心回答

这里我觉得有点奇怪,如果是按照数据地址增加来读取数据,那岂不是先输出低位数据 再输出高位,而实际情况是先输出高位,再输出地位

看看24C02的数据手册吧,不要被这些所谓的”大神们“牵着鼻子走,你可能刚接触IIC,IIC时序不难,比较绕,看看时序图,数据存储地址也是按字节的,从0X00-0XFF,0XFE只是用了其中一个字节而已,不是读多个字节,所以地址不会加的,

看看24C02的数据手册吧,不要被这些所谓的”大神们“牵着鼻子走,你可能刚接触IIC,IIC时序不难,比较绕,看看时序图,数据存储地址也是按字节的,从0X00-0XFF,0XFE只是用了其中一个字节而已,不是读多个字节,所以地址不会加的,

注意,OXFE是数据,不是存储地址,看数据手册吧,理解的深刻点

哦 好的  我之前理解的是 每一个地址对应一个8位的存储空间 而8位中的每一位也对应一个地址 我还以为你说的按照地址来读是指每一位的地址呢,这样理解的话就变成了从低位到高位读了

其实我上面写的write_byte(2)才是写地址的,0xfe 的确是写的数据,不过顺便问一下,为什么 0xfe只能是数据不能是地址,其地址范围不是0x00-0xff吗

啊呀,看来你绕进去了,0XFE是你要写的数据,我怕你误解成存储地址了,作为地址和数据都可以

哦,不会绕的 ,先写地址再写数据这一点我还是理解得很清楚的

还有一个问题再请教下,就是单片机向AT24C02写一个字节数据后,从器件会产生一个应答信号,如果不应答那么一段时间后就默认应答了,
所以郭天祥对于应答信号有这么一个子函数:
void response()
{
      uchar  i=0;
       scl=1;
       delay();
       while((sda==1)&&(i<255))
         i++;
         scl=0;
         delay();
}
这个子函数不理解while((sda==1)&&(i<255)) i++;这一块,郭天祥讲的其作用是在没有应答信号时延时退出,可我在想当SCL拉高的时候如果没有应答信号,即SDA==1;就算此时加了这个延时退出,可退出后SDA还是1没变,那么单片机还不是得继续等待应答,程序不会往下执行,跟加这个延时退出之前效果没什么分别,好像没有什么作用?或者我直接把while((sda==1)&&(i<255))i++;这一句换成一个延时函数,效果不是一样的吗?

首先你要搞清楚,这个是主机应答还是从机应答?郭天祥如何定义的我不知道,看注释,每个人有每个人的风格,各有利弊,我觉得哪一种风格对初学者有益就应该学哪一种吧,应答信号有从机应答和主机应答,这个你知道吧?应答则为0,非应答则为1,主机也就是单片机往EEPROM里面写数据,EEPROM是从机,如果数据成功写进去了,那么EEPROM要返回一个应答位,这个应答位的检测是定义一个变量,比如K,直接让K = SDA;,EEPROM从机会主动返回的,而不是强制置为1,这个应答位是什么意思呢?就是表示啊,EEPORM是不是正确接收了这个数据,比如我借给你100块钱,我转你账号里了,银行显示转账成功,这个就是应答信号,写数据的时候永远是主机发出,从机应答。
然后,再来看读数据,单片机依然是主机,EEPROM依然是从机,这个时候,如果是读一个字节,那么读完了的话,单片机直接给EEPROM一个非应答位1,告诉EEPROM,我不要数据了,不要给我了,结束通信,如果是读多个字节的话,那么,单片机要告诉EEPROM,嗯,讨厌,人家还要嘛,然后继续读下去,知道不想读了,结束

另外。特别吐槽一下如今的开发板,大部分都可以让你入门,但是,那一层窗户纸,很薄很薄的一层纸,没有人,也不会有人给你捅破,不知道为什么,大家都这样,不管51,AVR,STM32,资料同质化太严重,同质到没有营养了,深入学习的资料几乎没有,综合实践的例子非常缺乏,我也是非常痛苦的走过来的,其实大部分的模块你会用了,只是一个人处于技术模仿阶段,谈不上消化,更谈不上质的进步,唯一的是做了项目之后,回归理论,再去学习,再次消化,个人的看法,希望对你有帮助,如果哪位大神看到这个吐槽,想要骂几句,我只能说,这是我的个人意见。

嗯,你吐槽的问题我也感觉到了,众多广告打到天上去的也只不过是些很表层的东西,想要深入思考,理解和学习难找到相关的依据,有时想不明白时又找不到相关的参考依据时感觉很痛苦,所以只能在网上求助,希望能得到经验丰富网友的帮助,非常感谢你的多次帮助

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top