TQ2440之I2C操作
开启IIC时钟:
CLKCON |= (1<<10)|(1<<13); //开启串口0时钟
中断服务程序:
void IRQ_Handler(void) __irq //irq中断函数 { switch(INTOFFSET) { case 27: irq_IIC();//中断处理程序 break; } }
中断处理函数:
void irq_IIC(void) { unsigned int iicSt,i; SRCPND = BIT_IIC; //Clear pending bit INTPND = BIT_IIC; iicSt = IICSTAT; if(iicSt & 0x8){} //When bus arbitration is failed. if(iicSt & 0x4){} //When a slave address is matched with IICADD if(iicSt & 0x2){} //When a slave address is 0000000b if(iicSt & 0x1){} //When ACK isn't received switch(_iicMode) { case POLLACK: _iicStatus = iicSt; //0xf0 break; case RDDATA: if((_iicDataCount--)==0) { _iicData[_iicPt++] = IICDS; IICSTAT = 0x90; //Stop MasRx condition 1001 0000 IICCON = 0xaf; //Resumes IIC operation. Delay(1); //Wait until stop condtion is in effect. //Too long time... //The pending bit will not be set after issuing stop condition. break; } _iicData[_iicPt++] = IICDS; //The last data has to be read with no ack. if((_iicDataCount)==0) IICCON = 0x2f; //Resumes IIC operation with NOACK. else IICCON = 0xaf; //Resumes IIC operation with ACK break; case WRDATA: if((_iicDataCount--)==0) { IICSTAT = 0xd0; //Stop MasTx condition IICCON = 0xaf; //Resumes IIC operation. 1010 1111 Delay(1); //Wait until stop condtion is in effect. //The pending bit will not be set after issuing stop condition. break; } IICDS = _iicData[_iicPt++]; //_iicData[0] has dummy. 发送接收数据移位寄存器 for(i=0;i<10;i++); //for setup time until rising edge of IICSCL IICCON = 0xaf; //resumes IIC operation. break; case SETRDADDR: // Uart_Printf("[ S%d ]",_iicDataCount); if((_iicDataCount--)==0) break; //IIC operation is stopped because of IICCON[4] IICDS = _iicData[_iicPt++]; for(i=0;i<10;i++); //For setup time until rising edge of IICSCL IICCON = 0xaf; //Resumes IIC operation. break; default: break; } }
写一个字节函数:
void Wr24C080(unsigned char slvAddr,unsigned char addr,unsigned char data) { _iicMode = WRDATA; _iicPt = 0; _iicData[0] = (unsigned char)addr; _iicData[1] = data; _iicDataCount = 2; IICDS = slvAddr; //0xa0 IICSTAT = 0xf0; //MasTx,Start //Clearing the pending bit isn't needed because the pending bit has been cleared. while(_iicDataCount!=-1); _iicMode = POLLACK; while(1) { IICDS = slvAddr; _iicStatus = 0x100; IICSTAT = 0xf0; //MasTx,Start IICCON = 0xaf; //Resumes IIC operation. while(_iicStatus==0x100); if(!(_iicStatus&0x1)) break; //When ACK is received } IICSTAT = 0xd0; //Stop MasTx condition IICCON = 0xaf; //Resumes IIC operation. Delay(1); //Wait until stop condtion is in effect. //Write is completed. }
读一个字节函数:
void Rd24C080(unsigned char slvAddr,unsigned char addr,unsigned char *data) { _iicMode = SETRDADDR; _iicPt = 0; _iicData[0] = (unsigned char)addr; _iicDataCount = 1; IICDS = slvAddr; IICSTAT = 0xf0; //MasTx,Start //Clearing the pending bit isn't needed because the pending bit has been cleared. while(_iicDataCount!=-1); _iicMode = RDDATA; _iicPt = 0; _iicDataCount = 1; IICDS = slvAddr; IICSTAT = 0xb0; //MasRx,Start IICCON = 0xaf; //Resumes IIC operation. while(_iicDataCount!=-1); *data = _iicData[1]; }
IIC测试程序:
void Test_Iic(void) { unsigned int i,j,save_E,save_PE; static unsigned char data[256]; Uart_Printf("\n\rIIC Test(Interrupt) using AT24C02\n\r"); save_E = GPECON; save_PE = GPEUP; GPEUP |= 0xc000; //Pull-up disable GPECON |= 0xa0000000; //GPE15:IICSDA , GPE14:IICSCL //pISR_IIC = (unsigned)IicInt; INTMSK &= ~(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 IICCON = (1<<7) | (0<<6) | (1<<5) | (0xf); IICADD = 0x10; //2440 slave address = [7:1] IICSTAT = 0x10; //IIC bus data output enable(Rx/Tx) IICLC = (1<<2)|(1); // Filter enable, 15 clocks SDA output delay added by junon Uart_Printf("\rWrite test data into AT24C02\n"); for(i=0;i<256;i++) Wr24C080(0xa0,(unsigned char)i,i);//字节写 for(i=0;i<256;i++) data[i] = 0; Uart_Printf("\rRead test data from AT24C02\n"); for(i=0;i<256;i++) Rd24C080(0xa0,(unsigned char)i,&(data[i])); //选择读时序 //Line changed 0 ~ f for(i=0;i<16;i++) { Uart_Printf("\r"); for(j=0;j<16;j++) Uart_Printf("%2x ",data[i*16+j]); Uart_Printf("\n"); } INTMSK |= BIT_IIC; GPEUP = save_PE; GPECON = save_E; }