1.rIICCON &= ~0x10; 清中断必须要在rIICDS = slvAddr; 和rIICSTAT = 0xf0; // 主设备,启动 之后
2.延时对于写外部的低速设备来说非常重要,比如while(flag)之后一定要加延时,还有在写数据时发现只能写入基数地址的数据,这也是由于延时导致的
3.开始调试的时候系统总是死在read的函数中,后来发现在数据手册的note中说当读取最后一个数据的时候一定不能返回ACK信号,而我却在程序中使用while(flag)来等待ACK引发中断,这不死才怪呢。。。。所以数据手册中的NOTE部分也是特别重要的
4.在真正对AT24C02A进行读取数据时,在发送带有读命令的从设备地址后,AT24C02A会再返回一个从设备地址信息或从设备内存地址信息作为应答,所以一定要把该字节读取后抛弃,因为它不是我们所要读取的信息。
5.下面是核心代码:
- #include "def.h"
- #include "2440addr.h"
- #include "I2C.h"
- #include "uart.h"
- extern void Delay(int time);
- int flag; //用于标识是否收到应答信号,改标识在终端处理程序中被清0
- void Test_Iic(void)
- {
- unsigned int i,j,save_E,save_PE;
- static U8 data[256];
- uart_printf("\nIIC Test(Interrupt) using AT24C02\n");
- save_E = rGPECON;
- save_PE = rGPEUP;
- rGPEUP |= 0xc000; //Pull-up disable
- rGPECON |= 0xa00000; //GPE15:IICSDA , GPE14:IICSCL
- pISR_IIC = (unsigned)IicInt;
- rINTMSK &= ~(BIT_IIC);
- //Enable ACK, Prescaler IICCLK=PCLK/16, Enable interrupt, Transmit clock value Tx clock=IICCLK/16
- // If PCLK 50.7MHz, IICCLK = 3.17MHz, Tx Clock = 0.198MHz
- rIICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);
- rIICADD = 0x10; //2440 slave address = [7:1]
- rIICSTAT = 0x10; //IIC bus data output enable(Rx/Tx)
- rIICLC = (1<<2)|(1); // Filter enable, 15 clocks SDA output delay added by junon
- uart_printf("Write test data into AT24C02\n");
- for(i=0;i<256;i++)
- { Wr24C080(0xa0,(U8)i,i);
- Delay(1); //注意这个延时不能少,否则出现有些数据无法写入的问题
- }
- for(i=0;i<256;i++)
- data[0] = 0;
- uart_printf("Read test data from AT24C02\n");
- for(i=0;i<256;i++)
- Rd24C080(0xa0,(U8)i,&(data[i]));
- for(i=0;i<16;i++)
- {
- for(j=0;j<16;j++)
- uart_printf("%2x ",data[i*16+j]);
- uart_printf("\n");
- }
- rINTMSK |= BIT_IIC;
- rGPEUP = save_PE;
- rGPECON = save_E;
- }
- void Wr24C080(U32 slvAddr, U32 addr, U8 data)
- {
- flag=1; //应答标志
- rIICDS = slvAddr;
- rIICSTAT = 0xf0; // 主设备,启动
- rIICCON &= ~0x10; //清中断标志 ,特别注意这条语句的位置,不能放到上条的前面
- while(flag == 1) //当发送从地址完成之后会收到ACK信号,在中断处理函数中将该标志置为0
- Delay(1);
- flag =1 ; //readly to translate addr
- rIICDS = addr;
- rIICCON &= ~0x10; //清中断标志
- while(flag == 1) //当发送从地址完成之后会收到ACK信号,在中断处理函数中将该标志置为0
- Delay(1);
- flag =1 ; //readly to translate data
- rIICDS = data;
- rIICCON &= ~0x10; //清中断标志
- while(flag == 1) //当发送从地址完成之后会收到ACK信号,在中断处理函数中将该标志置为0
- Delay(1);
- rIICSTAT = 0xd0; //Stop MasTx condition
- rIICCON = 0xaf; //Resumes IIC operation.
- Delay(1);
- }
- void Rd24C080(U32 slvAddr, U32 addr, U8 *data)
- {
- unsigned char temp;
- flag=1; //应答标志
- rIICDS = slvAddr;
- rIICSTAT = 0xf0; // 主设备发送模式用来发送slvAddr和addr,,启动
- rIICCON &= ~0x10; //清中断标志
- while(flag == 1) //当发送从地址完成之后会收到ACK信号,在中断处理函数中将该标志置为0
- Delay(1);
- flag =1 ; //readly to translate addr
- rIICDS = addr;
- rIICCON &= ~0x10; //清中断标志
- while(flag == 1) //当发送从地址完成之后会收到ACK信号,在中断处理函数中将该标志置为0
- Delay(1);
- flag=1;
- rIICDS = slvAddr;
- rIICSTAT = 0xb0; // 主设备接收模式用来接收数据,启动
- rIICCON &= ~0x10; //清中断标志
- while(flag == 1) //当发送从地址完成之后会收到ACK信号,在中断处理函数中将该标志置为0
- Delay(1);
- //注意:读取下面这个字节必须进行,因为在发送带有读命令的从设备地址后,
- //AT24C02A会再返回一个从设备地址信息或从设备内存地址信息作为应答,所以一定要把该字节读取后抛弃,因为它不是我们所要读取的信息;
- flag =1 ; //readly to translate addr
- temp = rIICDS; // 抛弃第一自己
- rIICCON &= ~0x10; //清中断标志
- while(flag)
- Delay(1);
- rIICCON = 0x2f; //Resumes IIC operation with NOACK.
- *data = rIICDS;
- Delay(1);
- rIICSTAT = 0x90; //Stop MasTx condition
- rIICCON = 0xaf; //Resumes IIC operation.
- Delay(1);
- }
- //-------------------------------------------------------------------------
- void __irq IicInt(void)
- {
- rSRCPND = BIT_IIC; //Clear pending bit
- rINTPND = BIT_IIC;
- flag = 0;
- }