?? i2cint.c
字號:
/*
---------------------------------------------------------------------------------------------------------
*********************************************************************************************************
** 文件名稱 : I2CINT.c
** 功能說明 : LPC2000硬件I2C中斷方式軟件包。
** 使用說明 : 主程序要配置好I2C總線接口(I2C引腳功能和I2C中斷,并已使能I2C主模式)
*********************************************************************************************************
---------------------------------------------------------------------------------------------------------
*/
#include "config.h"
/* 定義用于和I2C中斷傳遞信息的全局變量 */
volatile uint8 I2C_sla; /* I2C器件從地址 */
volatile uint32 I2C_suba; /* I2C器件內部子地址 */
volatile uint8 I2C_suba_num; /* I2C子地址字節數 */
volatile uint8 *I2C_buf; /* 數據緩沖區指針 */
volatile uint32 I2C_num; /* 要讀取/寫入的數據個數 */
volatile uint8 I2C_end; /* I2C總線結束標志:結束總線是置1 */
volatile uint8 I2C_suba_en; /* 子地址控制。
0--子地址已經處理或者不需要子地址
1--讀取操作
2--寫操作
*/
/*
**********************************************************************************************************
** 函數名稱:ISendByte()
** 函數功能:向無子地址器件發送1字節數據。
** 入口參數:sla 器件地址
** dat 要發送的數據
** 出口參數:返回值為0時表示出錯,為1時表示操作正確。
** 說明: 使用前要初始化好I2C引腳功能和I2C中斷,并已使能I2C主模式
*********************************************************************************************************
*/
uint8 ISendByte(uint8 sla, uint8 dat)
{ /* 參數設置 */
I2C_sla = sla; // 寫操作的器件地址
I2C_buf = &dat; // 待發送的數據
I2C_num = 1; // 發送1字節數據
I2C_suba_en = 0; // 無子地址
I2C_end = 0;
I2CONCLR = 0x2C;
I2CONSET = 0x60; // 設置為主機,并啟動總線
while(0==I2C_end);
if(1==I2C_end) return(1);
else return(0);
}
/*
*********************************************************************************************************
** 函數名稱:IRcvByte()
** 函數功能:向無子地址器件讀取1字節數據。
** 入口參數:sla 器件地址
** dat 接收數據的變量指針
** 出口參數:返回值為0時表示操作出錯,為1時表示操作正確。
** 說明:使用前要初始化好I2C引腳功能和I2C中斷,并已使能I2C主模式
*********************************************************************************************************
*/
uint8 IRcvByte(uint8 sla, uint8 *dat)
{ /* 參數設置 */
I2C_sla = sla+1; // 讀操作的器件地址
I2C_buf = dat;
I2C_num = 1;
I2C_suba_en = 0; // 無子地址
I2C_end = 0;
I2CONCLR = 0x2C;
I2CONSET = 0x60; // 設置為主機,并啟動總線
while(0==I2C_end);
if(1==I2C_end) return(1);
else return(0);
}
/*
*********************************************************************************************************
** 函數名稱 :I2C_ReadNByte()
** 函數功能 :從有子地址器件任意地址開始讀取N字節數據
** 入口參數 : sla 器件從地址
** suba_type 子地址結構 1-單字節地址 2-8+X結構 2-雙字節地址
** suba 器件子地址
** s 數據接收緩沖區指針
** num 讀取的個數
** 出口參數 : TRUE 操作成功
** FALSE 操作失敗
*********************************************************************************************************
*/
uint8 I2C_ReadNByte (uint8 sla, uint32 suba_type, uint32 suba, uint8 *s, uint32 num)
{
if (num > 0) /* 判斷num個數的合法性 */
{ /* 參數設置 */
if (suba_type == 1)
{ /* 子地址為單字節 */
I2C_sla = sla + 1; /* 讀器件的從地址,R=1 */
I2C_suba = suba; /* 器件子地址 */
I2C_suba_num = 1; /* 器件子地址為1字節 */
}
if (suba_type == 2)
{ /* 子地址為2字節 */
I2C_sla = sla + 1; /* 讀器件的從地址,R=1 */
I2C_suba = suba; /* 器件子地址 */
I2C_suba_num = 2; /* 器件子地址為2字節 */
}
if (suba_type == 3)
{ /* 子地址結構為8+X*/
I2C_sla = sla + ((suba >> 7 )& 0x0e) + 1; /* 讀器件的從地址,R=1 */
I2C_suba = suba & 0x0ff; /* 器件子地址 */
I2C_suba_num = 1; /* 器件子地址為8+x */
}
I2C_buf = s; /* 數據接收緩沖區指針 */
I2C_num = num; /* 要讀取的個數 */
I2C_suba_en = 1; /* 有子地址讀 */
I2C_end = 0;
/* 清除STA,SI,AA標志位 */
I2CONCLR = (1 << 2)| /* AA */
(1 << 3)| /* SI */
(1 << 5); /* STA */
/* 置位STA,啟動I2C總線 */
I2CONSET = (1 << 5)| /* STA */
(1 << 6); /* I2CEN */
/* 等待I2C操作完成 */
while (I2C_end == 0)
{ }
if (I2C_end == 1)
return (TRUE);
else
return (FALSE);
}
return (FALSE);
}
/*
*********************************************************************************************************
** 函數名稱 :I2C_WriteNByte()
** 函數功能 :向有子地址器件寫入N字節數據
** 入口參數 : sla 器件從地址
** suba_type 子地址結構 1-單字節地址 3-8+X結構 2-雙字節地址
** suba 器件內部物理地址
** *s 將要寫入的數據的指針
** num 將要寫入的數據的個數
** 出口參數 : TRUE 操作成功
** FALSE 操作失敗
*********************************************************************************************************
*/
uint8 I2C_WriteNByte(uint8 sla, uint8 suba_type, uint32 suba, uint8 *s, uint32 num)
{
if (num > 0)/* 如果讀取的個數為0,則返回錯誤 */
{ /* 設置參數 */
if (suba_type == 1)
{ /* 子地址為單字節 */
I2C_sla = sla; /* 讀器件的從地址 */
I2C_suba = suba; /* 器件子地址 */
I2C_suba_num = 1; /* 器件子地址為1字節 */
}
if (suba_type == 2)
{ /* 子地址為2字節 */
I2C_sla = sla; /* 讀器件的從地址 */
I2C_suba = suba; /* 器件子地址 */
I2C_suba_num = 2; /* 器件子地址為2字節 */
}
if (suba_type == 3)
{ /* 子地址結構為8+X */
I2C_sla = sla + ((suba >> 7 )& 0x0e); /* 讀器件的從地址 */
I2C_suba = suba & 0x0ff; /* 器件子地址 */
I2C_suba_num = 1; /* 器件子地址為8+X */
}
I2C_buf = s; /* 數據 */
I2C_num = num; /* 數據個數 */
I2C_suba_en = 2; /* 有子地址,寫操作 */
I2C_end = 0;
/* 清除STA,SI,AA標志位 */
I2CONCLR = (1 << 2)| /* AA */
(1 << 3)| /* SI */
(1 << 5); /* STA */
/* 置位STA,啟動I2C總線 */
I2CONSET = (1 << 5)| /* STA */
(1 << 6); /* I2CEN*/
/* 等待I2C操作完成 */
while (I2C_end == 0)
{ }
if (I2C_end == 1)
return (TRUE);
else
return (FALSE);
}
return (FALSE);
}
/*
*********************************************************************************************************
** 函數名稱 :__irq IRQ_I2C()
** 函數名次 :硬件I2C中斷服務程序。
** 入口參數 :無
** 出口參數 :無
** 說明 :注意處理子地址為2字節的情況。
*********************************************************************************************************
*/
void __irq IRQ_I2C(void)
{ /* 讀取I2C狀態寄存器I2DAT */
/* 按照全局變量的設置進行操作及設置軟件標志 */
/* 清除中斷邏輯,中斷返回 */
switch (I2STAT & 0xF8)
{ /* 根據狀態碼進行相應的處理 */
case 0x08: /* 已發送起始條件 */ /* 主發送和主接收都有 */
/* 裝入SLA+W或者SLA+R */
if(I2C_suba_en == 1)/* SLA+R */ /* 指定子地址讀 */
{ I2DAT = I2C_sla & 0xFE; /* 先寫入地址 */
}
else /* SLA+W */
{ I2DAT = I2C_sla; /* 否則直接發送從機地址 */
}
/* 清零SI位 */
I2CONCLR = (1 << 3)| /* SI */
(1 << 5); /* STA */
break;
case 0x10: /*已發送重復起始條件 */ /* 主發送和主接收都有 */
/* 裝入SLA+W或者SLA+R */
I2DAT = I2C_sla; /* 重起總線后,重發從地址 */
I2CONCLR = 0x28; /* 清零SI,STA */
break;
case 0x18:
case 0x28: /* 已發送I2DAT中的數據,已接收ACK */
if (I2C_suba_en == 0)
{
if (I2C_num > 0)
{ I2DAT = *I2C_buf++;
I2CONCLR = 0x28; /* 清零SI,STA */
I2C_num--;
}
else /* 沒有數據發送了 */
{ /* 停止總線 */
I2CONSET = (1 << 4); /* STO */
I2CONCLR = 0x28; /* 清零SI,STA */
I2C_end = 1; /* 總線已經停止 */
}
}
if(I2C_suba_en == 1) /* 若是指定地址讀,則重新啟動總線 */
{
if (I2C_suba_num == 2)
{ I2DAT = ((I2C_suba >> 8) & 0xff);
I2CONCLR = 0x28; /* 清零SI,STA */
I2C_suba_num--;
break;
}
if(I2C_suba_num == 1)
{ I2DAT = (I2C_suba & 0xff);
I2CONCLR = 0x28; /* 清零SI,STA */
I2C_suba_num--;
break;
}
if (I2C_suba_num == 0)
{ I2CONSET = 0x20;
I2CONCLR = 0x08;
I2C_suba_en = 0; /* 子地址己處理 */
break;
}
}
if (I2C_suba_en == 2)/* 指定子地址寫,子地址尚未指定,則發送子地址 */
{
if (I2C_suba_num > 0)
{ if (I2C_suba_num == 2)
{ I2DAT = ((I2C_suba >> 8) & 0xff);
I2CONCLR = 0x28;
I2C_suba_num--;
break;
}
if (I2C_suba_num == 1)
{ I2DAT = (I2C_suba & 0xff);
I2CONCLR = 0x28;
I2C_suba_num--;
I2C_suba_en = 0;
break;
}
}
}
break;
case 0x40: /* 已發送SLA+R,已接收ACK */
if (I2C_num <= 1) /* 如果是最后一個字節 */
{ I2CONCLR = 1 << 2; /* 下次發送非應答信號 */
}
else
{ I2CONSET = 1 << 2; /* 下次發送應答信號 */
}
I2CONCLR = 0x28; /* 清零SI,STA */
break;
case 0x20: /* 已發送SLA+W,已接收非應答 */
case 0x30: /* 已發送I2DAT中的數據,已接收非應答 */
case 0x38: /* 在SLA+R/W或數據字節中丟失仲裁 */
case 0x48: /* 已發送SLA+R,已接收非應答 */
I2CONCLR = 0x28;
I2C_end = 0xFF;
break;
case 0x50: /* 已接收數據字節,已返回ACK */
*I2C_buf++ = I2DAT;
I2C_num--;
if (I2C_num == 1)/* 接收最后一個字節 */
{ I2CONCLR = 0x2C; /* STA,SI,AA = 0 */
}
else
{ I2CONSET = 0x04; /* AA=1 */
I2CONCLR = 0x28;
}
break;
case 0x58: /* 已接收數據字節,已返回非應答 */
*I2C_buf++ = I2DAT; /* 讀取最后一字節數據 */
I2CONSET = 0x10; /* 結束總線 */
I2CONCLR = 0x28;
I2C_end = 1;
break;
default:
break;
}
VICVectAddr = 0x00; /* 中斷處理結束 */
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -