您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“arm9 IIC接口有什么用”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“arm9 IIC接口有什么用”吧!
在2440的使用中其iic接口一般用來(lái)讀取外圍芯片的數(shù)據(jù), 這種情況下2440處于主機(jī)模式, 本例用中斷的方式來(lái)講述 主機(jī)發(fā)送/主機(jī)接收 模式.
主機(jī)發(fā)送模式使用流程:
IICCON: 是否返回ack, 總線時(shí)鐘選擇, 中斷標(biāo)志
IICCON[7] 在發(fā)送模式該位沒(méi)有意義, 因?yàn)榘l(fā)送模式下主機(jī)只接收ACK信號(hào), 并不主動(dòng)發(fā)出ACK.
在接收模式中當(dāng)從機(jī)返回了數(shù)據(jù)之后, 如果主機(jī)需要從機(jī)繼續(xù)返回?cái)?shù)據(jù)就必須發(fā)送一個(gè)ACK, 否則數(shù)據(jù)發(fā)送方不會(huì)繼續(xù)發(fā)送數(shù)據(jù).
綜上: 無(wú)論是主/從, 只要接收數(shù)據(jù)的一方想要繼續(xù)通信就必須要發(fā)送一個(gè)ACK信號(hào), 所以ACK信號(hào)絕對(duì)是由接收數(shù)據(jù)的一方來(lái)發(fā)出的.
IICCON[5] 必須為1, 否則IICCON[4]無(wú)法使用
IICCON[4] 0: 無(wú)中斷發(fā)生 1: 有中斷發(fā)生, 這時(shí)總線傳輸中止. 如果要繼續(xù)傳輸則需將該位清0
發(fā)生中斷的條件: 1. 總線仲裁失敗 2. 發(fā)送/接收完一個(gè)字節(jié) 3. 當(dāng)廣播或從地址匹配成功
GPEUP |= 0xc000; // 禁止內(nèi)部上拉 GPECON |= 0xa0000000; // 選擇引腳功能:GPE15:IICSDA, GPE14:IICSCL INTMSK &= ~(BIT_IIC); //清除IIC中斷屏蔽位 /* bit[7] = 1, 使能ACK * bit[6] = 0, IICCLK = PCLK/16 * bit[5] = 1, 使能中斷 * bit[3:0] = 0xf, Tx clock = IICCLK/16 * PCLK = 50MHz, IICCLK = 3.125MHz, Tx Clock = 0.195MHz */ IICCON = (1<<7) | (0<<6) | (1<<5) | (0xf); // 0xaf IICSTAT = 0x10; // IICSTAT[4]:I2C串行輸出使能(Rx/Tx), 這里可以不必配置該寄存器, 因?yàn)檎嬲_始發(fā)送/接收的時(shí)候會(huì)重新配置IICSTAT(見下邊的I2C_Write)
IICADD: 當(dāng)2440作為從機(jī)的時(shí)候, 本身的iic地址可以由該寄存器來(lái)設(shè)置.
IICSTAT : 主從模式選擇, S/P信號(hào)發(fā)送, 標(biāo)記各種狀態(tài)
IICSTAT[7:6] 主從模式選擇
IICSTAT[5] 讀取此位時(shí) 0 : 總線空閑, 1 : 總線忙 ; 寫入0: 發(fā)出 P 信號(hào), 寫入 1: 發(fā)出 S 信號(hào)
IICSTAT[4] 開啟收發(fā)
IICSTAT[3] 總線仲裁成功標(biāo)志位
IICSTAT[2] 當(dāng)2440作為從機(jī)時(shí), 接收到的地址和IICADD匹配則該位置一, 在檢測(cè)到 S/P 信號(hào)時(shí)自動(dòng)清0
IICSTAT[1] 當(dāng)接收到 0x00 地址時(shí)置一, 當(dāng)檢測(cè)到 S/P 信號(hào)時(shí)自動(dòng)清0
IICSTAT[0] 0: 接收到ACK; 1: 沒(méi)有接收到ACK
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *以下為中斷方式操作I2C接口的主要代碼, 從機(jī)芯片為 m41t11* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
在啟動(dòng)文件中設(shè)定好I2C中斷的異常向量, 在ISR中清除異常標(biāo)志
//head.S中設(shè)置異常向量 @ 0x1c: 快中斷模式的向量地址 HandleFIQ: b HandleFIQ //interrupt.c中的ISR, 該ISR總查詢到了IIC中斷, 調(diào)取了IIC異常處理函數(shù) void IRQ_Handle(void) { unsigned long oft = INTOFFSET; //清中斷 if (oft == 4) EINTPEND = 1<<7; //EINT4-7合用IRQ4,注意EINTPEND[3:0]保留未用,向這些位寫入1可能導(dǎo)致未知結(jié)果 SRCPND = 1<<oft; INTPND = INTPND; /* 調(diào)用中斷服務(wù)程序 */ isr_handle_array[oft](); }
以下為IIC的主要操作:
#define WRDATA (1) #define RDDATA (2) typedef struct tI2C { unsigned char *pData; /* 數(shù)據(jù)緩沖區(qū) */ volatile int DataCount; /* 等待傳輸?shù)臄?shù)據(jù)長(zhǎng)度 */ volatile int Status; /* 狀態(tài) */ volatile int Mode; /* 模式:讀/寫 */ volatile int Pt; /* pData中待傳輸數(shù)據(jù)的位置 */ }tS3C24xx_I2C, *ptS3C24xx_I2C; static tS3C24xx_I2C g_tS3C24xx_I2C; // I2C初始化 void i2c_init(void) { GPEUP |= 0xc000; // 禁止內(nèi)部上拉 GPECON |= 0xa0000000; // 選擇引腳功能:GPE15:IICSDA, GPE14:IICSCL INTMSK &= ~(BIT_IIC); //允許IIC中斷 /* bit[7] = 1, 使能ACK * bit[6] = 0, IICCLK = PCLK/16 * bit[5] = 1, 使能中斷 * bit[3:0] = 0xf, Tx clock = IICCLK/16 * PCLK = 50MHz, IICCLK = 3.125MHz, Tx Clock = 0.195MHz */ IICCON = (1<<7) | (0<<6) | (1<<5) | (0xf); // 0xaf IICADD = 0x10; // S3C24xx slave address = [7:1] 這句可以不需要的, 該寄存器只在2440作為從機(jī)才有用 IICSTAT = 0x10; // I2C串行輸出使能(Rx/Tx) 這句也可以不用, 因?yàn)檎嬲龑懙臅r(shí)候又重新配置了IICSTAT } /* * 主機(jī)發(fā)送 * slvAddr : 從機(jī)地址,buf : 數(shù)據(jù)存放的緩沖區(qū),len : 數(shù)據(jù)長(zhǎng)度 */ void i2c_write(unsigned int slvAddr, unsigned char *buf, int len) { g_tS3C24xx_I2C.Mode = WRDATA; // 寫操作 g_tS3C24xx_I2C.Pt = 0; // 索引值初始為0 g_tS3C24xx_I2C.pData = buf; // 保存緩沖區(qū)地址 g_tS3C24xx_I2C.DataCount = len; // 傳輸長(zhǎng)度 IICDS = slvAddr; IICSTAT = 0xf0; // 主機(jī)發(fā)送,啟動(dòng) /* 等待直至數(shù)據(jù)傳輸完畢 */ while (g_tS3C24xx_I2C.DataCount != -1); } // 主機(jī)接收 // slvAddr : 從機(jī)地址,buf : 數(shù)據(jù)存放的緩沖區(qū),len : 數(shù)據(jù)長(zhǎng)度 void i2c_read(unsigned int slvAddr, unsigned char *buf, int len) { g_tS3C24xx_I2C.Mode = RDDATA; // 讀操作 g_tS3C24xx_I2C.Pt = -1; // 索引值初始化為-1,表示第1個(gè)中斷時(shí)不接收數(shù)據(jù)(地址中斷) g_tS3C24xx_I2C.pData = buf; // 保存緩沖區(qū)地址 g_tS3C24xx_I2C.DataCount = len; // 傳輸長(zhǎng)度 IICDS = slvAddr; IICSTAT = 0xb0; // 主機(jī)接收,啟動(dòng) /* 等待直至數(shù)據(jù)傳輸完畢 */ while (g_tS3C24xx_I2C.DataCount != -1); } // I2C中斷服務(wù)程序 // 根據(jù)剩余的數(shù)據(jù)長(zhǎng)度選擇繼續(xù)傳輸或者結(jié)束 void I2CIntHandle(void) { unsigned int iicSt,i; // 清中斷 SRCPND = BIT_IIC; INTPND = BIT_IIC; iicSt = IICSTAT; //先判斷是不是仲裁失敗引起的中斷 if(iicSt & 0x8){ printf("Bus arbitration failed\n\r"); } switch (g_tS3C24xx_I2C.Mode) { case WRDATA: { //檢測(cè)是否數(shù)據(jù)發(fā)送完畢, 若完畢: 發(fā)送P信號(hào), 數(shù)據(jù)長(zhǎng)度=-1 if((g_tS3C24xx_I2C.DataCount--) == 0) { // 下面兩行用來(lái)恢復(fù)I2C操作,發(fā)出P信號(hào) IICSTAT = 0xd0; IICCON = 0xaf; Delay(10000); // 等待一段時(shí)間以便P信號(hào)已經(jīng)發(fā)出 break; //注意這里的break, 發(fā)送P信號(hào)完畢直接返回. } //若數(shù)據(jù)未發(fā)送完畢直接發(fā)送, 緩沖區(qū)索引值++ IICDS = g_tS3C24xx_I2C.pData[g_tS3C24xx_I2C.Pt++]; // 將數(shù)據(jù)寫入IICDS后,需要一段時(shí)間才能出現(xiàn)在SDA線上 for (i = 0; i < 10; i++); IICCON = 0xaf; // 恢復(fù)I2C傳輸 break; } case RDDATA: { // 這次中斷是發(fā)送I2C設(shè)備地址后發(fā)生的,沒(méi)有數(shù)據(jù), 第一次發(fā)送完地址之后(發(fā)送完一個(gè)字節(jié)會(huì)產(chǎn)生中斷)產(chǎn)生的中斷, 接收數(shù)據(jù)之后2440是需要發(fā)出ACK信號(hào)的 if (g_tS3C24xx_I2C.Pt == -1) { // 只接收一個(gè)數(shù)據(jù)時(shí),不要發(fā)出ACK信號(hào) g_tS3C24xx_I2C.Pt = 0;//準(zhǔn)備從數(shù)據(jù)緩存區(qū)的0開始發(fā)送數(shù)據(jù) if(g_tS3C24xx_I2C.DataCount == 1) IICCON = 0x2f; // 恢復(fù)I2C傳輸,開始接收數(shù)據(jù),關(guān)閉ACK, 接收到數(shù)據(jù)時(shí)不發(fā)出ACK, 最后一個(gè)數(shù)據(jù)要先關(guān)閉ack, 因?yàn)樽詈笠粋€(gè)數(shù)據(jù)要發(fā)送no ack, 其實(shí)就是不發(fā)送ack else IICCON = 0xaf; // 恢復(fù)I2C傳輸,開始接收數(shù)據(jù), 0x2f與0xaf的區(qū)別就是前者不開ack break; } if ((g_tS3C24xx_I2C.DataCount--) == 0) { //如果要讀取的剩余數(shù)據(jù)長(zhǎng)度為0, 就發(fā)送P信號(hào) g_tS3C24xx_I2C.pData[g_tS3C24xx_I2C.Pt++] = IICDS; // 下面兩行恢復(fù)I2C操作,發(fā)出P信號(hào) IICSTAT = 0x90; IICCON = 0xaf; Delay(10000); // 等待一段時(shí)間以便P信號(hào)已經(jīng)發(fā)出 break; } g_tS3C24xx_I2C.pData[g_tS3C24xx_I2C.Pt++] = IICDS; // 接收最后一個(gè)數(shù)據(jù)時(shí),不要發(fā)出ACK信號(hào) if(g_tS3C24xx_I2C.DataCount == 0) IICCON = 0x2f; // 恢復(fù)I2C傳輸,接收到下一數(shù)據(jù)時(shí)無(wú)ACK else IICCON = 0xaf; // 恢復(fù)I2C傳輸,接收到下一數(shù)據(jù)時(shí)發(fā)出ACK break; } default: break; } }
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *以上為中斷方式操作I2C總線, 以下使用輪詢方式來(lái)操作* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
以下以 LM75(數(shù)字溫度傳感器) 來(lái)說(shuō)明 輪詢方式 讀取溫度值的方法.
控制過(guò)程: 1. 讀取溫度值之前需要先指定 LM75 的寄存器, LM75 的寄存器 0x0 是溫度寄存器器(READ ONLY). 所以先發(fā)送S信號(hào)再發(fā)送 LM75 的地址, 然后發(fā)送 0x0 就可以選中溫度寄存器
2. 選中溫度寄存器之后, LM75 會(huì)將 高/低 字節(jié)依次發(fā)送到I2C總線. 所以, 再次發(fā)送 LM75 地址, 讀取 高/低 字節(jié) 發(fā)送P信號(hào)結(jié)束傳輸.
int set_pointer_and_read_2byte(int mode) { //主機(jī)發(fā)送模式, 選中溫度寄存器 I2C0.I2CDS0 = 0x90; // 發(fā)送LM75地址 I2C0.I2CCON0 = 0xe0; // 使能, PRESCALER:512 ,RX/TX 中斷使能 I2C0.I2CSTAT0 =0xf0; // 主發(fā)送模式, 啟動(dòng), 使能 RX/TX while(!(I2C0.I2CCON0&(1<<4))); // 等待直至發(fā)送完成 I2C0.I2CDS0 = mode; // READ TEMPERATURE ONLY 讀取溫度寄存器 I2C0.I2CCON0 &= ~(1<<4); // 清除掛起標(biāo)志 & 恢復(fù)總線操作 while(!(I2C0.I2CCON0&(1<<4))); // 等待直至發(fā)送完成 //主機(jī)接收模式, 開始接收溫度數(shù)據(jù) I2C0.I2CDS0 = 0x91; // 重新發(fā)送LM75地址 I2C0.I2CSTAT0 =0xb0; // 主機(jī)接收模式, 啟動(dòng), 使能 RX/TX I2C0.I2CCON0 &= ~(1<<4); // 清除掛起標(biāo)志 & 恢復(fù)總線操作 while(!(I2C0.I2CCON0&(1<<4))); // 等待直至發(fā)送完成 I2C0.I2CCON0 &= ~(1<<4); // 清除掛起標(biāo)志 & 恢復(fù)總線操作 while(!(I2C0.I2CCON0&(1<<4))); // 等待直至讀取完成 high = I2C0.I2CDS0; // 讀取低8位數(shù)據(jù) I2C0.I2CCON0 &= ~((1<<7)|(1<<4));// 清除掛起標(biāo)志 & 恢復(fù)總線操作 & 禁止發(fā)送 ACK while(!(I2C0.I2CCON0&(1<<4))); // 等待直至讀取完成 low = I2C0.I2CDS0; // 讀取更低字節(jié)數(shù)據(jù)(小數(shù)部分 ?) I2C0.I2CSTAT0 &= ~(1<<5); // 發(fā)送 P信號(hào), 釋放總線 I2C0.I2CCON0 &= ~(1<<4); // 清除中斷標(biāo)志位 return ((high << 8) | low); }
到此,相信大家對(duì)“arm9 IIC接口有什么用”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。