IIC(Inter-Integrated Circuit,I2C)總線是一種由PHILIPS公司開發(fā)的兩線式串行總線,用于連接微處理器及其外圍設(shè)備,它的最主要優(yōu)點(diǎn)是簡(jiǎn)單和有效。它只需要數(shù)據(jù)線SDA和時(shí)鐘線SCL,就能夠?qū)崿F(xiàn)CPU與被控IC之間、IC與IC之間進(jìn)行雙向傳送。 s3c2440內(nèi)部有一個(gè)IIC總線接口,因此為我們連接帶有IIC通信模塊的外圍設(shè)備提供了便利。它具有四種操作模式:主設(shè)備發(fā)送模式、主設(shè)備接收模式、從設(shè)備發(fā)送模式和從設(shè)備接收模式。在這里我們只把s3c2440當(dāng)做IIC總線的主設(shè)備來使用,因此只介紹前兩種操作模式。在主設(shè)備發(fā)送模式下,它的工作流程為:首先配置IIC模式,然后把從設(shè)備地址寫入接收發(fā)送數(shù)據(jù)移位寄存器IICDS中,再把0xF0寫入控制狀態(tài)寄存器IICSTAT中,這時(shí)等待從設(shè)備發(fā)送應(yīng)答信號(hào),如果想要繼續(xù)發(fā)送數(shù)據(jù),那么在接收到應(yīng)答信號(hào)后,再把待發(fā)送的數(shù)據(jù)寫入寄存器IICDS中,清除中斷標(biāo)志后,再次等待應(yīng)答信號(hào);如果不想再發(fā)送數(shù)據(jù)了,那么把0x90寫入寄存器IICSTAT中,清除中斷標(biāo)志并等待停止條件后,即完成了一次主設(shè)備的發(fā)送。在主設(shè)備接收模式下,它的工作流程為:首先配置IIC模式,然后把從設(shè)備地址寫入接收發(fā)送數(shù)據(jù)移位寄存器IICDS中,再把0xB0寫入控制狀態(tài)寄存器IICSTAT中,這時(shí)等待從設(shè)備發(fā)送應(yīng)答信號(hào),如果想要接收數(shù)據(jù),那么在應(yīng)答信號(hào)后,讀取寄存器IICDS,清除中斷標(biāo)志;如果不想接收數(shù)據(jù)了,那么就向寄存器IICSTAT寫入0x90,清除中斷標(biāo)志并等待停止條件后,即完成了一次主設(shè)備的接收。在完成上述兩個(gè)模式時(shí),主要用到了控制寄存器IICCON、控制狀態(tài)寄存器IICSTAT和發(fā)送接收數(shù)據(jù)移位寄存器IICDS。由于我們只把s3c2440當(dāng)做主設(shè)備來用,并且系統(tǒng)的IIC總線上只有這么一個(gè)主設(shè)備,因此用來設(shè)置從設(shè)備地址的地址寄存器IICADD,和用于仲裁總線的多主設(shè)備線路控制寄存器IICLC都無需配置。寄存器IICCON的第6位和低4位用于設(shè)置IIC的時(shí)鐘頻率,因?yàn)镮IC的時(shí)鐘線SCL都是由主設(shè)備提供的。s3c2440的IIC時(shí)鐘源為PCLK,當(dāng)系統(tǒng)的PCLK為50MHz,而從設(shè)備最高需要100kHz時(shí),可以將IICCON的第6位置1,IICCON的低4位全為0即可。寄存器IICCON的第7位用于設(shè)置是否發(fā)出應(yīng)答信號(hào),第5位用于是否使能發(fā)送和接收中斷,第4位用于中斷的標(biāo)志,當(dāng)接收或發(fā)送數(shù)據(jù)后一定要對(duì)該位進(jìn)行清零,以清除中斷標(biāo)志。寄存器IICSTAT的高2位用于設(shè)置是哪種操作模式,當(dāng)向第5位寫0或?qū)?時(shí),則表示結(jié)束IIC或開始IIC通訊,第4位用于是否使能接收/發(fā)送數(shù)據(jù)。 #include "2440addr.h" #define U32 unsigned int unsigned char iic_buffer[8]; U32 length; unsigned char add, word; int cmd, flag, count, command; void delay(int a) { int k; for(k=0;k<a;k++) ; } void __irq UART0_ISR(void){ char ch; rSRCPND |= (0x1<<28); rINTPND |= (0x1<<28); rSUBSRCPND |= 0x1<<0; if(rUTRSTAT0 & 0x1){ ch = rURXH0; while(!(rUTRSTAT0&0x4)); rUTXH0 = ch; if(count == 0) command = ch; if(command == 0xa1){ if(count == 1){ add = ch; } else if(count == 2){ word = ch; } else if(count == 3){ length = ch; } else if(count >= 4) { iic_buffer[count-4] = ch; if(count == length+3){ count = -1; cmd = 0x01; } } count++; } else if(command == 0xa2) { if(count == 1) add = ch; else if(count == 2) word = ch; else if(count == 3){ length = ch; count = -1; cmd = 0x02; } count++; } } } void __irq IIC_ISR(void){ rSRCPND |= 0x1<<27; rINTPND |= 0x1<<27; flag = 0; } void wrat24c02(unsigned char add,unsigned char word, U32 length){ int i; flag = 1; rIICDS = 0xa0; //dev add rIICCON &= "(0x1<<4); //清中斷 rIICSTAT = 0xf0; //主發(fā)送模式,寫開始信號(hào)輸出,IIC Rx/Tx使能 //等待ACK,接收器在接受到8位數(shù)據(jù)后,在第9個(gè)時(shí)鐘周期,拉低SDA電平,然后會(huì)產(chǎn)生中斷 while(flag == 1) delay(100); flag = 1; rIICDS = word; //word add 發(fā)送要寫入的數(shù)據(jù)的內(nèi)存其實(shí)地址 rIICCON &= "(0x1<<4); while(flag) delay(100); //注意要有delay for(i = 0; i < length; i++){ flag = 1; rIICDS = iic_buffer[ i]; rIICCON &= "(0x1<<4); while(flag) delay(100); } rIICCON = 0xe0; //IIC應(yīng)答有效,IICCLK=fpclk/512,IIC接受發(fā)送中斷使能位 rIICSTAT = 0xd0; //主發(fā)送模式,rIICCON和rIICSTAT配置好,方便下次使用 } void rdat24c02(unsigned char add, unsigned char word, U32 length){ int i; char temp; flag = 1; rIICDS = add; //dev add rIICCON &= "(0x1<<4); rIICSTAT = 0xf0; while(flag) delay(100); flag = 1; rIICDS = word; //word add rIICCON &= "(0x1<<4); while(flag) delay(100); flag = 1; //這里的IIC的隨機(jī)讀操作,根據(jù)IIC的隨機(jī)讀時(shí)序,先發(fā)啟動(dòng),要讀取的設(shè)備地址和寫的內(nèi)存地址,方向是寫,即0,重啟IIC, //發(fā)要讀取的設(shè)備地址,這次方向是讀,然后接到ACK,從機(jī)向主機(jī)發(fā)data,主機(jī)相應(yīng)ACK,直到最后一個(gè)data,主機(jī)不相應(yīng)ACK, //發(fā)送停止信號(hào) rIICDS = add; //dev add rIICSTAT = 0xb0; //改變方向?yàn)橹鹘邮? rIICCON &= "(0x1<<4); while(flag) delay(100); flag = 1; temp = rIICDS; rIICCON &= "(0x1<<4); while(flag) delay(100); for(i = 0; i < length; i++){ flag = 1; if(i == (length - 1)){ rIICCON &= "(0x1<<7); } iic_buffer[ i] = rIICDS; rIICCON &= "(0x1<<4); while(flag) delay(100); } rIICCON = 0xd0; rIICSTAT = 0x90; delay(200); } int Main(){ int i; count= 0; length = 0; cmd = 0; command = 0; rGPECON = 0xa0000000; //GPE15~14 IICSDA,IICSCL rGPEUP = 0xc000; rIICCON = 0xe0; //IIC應(yīng)答有效,IICCLK=fpclk/512,IIC接受發(fā)送中斷使能位 rIICSTAT = 0x10; //IIC總線有效Rx/Tx rULCON0 = 0x3; rUCON0 = (1<<11)|(1<<2)|(1<<0); rUBRDIV0 = 26; rSRCPND = (0x1<<28)|(0x1<<27); rINTPND = (0x1<<28)|(0x1<<27); rSUBSRCPND = 0x1<<0; rINTMSK &= "((0x1<<28)|(0x1<<27)); rINTSUBMSK &= "(0x1<<0); pISR_UART0 = (U32)UART0_ISR; pISR_IIC = (U32)IIC_ISR; for(i = 0; i < 8; i++){ iic_buffer[ i] = 0xee; } while(1){ switch(cmd){ case 0x01: cmd = 0; wrat24c02(add, word, length); break; case 0x02: cmd = 0; rdat24c02(add, word, length); for(i = 0; i < 8; i++){ while(!(rUTRSTAT0&0x4)); rUTXH0 = iic_buffer[ i]; } break; } } return 0; } 作者:李萬(wàn)鵬 |