?? i2cint.c
字號(hào):
/****************************************************************************
* File:I2CINT.C
* 功能:使用硬件I2C對(duì)E2PROM進(jìn)行操作,利用中斷方式操作。
* 說明:將跳線器JP8_LED1、JP12短接。
****************************************************************************/
#include "config.h"
#define CSI24WC02 0xA0 /* 定義器件地址 */
#define LED1CON 0x00000400 /* P0.10引腳控制LED1,低電平點(diǎn)亮 */
/* 以下為I2C操作時(shí)所需要的變量,在調(diào)用I2C子程序前要設(shè)置好這些變量 */
volatile uint8 I2C_sla; // 從機(jī)地址
volatile uint8 I2C_suba; // 子地址
volatile uint8 *I2C_buf; // 數(shù)據(jù)緩沖區(qū)指針 (讀操作時(shí)會(huì)被更改)
volatile uint8 I2C_num; // 操作數(shù)據(jù)個(gè)數(shù) (會(huì)被更改)
volatile uint8 I2C_end; // 操作結(jié)束標(biāo)志,為1時(shí)表示操作結(jié)束,為0xFF時(shí)表示操作失敗 (會(huì)被設(shè)置)
volatile uint8 I2C_suba_en; // 子地址使能控制,讀操作時(shí)請(qǐng)?jiān)O(shè)置為1,寫操作時(shí)請(qǐng)?jiān)O(shè)置為2 (會(huì)被更改)
/****************************************************************************
* 名稱:IRQ_I2C()
* 功能:I2C中斷,通過判斷I2C狀態(tài)字進(jìn)行相應(yīng)的操作。
* 入口參數(shù):無
* 出口參數(shù):無
****************************************************************************/
void __irq IRQ_I2C(void)
{ uint8 sta;
sta = I2STAT; // 讀出I2C狀態(tài)字
switch(sta)
{ case 0x08: // 己發(fā)送起始條件
if(1==I2C_suba_en) I2DAT = I2C_sla&0xFE; // 指定子地址讀時(shí),先寫入地址
else I2DAT = I2C_sla; // 否則直接發(fā)送從機(jī)地址
I2CONCLR = 0x28; // SI=0
break;
case 0x10:
I2DAT = I2C_sla; // 重啟動(dòng)總線后,發(fā)送從地址
I2CONCLR = 0x28; // SI=0
break;
case 0x18: // 已發(fā)送SLA+W,并已接收應(yīng)答
if(0==I2C_suba_en) // 無子地址,則直接發(fā)送數(shù)據(jù)
{ if(I2C_num>0)
{ I2DAT = *I2C_buf++;
I2CONCLR = 0x28;
I2C_num--;
}
else
{ I2CONSET = 0x10; // 無數(shù)據(jù)發(fā)送,結(jié)束總線
I2CONCLR = 0x28;
I2C_end = 1; // 設(shè)置總線操作結(jié)束標(biāo)志
}
break;
}
if(1==I2C_suba_en) // 發(fā)送子地址
{ I2DAT = I2C_suba;
I2CONCLR = 0x28;
}
if(2==I2C_suba_en)
{ I2DAT = I2C_suba;
I2CONCLR = 0x28;
I2C_suba_en = 0; // 子地址己處理
}
break;
case 0x28: // 已發(fā)送I2C數(shù)據(jù),并接收到應(yīng)答
if(0==I2C_suba_en) // 無子地址,則直接發(fā)送數(shù)據(jù)
{ if(I2C_num>0)
{ I2DAT = *I2C_buf++;
I2CONCLR = 0x28;
I2C_num--;
}
else
{ I2CONSET = 0x10; // 無數(shù)據(jù)發(fā)送,結(jié)束總線
I2CONCLR = 0x28;
I2C_end = 1;
}
break;
}
if(1==I2C_suba_en) // 若是指定地址讀,則重新啟動(dòng)總線
{ I2CONSET = 0x20;
I2CONCLR = 0x18;
I2C_suba_en = 0; // 子地址己處理
}
break;
case 0x20:
case 0x30:
case 0x38:
I2CONCLR = 0x28; // 總線進(jìn)入不可尋址從模式
I2C_end = 0xFF; // 總線出錯(cuò),設(shè)置標(biāo)志
break;
case 0x40: // 己發(fā)送SLA+R,并已接收到應(yīng)答
if(1==I2C_num) // 最后一字節(jié),接收數(shù)據(jù)后發(fā)送非應(yīng)答信號(hào)
{ I2CONCLR = 0x2C; // AA=0,接收到數(shù)據(jù)后產(chǎn)生非應(yīng)答
}
else // 接收數(shù)據(jù)并發(fā)送應(yīng)答信號(hào)
{ I2CONSET = 0x04; // AA=1,接收到數(shù)據(jù)后產(chǎn)生應(yīng)答
I2CONCLR = 0x28;
}
break;
case 0x50:
*I2C_buf++ = I2DAT; // 讀取數(shù)據(jù)
I2C_num--;
if(1==I2C_num)
{ I2CONCLR = 0x2C; // AA=0,接收到數(shù)據(jù)后產(chǎn)生非應(yīng)答
}
else
{ I2CONSET = 0x04; // AA=1,接收到數(shù)據(jù)后產(chǎn)生應(yīng)答
I2CONCLR = 0x28;
}
break;
case 0x58:
*I2C_buf++ = I2DAT; // 讀取最后一字節(jié)數(shù)據(jù)
I2CONSET = 0x10; // 結(jié)束總線
I2CONCLR = 0x28;
I2C_end = 1;
break;
case 0x48:
I2CONCLR = 0x28; // 總線進(jìn)入不可尋址從模式
I2C_end = 0xFF;
break;
}
VICVectAddr = 0x00; // 中斷處理結(jié)束
}
/****************************************************************************
* 名稱:ISendStr()
* 功能:使用硬件I2C發(fā)送數(shù)據(jù)。
* 入口參數(shù):無
* 出口參數(shù):返回值為0時(shí)表示出錯(cuò),為1時(shí)表示操作正確。
* 說明:使用前設(shè)置好參數(shù)
****************************************************************************/
uint8 ISendStr(void)
{ I2C_end = 0;
I2CONCLR = 0x2C;
I2CONSET = 0x40; // 使能I2C
I2CONSET = 0x64; // 設(shè)置為主機(jī),并啟動(dòng)總線
while(0==I2C_end);
if(1==I2C_end) return(1);
else return(0);
}
/****************************************************************************
* 名稱:IRcvStr()
* 功能:使用硬件I2C讀取數(shù)據(jù)。
* 入口參數(shù):無
* 出口參數(shù):返回值為0時(shí)表示出錯(cuò),為1時(shí)表示操作正確。
* 說明:使用前設(shè)置好參數(shù)
****************************************************************************/
uint8 IRcvStr(void)
{ if(0==I2C_num) return(0);
I2C_end = 0;
I2CONCLR = 0x2C;
I2CONSET = 0x40; // 使能I2C
I2CONSET = 0x64; // 設(shè)置為主機(jī),并啟動(dòng)總線
while(0==I2C_end);
if(1==I2C_end) return(1);
else return(0);
}
/****************************************************************************
* 名稱:I2C_Init()
* 功能:I2C初始化,包括初始化其中斷為向量IRQ中斷。
* 入口參數(shù):無
* 出口參數(shù):無
****************************************************************************/
void I2C_Init(void)
{ /* 設(shè)置I2C時(shí)鐘為100KHz */
I2SCLH = I2SCLL = 14; // 晶振為11.0592MHz,F(xiàn)pclk = 2.7648MHz
/* 設(shè)置I2C中斷允許 */
VICIntSelect = 0x00000000; // 設(shè)置所有通道為IRQ中斷
VICVectCntl0 = 0x29; // I2C通道分配到IRQ slot 0,即優(yōu)先級(jí)最高
VICVectAddr0 = (int)IRQ_I2C; // 設(shè)置I2C中斷向量地址
VICIntEnable = 0x0200; // 使能I2C中斷
}
/****************************************************************************
* 名稱:DelayNS()
* 功能:長(zhǎng)軟件延時(shí)
* 入口參數(shù):dly 延時(shí)參數(shù),值越大,延時(shí)越久
* 出口參數(shù):無
****************************************************************************/
void DelayNS(uint32 dly)
{ uint32 i;
for(; dly>0; dly--)
for(i=0; i<50000; i++);
}
/****************************************************************************
* 名稱:WrEepromErr()
* 功能:讀寫EEPRM出錯(cuò)報(bào)警,即閃動(dòng)LED1。
* 入口參數(shù):無
* 出口參數(shù):無
****************************************************************************/
void WrEepromErr(void)
{ while(1)
{ IOSET = LED1CON;
DelayNS(10);
IOCLR = LED1CON;
DelayNS(10);
}
}
/****************************************************************************
* 名稱:main()
* 功能:向E2PROM寫入10字節(jié)數(shù)據(jù),然后讀出判斷是否正確寫入。
****************************************************************************/
int main(void)
{ uint8 i;
uint8 data_buf[30];
PINSEL0 = 0x00000050; // 設(shè)置I/O口工作模式,使用I2C口
PINSEL1 = 0x00000000;
IODIR = LED1CON; // 設(shè)置LED1控制口為輸出,其它I/O為輸入
I2C_Init(); // I2C初始化
for(i=0; i<10; i++) data_buf[i] = i+'0';
I2C_sla = CSI24WC02;
I2C_suba = 0x00;
I2C_suba_en = 2;
I2C_buf = data_buf;
I2C_num = 10;
ISendStr(); // 在0x00地址處寫入10字節(jié)數(shù)據(jù)
DelayNS(1); // 等待寫周期結(jié)束
for(i=0; i<10; i++) data_buf[i] = 0;
I2C_sla = CSI24WC02+1;
I2C_suba = 0x00;
I2C_suba_en = 1;
I2C_buf = data_buf;
I2C_num = 10;
IRcvStr(); // 在0x00地址處讀出10字節(jié)數(shù)據(jù)
/* 校驗(yàn)讀出的數(shù)據(jù),若不正確則閃爍LED報(bào)警 */
for(i=0; i<10; i++)
{ if(data_buf[i]!=(i+'0')) WrEepromErr();
}
IOCLR = LED1CON; // 點(diǎn)亮LED1
while(1);
return(0);
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -