mini2440 IIC实验(读写EEPROM)

来源:互联网 发布:mysql数据库名称查询 编辑:程序博客网 时间:2024/06/04 19:26

    下面,我就说说那个让我做了5天的实验吧。代码其实还有点问题,有待以后改进。

      实验目的:通过IIC总线读写EEPROM (AT24C08A)

      相关的内容见赵老师的博客:http://blog.csdn.net/zhaocj/article/details/5477152

      赵老师的程序是读写at24c02a,而我的板子上的是AT24C08A,但是原理是一样的。

      想要读写某一芯片就必须好好看看它的芯片手册,否则可能会出现很奇怪的问题

      我从芯片手册上得知AT24C08A的容量为8Kbits,换算成字节就是1KB,不过开发板的使用手册上说AT24C08A有256B容量。这是为什么呢?

      大家看看AT24C08A的芯片手册,原文有这么一句话:

      The AT24C08A only uses the A2 input for hardwire addressing and a total of two 8K devices maybe addressed on a single bus system. The A0 and A1 pins are no connects.

      这段话我翻译了一下,如下:

      AT24C08A只使用A2引脚用来硬接线寻址,在同一个总线上总共有两个8K的AT24C08A能被寻址。A0,A1引脚悬空。

      也就是说,当总线上有两片AT24C08A时,使用A2来决定选中哪一片。比如:A2=0时选中第一片,A2=1时选中第二片。

      但是,mini2440开发板上是这样连接AT24C08A芯片的:


      从图中可以看到:A2 A1 A0全部接地。

AT24C08A芯片手册中还有这么一句:

      The 8K is internally organized with 4 blocks of 256 pages of 4-bytes each.Random word addressing requires a 10 bit data word address.

大体意思是:AT24C08A分成4块,一块64页,一共256页,每一页4B。(所以一块的大小是256B),随机寻址需要10位的地址。

      其中我觉得A1 A0使用来选择哪一块的。但是mini2440开发板将A1 A0接地,所以只能寻址第一块的空间,所以才说AT24C08A容量有256B(其余的256B*3的空间没有使用)正确的解释看下面:

      好了,我在吧我修改的代码附上,其中我有疑问的用问号标注,希望有朋友能和我共同探讨。


===========2013-5-15==========

今天有看了看芯片手册,结合韦老师的视频,发现原来的理解稍微有点偏差:

芯片手册有如下说明:The 8K EEPROM only uses the A2 device address bit with the next 2 bits being for memory page addressing. The A2 bit must compare to its corresponding hard-wired input pin.The A1 and A0 pins are no connect.学过IIC的童鞋知道,通信开始的时候要发一个开始信号,接着发从设备的地址,对于at24c08a来说,地址为 1 0 1 0 A2 P1 P0 r/w 这8位。其中P1 P0 用来选择4页中的一页(块)。所以即使A2 A1 A0都接地,但是,在发送从设备地址的时候,可以指定读哪一个页,就可以访问到全部1KB空间了。



//AT24C08A页写(最多写16个字节)//输入参数依次为设备内存地址、IIC数据缓存数组和要写入的数据个数void wr24c08a(unsigned char page, unsigned char wordAddr,unsigned char *buffer,int sizeofdate ){int i;flag =1;        //应答标志设置为1,表示没有进入IIC中断IICDS = page;//IICCON &= ~0x10; //清中断标志IICSTAT = 0xf0;//主设备发送模式uart0_puts("\n\rwait for ack after start signal........\n\r");while(flag == 1){//等待从设备应答,                               uart0_puts("flag=1\n\r"); //如果将这句话注释条,程序就不能继续运行了。这是为什么????下面也是这样。delay(10);//一旦进入IIC中断,设置flag=0之后,即可跳出该死循环}uart0_puts("receive the ack from the device\n\r");uart0_puts("write device memory address\n\r");flag = 1;IICDS = wordAddr;//写入从设备内存地址IICCON &= ~0x10;//恢复IIC传送while(flag){uart0_puts("flag=1\n\r");delay(10);}uart0_puts("get ack\n\r");//连续写入数据uart0_puts("write data to EEPROM\n\r");for(i=0;i<sizeofdate;i++){      flag = 1;      IICDS = *(buffer+i);      IICCON &= ~0x10;      while(flag){uart0_puts("flag=1\n\r");delay(10);}}uart0_puts("finish writing\n\r");IICSTAT = 0xd0;         //发出stop命令,结束该次通讯IICCON = 0xaf;          //为下次IIC通讯做准备delay(100);                   //等待} //AT24C08A的序列读,sizeofdate最大为256//输入参数依次为设备内存地址、IIC数据缓存数组和要读取的数据个数void rd24c08a(unsigned char page, unsigned char wordAddr,unsigned char *buffer,int sizeofdate){int i;      unsigned char temp;uart0_puts("\n\rDUMMY WIRTE\n\r");      flag =1;      IICDS = page;//      IICCON &= ~0x10; //清中断标志      IICSTAT = 0xf0; //主设备发送模式uart0_puts("send device address\n\r");      while(flag)delay(100);uart0_puts("get ack\n\r");uart0_puts("send word address \n\r");      flag = 1;      IICDS = wordAddr;      IICCON &= ~0x10;      while(flag){uart0_puts("flag=1\n\r");delay(10);}uart0_puts("get ack\n\r");uart0_puts("DUMMY WRITE FINISH.\n\r");uart0_puts("host receive mode,send start signal again\n\r");      flag = 1;      IICDS =  page;//      IICCON &= ~0x10;         IICSTAT = 0xb0; //主设备接收模式     while(flag){uart0_puts("flag=1\n\r");delay(10);}uart0_puts("get ack\n\r");  uart0_puts("first data is device address\n\r");      flag = 1;      temp = IICDS;                    //读取从设备地址      IICCON &= ~0x10;      while(flag){uart0_puts("flag=1\n\r");delay(10);}uart0_puts("get ack,decice address is \n\r" );//连续读uart0_puts("read data\n");      for(i=0;i<sizeofdate;i++){flag = 1;if(i==sizeofdate-1) //如果是最后一个数据IICCON &= ~0x80; //不再响应*(buffer+i) = IICDS;IICCON &= ~0x10;while(flag){uart0_puts("flag=1\n\r");      delay(10);}        }uart0_puts("finish reading\n\r");      IICSTAT = 0x90;         //结束该次通讯      IICCON = 0xaf;          //      delay(100);                         }


注意:如果要进行连续的读写操作,那么两次操作之间要加上一个延时,如delay(3000);