?? i2cint.c
字號:
#define IN_I2C
#include "config.h"
static OS_EVENT *I2C_Sem;
static OS_EVENT *I2C_Mbox;
static volatile uint8 I2C_sla; /* I2C器件從地址 */
static volatile uint32 I2C_suba; /* I2C器件內(nèi)部子地址 */
static volatile uint8 I2C_suba_num; /* I2C子地址字節(jié)數(shù) */
static volatile uint8 *I2C_buf; /* 數(shù)據(jù)緩沖區(qū)指針 */
static volatile uint32 I2C_num; /* 要讀取/寫入的數(shù)據(jù)個數(shù) */
static volatile uint8 I2C_end; /* I2C總線結(jié)束標(biāo)志:結(jié)束總線是置1 */
static volatile uint8 I2C_suba_en; /* 子地址控制。
0--子地址已經(jīng)處理或者不需要子地址
1--讀取操作
2--寫操作
*/
#define I2C_WRITE_END 1 /* 寫完成 */
#define I2C_READ_END 2 /* 讀完成 */
#define I2C_NOT_GET_BUS 4 /* 丟失仲裁 */
#define I2C_ACK_ERR 8 /* 接收ACK錯誤 */
//uint8 I2C_Buf[256];
uint8 I2C_Init(uint32 Fi2c)
{
VICIntEnClr = 1 << 9; // 禁止能I2C_中斷
if (Fi2c <= 400000)
{
PINSEL0 = (PINSEL0 & 0xffffff0f) | 0x50; // 選擇管腳為I2C
I2CONCLR = 0x6C; // 清除控制寄存器
I2SCLH = (Fpclk / Fi2c + 1) / 2; // 設(shè)置高電平時間
I2SCLL = (Fpclk / Fi2c) / 2; // 設(shè)置低電平時間
I2C_Sem = OSSemCreate(1); // 信號量用于互斥操作總線
I2C_Mbox = OSMboxCreate(NULL); // 消息郵箱用于中斷向任務(wù)傳遞操作結(jié)果
if (I2C_Mbox == NULL)
{
return FALSE;
}
if (I2C_Sem != NULL)
{
return TRUE;
}
}
return FALSE;
}
uint8 I2C_ISendByte(uint8 sla, uint8 dat)
{ uint8 err;
OSSemPend(I2C_Sem, 0, &err);
I2C_sla = sla; // 寫操作的器件地址
I2C_buf = &dat; // 待發(fā)送的數(shù)據(jù)
I2C_num = 1; // 發(fā)送1字節(jié)數(shù)據(jù)
I2C_suba_en = 0; // 無子地址
I2C_end = 0;
I2CONCLR = 0x2C;
I2CONSET = 0x60; // 設(shè)置為主機,并啟動總線
while(0 == I2C_end);
if(1 == I2C_end)
{
OSSemPost(I2C_Sem);
return TRUE;
}
else
{
OSSemPost(I2C_Sem);
return FALSE;
}
}
uint8 I2C_IRcvByte(uint8 sla, uint8 *dat)
{ uint8 err;
OSSemPend(I2C_Sem, 0, &err);
I2C_sla = sla+1; // 讀操作的器件地址
I2C_buf = dat;
I2C_num = 1;
I2C_suba_en = 0; // 無子地址
I2C_end = 0;
I2CONCLR = 0x2C;
I2CONSET = 0x60; // 設(shè)置為主機,并啟動總線
while(0 == I2C_end);
if(1 == I2C_end)
{
OSSemPost(I2C_Sem);
return TRUE;
}
else
{
OSSemPost(I2C_Sem);
return FALSE;
}
}
uint8 I2C_ReadNByte (uint8 sla, uint32 suba_type, uint32 suba, uint8 *s, uint32 num)
{ uint8 err;
if (num > 0) /* 判斷num個數(shù)的合法性 */
{ /* 參數(shù)設(shè)置 */
OSSemPend(I2C_Sem, 0, &err);
if (suba_type == 1)
{ /* 子地址為單字節(jié) */
I2C_sla = sla + 1; /* 讀器件的從地址,R=1 */
I2C_suba = suba; /* 器件子地址 */
I2C_suba_num = 1; /* 器件子地址為1字節(jié) */
}
if (suba_type == 2)
{ /* 子地址為2字節(jié) */
I2C_sla = sla + 1; /* 讀器件的從地址,R=1 */
I2C_suba = suba; /* 器件子地址 */
I2C_suba_num = 2; /* 器件子地址為2字節(jié) */
}
if (suba_type == 3)
{ /* 子地址結(jié)構(gòu)為8+X*/
I2C_sla = sla + ((suba >> 7 )& 0x0e) + 1; /* 讀器件的從地址,R=1 */
I2C_suba = suba & 0x0ff; /* 器件子地址 */
I2C_suba_num = 1; /* 器件子地址為8+x */
}
I2C_buf = s; /* 數(shù)據(jù)接收緩沖區(qū)指針 */
I2C_num = num; /* 要讀取的個數(shù) */
I2C_suba_en = 1; /* 有子地址讀 */
I2C_end = 0;
I2CONCLR = (1 << 6)| // 清除控制寄存器
(1 << 5)|
(1 << 3)|
(1 << 2);
I2CONSET = (1 << 6)| // 設(shè)置為主模式,啟動總線
(1 << 5)|
(1 << 2);
VICIntEnable = 1 << 9;
OSMboxPend(I2C_Mbox, 0, &err);
VICIntEnClr = 1 << 9;
OSSemPost(I2C_Sem);
return TRUE;
}
else
{
return FALSE;
}
}
uint8 I2C_WriteNByte(uint8 sla, uint8 suba_type, uint32 suba, uint8 *s, uint32 num)
{ uint8 err;
if (num > 0)/* 如果讀取的個數(shù)為0,則返回錯誤 */
{ OSSemPend(I2C_Sem, 0, &err);
if (suba_type == 1)
{ /* 子地址為單字節(jié) */
I2C_sla = sla; /* 讀器件的從地址 */
I2C_suba = suba; /* 器件子地址 */
I2C_suba_num = 1; /* 器件子地址為1字節(jié) */
}
if (suba_type == 2)
{ /* 子地址為2字節(jié) */
I2C_sla = sla; /* 讀器件的從地址 */
I2C_suba = suba; /* 器件子地址 */
I2C_suba_num = 2; /* 器件子地址為2字節(jié) */
}
if (suba_type == 3)
{ /* 子地址結(jié)構(gòu)為8+X */
I2C_sla = sla + ((suba >> 7 )& 0x0e); /* 讀器件的從地址 */
I2C_suba = suba & 0x0ff; /* 器件子地址 */
I2C_suba_num = 1; /* 器件子地址為8+X */
}
I2C_buf = s; /* 數(shù)據(jù) */
I2C_num = num; /* 數(shù)據(jù)個數(shù) */
I2C_suba_en = 2; /* 有子地址,寫操作 */
I2C_end = 0;
I2CONCLR = (1 << 6)| // 清除控制寄存器
(1 << 5)|
(1 << 3)|
(1 << 2);
I2CONSET = (1 << 6)| // 設(shè)置為主模式,啟動總線
(1 << 5)|
(1 << 2);
VICIntEnable = 1 << 9;
OSMboxPend(I2C_Mbox, 0, &err);
VICIntEnClr = 1 << 9;
OSSemPost(I2C_Sem);
return TRUE;
}
else
{
return FALSE;
}
}
void I2C_Exception(void)
{
OS_ENTER_CRITICAL();
switch (I2STAT & 0xf8)
{ // I2C總線已啟動,準(zhǔn)備發(fā)送從地址。
case 0x08:
if(I2C_suba_en == 1) // 指定子地址讀
{
I2DAT = I2C_sla & 0xfe; // 先寫入地址
}
else
{
I2DAT = I2C_sla; // 否則直接發(fā)送從機地址
}
I2CONSET = (1 << 2); // AA = 1
I2CONCLR = (1 << 3); // SI = 0
break;
// 已發(fā)送重復(fù)起始條件
case 0x10:
I2DAT = I2C_sla; // 重起總線后,重發(fā)從地址
I2CONSET = (1 << 2); // AA = 1
I2CONCLR = (1 << 3); // SI = 0
break;
// 已發(fā)送I2DAT中的數(shù)據(jù),已接收ACK
case 0x18:
case 0x28:
// 若是無子地址讀
if (I2C_suba_en == 0) // 若是指定地址讀,則重新啟動總線
{
if (I2C_num > 0)
{
I2DAT = *I2C_buf++;
I2CONSET = (1 << 2); // AA = 1
I2CONCLR = (1 << 3); // SI = 0
I2C_num--;
}
// 沒有數(shù)據(jù)發(fā)送,則發(fā)送停止總線標(biāo)志
else
{
I2CONSET = (1 << 2)| // AA = 1
(1 << 4); // STO = 1
I2CONCLR = (1 << 3); // SI = 0
I2C_end = 1; // 指示總線停止
OSMboxPost(I2C_Mbox, (void *)I2C_WRITE_END);
VICIntEnClr = 1 << 9;
}
}
// 若是指定子地址讀,則重新啟動總線
if(I2C_suba_en == 1)
{
if (I2C_suba_num == 2)
{
I2DAT = ((I2C_suba >> 8) & 0xff);
I2CONSET = (1 << 2); // AA = 1
I2CONCLR = (1 << 3)| // SI = 0
(1 << 5); // STA = 0
I2C_suba_num--;
break;
}
if(I2C_suba_num == 1)
{
I2DAT = (I2C_suba & 0xff);
I2CONSET = (1 << 2); // AA = 1
I2CONCLR = (1 << 3)| // SI = 0
(1 << 5); // STA = 0
I2C_suba_num--;
break;
}
if (I2C_suba_num == 0)
{
I2CONSET = (1 << 5); // STA = 1
I2CONCLR = (1 << 3); // SI = 0
I2C_suba_en = 0;
break;
}
}
// 指定子地址寫,子地址尚未指定,則發(fā)送子地址
if (I2C_suba_en == 2)
{
if (I2C_suba_num > 0)
{ if (I2C_suba_num == 2)
{
I2DAT = ((I2C_suba >> 8) & 0xff);
I2CONSET = (1 << 2); // AA = 1
I2CONCLR = (1 << 3)| // SI = 0
(1 << 5); // STA = 0
I2C_suba_num--;
break;
}
if (I2C_suba_num == 1)
{
I2DAT = (I2C_suba & 0xff);
I2CONSET = (1 << 2); // AA = 1
I2CONCLR = (1 << 3)| // SI = 0
(1 << 5); // STA = 0
I2C_suba_num--;
I2C_suba_en = 0;
break;
}
}
}
break;
// 已發(fā)送SLA+R;已接收ACK
case 0x40:
if (I2C_num <= 1)
{
I2CONCLR = (1 << 2); // AA = 0
}
else
{
I2CONSET = (1 << 2); // AA = 1
}
I2CONCLR = (1 << 3)| // SI = 0
(1 << 5); // STA = 0 不能刪除,因為STA不能自動清除
break;
// 總線發(fā)生異常
case 0x20: // 已發(fā)送SLA+W,已接收非應(yīng)答
case 0x30: // 已發(fā)送I2DAT中的數(shù)據(jù),已接收非應(yīng)答
case 0x38: // 在SLA+R/W或數(shù)據(jù)字節(jié)中丟失仲裁
case 0x48: // 已發(fā)送SLA+R,已接收非應(yīng)答
I2CONSET = (1 << 2)| // AA = 1
(1 << 4); // STO = 1
I2CONCLR = (1 << 3); // SI = 0
I2C_end = 0xff; // 異常,總線停止
OSMboxPost(I2C_Mbox, (void *)I2C_ACK_ERR);
VICIntEnClr = 1 << 9;
break;
// 已接收數(shù)據(jù)字節(jié),已返回ACK
case 0x50:
*I2C_buf++ = I2DAT;
I2C_num--;
if (I2C_num == 1) // 接收最后一個字節(jié)
{
I2CONCLR = (1 << 2)| // AA = 0
(1 << 3); // SI = 0
}
else
{
I2CONSET = (1 << 2); // AA = 1
I2CONCLR = (1 << 3); // SI = 0
}
break;
// 已接收數(shù)據(jù)字節(jié),已返回非應(yīng)答
case 0x58:
*I2C_buf++ = I2DAT; // 讀取最后一字節(jié)數(shù)據(jù)
I2CONSET = (1 << 2)| // AA = 1
(1 << 4); // STO = 1
I2CONCLR = (1 << 3); // SI = 0
I2C_end = 1;
OSMboxPost(I2C_Mbox, (void *)I2C_READ_END);
VICIntEnClr = 1 << 9;
break;
default:
//I2CONCLR = 0x28; // 清除標(biāo)志
break;
}
VICVectAddr = 0x00;
OS_EXIT_CRITICAL();
}
/*********************************************************************************************************
** End Of File
********************************************************************************************************/
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -