📄 drv_i2c.c
字号:
////////////////////////////////////////////////////////////////////////
#include "config_60_61.h"
#include "config_GD61.h"
#include "include_GD61.h"
////////////////////////////////////////////////////////////////////////
#define ONE_BYTE_SUBA 1
#define TWO_BYTE_SUBA 2
#define X_ADD_8_SUBA 3
#define I2C_EN 0x40 //I2CONSET bits define
#define I2C_STA 0x20
#define I2C_STO 0x10
#define I2C_SI 0x08
#define I2C_AA 0x04
#define I2C_W 0xFE
#define I2C_R 0x01
#define I2C_DEV_FREE 0x01
#define I2C_DEV_BUSY 0x00
#define I2C_TRANS_LIMIT 100 //100 milsecond, about 100 bytes
extern volatile uint16 mSecondTick;
///////////////////////////////////////////////////////////////////////
/* 定义用于和I2C中断传递信息的全局变量 */
volatile uint8 I2C_dveAddr; //I2C器件从地址
volatile uint8 I2C_subAddrNum; //I2C子地址字节数
volatile uint32 I2C_subAddr; //I2C器件内部子地址
volatile uint8 *I2C_dbuf_Pt; //数据缓冲区指针
volatile uint8 I2C_byteNum; //要读取/写入的数据个数
volatile uint8 I2C_endFlag; //I2C总线结束标志:结束总线是置1
volatile uint8 I2C_subAddrFlag; // 子地址控制。
// 0--子地址已经处理或者不需要子地址
// 1--读取操作
// 2--写操作
///////////////////////////////////////////////////////////////////////
void I2C_StopAct(void);
void I2C_Initialize(uint32 FrqI2C);
//uint8 I2C_SendByte(uint8 sla, uint8 dat);
//uint8 I2C_RcvByte(uint8 sla, uint8 *dat);
uint8 I2C_ReadNByte (uint8 sla, uint8 suba_type, uint32 suba, uint8*s, uint8 num);
uint8 I2C_WriteNByte(uint8 sla, uint8 suba_type, uint32 suba, uint8*s, uint8 num);
void __irq IRQ_I2C_Serving(void);
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
void I2C_StopAct(void)
{
IRQDisable();
I2CONSET = I2C_STO; //0x10; /*结束总线*/
I2CONCLR = I2C_STA|I2C_SI; //0x28;
I2C_endFlag = I2C_DEV_FREE; //1;
VICVectAddr = 0x00; /*中断处理结束*/
IRQEnable(); // 使能IRQ中断
}
/*
///////////////////////////////////////////////////////////////////////
** 函数名称 :I2C_Initialize()
** 函数功能 :I2C初始化
** 入口参数 :FrqI2C I2C总线频率(最大400K)
** 出口参数 :无
///////////////////////////////////////////////////////////////////////
*/
void I2C_Initialize(uint32 FrqI2C)
{
IRQDisable();
if (FrqI2C > 400000) FrqI2C = 400000;
PINSEL0 = (PINSEL0 & (~0xF0))|0x50; // 不影响其它管脚连接
I2SCLH = (LPC_FPCLK/FrqI2C + 1)/2; /* 设定I2C时钟*/
I2SCLL = (LPC_FPCLK/FrqI2C)/2;
I2CONCLR = I2C_STA|I2C_SI |I2C_AA; //0x2C;
I2CONSET = I2C_EN; //0x40; /* 使能主I2C*/
/* 设置I2C中断允许 */
VICVectCntl3 = (0x20|INT_IIC0); /* I2C通道分配到IRQ slot3*/
VICVectAddr3 = (int32)IRQ_I2C_Serving; /* 设置I2C中断向量*/
VICIntEnable = 1<<INT_IIC0; /* 使能I2C中断*/
IRQEnable(); // 使能IRQ中断
}
/*
**********************************************************************************
** 函数名称 :I2C_ReadNByte()
** 函数功能 :从有子地址器件任意地址开始读取N字节数据
** 入口参数 : sla 器件从地址
** suba_type 子地址结构 1-单字节地址 2-8+X结构 2-双字节地址
** suba 器件子地址
** s 数据接收缓冲区指针
** num 读取的个数
** 出口参数 : TRUE 操作成功
** FALSE 操作失败
**********************************************************************************
*/
//#define ONE_BYTE_SUBA 1
//#define TWO_BYTE_SUBA 2
//#define X_ADD_8_SUBA 3
uint8 I2C_ReadNByte (uint8 sla, uint8 suba_type, uint32 suba, uint8 *s, uint8 num)
{
I2C_StopAct(); DelayMS_(1);
if (num>0){ /* 判断num个数的合法性 *//* 参数设置 */
if (suba_type == ONE_BYTE_SUBA){ /* 子地址为单字节 */
I2C_dveAddr = sla|I2C_R; //+ 1; /* 读器件的从地址,R=1 */
I2C_subAddr = suba; /* 器件子地址 */
I2C_subAddrNum = 1; /* 器件子地址为1字节 */
}else if (suba_type == TWO_BYTE_SUBA){ /* 子地址为2字节 */
I2C_dveAddr = sla|I2C_R; // + 1; /* 读器件的从地址,R=1 */
I2C_subAddr = suba; /* 器件子地址 */
I2C_subAddrNum = 2; /* 器件子地址为2字节 */
}else if (suba_type == X_ADD_8_SUBA){ /* 子地址结构为8+X*/
I2C_dveAddr = (sla+((suba>>7)&0x0e))|I2C_R; //1;/* 读器件的从地址,R=1 */
I2C_subAddr = suba & 0x0ff; /* 器件子地址 */
I2C_subAddrNum = 1; /* 器件子地址为8+x */
}
I2C_dbuf_Pt = s; /* 数据接收缓冲区指针 */
I2C_byteNum = num; /* 要读取的个数 */
I2C_subAddrFlag = 1; /* 有子地址, 读操作 */
I2C_endFlag = I2C_DEV_BUSY; //0;
I2CONCLR = I2C_AA|I2C_SI|I2C_STA; /* AA SI STA ,清除STA,SI,AA标志位 */
I2CONSET = I2C_STA|I2C_EN; /* STA I2CEN ,置位STA,启动I2C总线 */
/* 等待I2C操作完成 */
mSecondTick=I2C_TRANS_LIMIT;
while((I2C_endFlag == I2C_DEV_BUSY)&&(mSecondTick>1));
if(I2C_endFlag == I2C_DEV_BUSY) DB_SendString("time overflow in I2C_ReadNByte()");
if (I2C_endFlag == I2C_DEV_FREE) return (TRUE);
else return (FALSE);
}
return (FALSE);
}
/*
***********************************************************************************
** 函数名称 :I2C_WriteNByte()
** 函数功能 :向有子地址器件写入N字节数据
** 入口参数 : sla 器件从地址
** suba_type 子地址结构 1-单字节地址 3-8+X结构 2-双字节地址
** suba 器件内部物理地址
** *s 将要写入的数据的指针
** num 将要写入的数据的个数
** 出口参数 : TRUE 操作成功
** FALSE 操作失败
**********************************************************************************
*/
//#define ONE_BYTE_SUBA 1
//#define TWO_BYTE_SUBA 2
//#define X_ADD_8_SUBA 3
uint8 I2C_WriteNByte(uint8 sla, uint8 suba_type, uint32 suba, uint8 *s, uint8 num)
{
I2C_StopAct(); DelayMS_(1);
if (num>0){ /* 如果读取的个数为0,则返回错误 */ /* 设置参数 */
if (suba_type == ONE_BYTE_SUBA){ /* 子地址为单字节 */
I2C_dveAddr = sla & I2C_W; /* 读器件的从地址 */
I2C_subAddr = suba; /* 器件子地址 */
I2C_subAddrNum = 1; /* 器件子地址为1字节 */
}
else if (suba_type == TWO_BYTE_SUBA){ /* 子地址为2字节 */
I2C_dveAddr = sla & I2C_W; /* 读器件的从地址 */
I2C_subAddr = suba; /* 器件子地址 */
I2C_subAddrNum = 2; /* 器件子地址为2字节 */
}else if (suba_type == X_ADD_8_SUBA){ /* 子地址结构为8+X */
I2C_dveAddr = (sla+((suba>>7)&0x0e)) & I2C_W; /*读器件的从地址*/
I2C_subAddr = suba & 0x0ff; /* 器件子地址 */
I2C_subAddrNum = 1; /* 器件子地址为8+X */
}
I2C_dbuf_Pt = s; /* 数据 */
I2C_byteNum = num; /* 数据个数 */
I2C_subAddrFlag = 2; /* 有子地址,写操作 */
I2C_endFlag = I2C_DEV_BUSY; //0;
I2CONCLR = I2C_AA|I2C_SI|I2C_STA; /* AA SI STA 清除STA,SI,AA标志位 */
I2CONSET = I2C_STA|I2C_EN; /* STA I2CEN, 置位STA,启动I2C总线 */
/* 等待I2C操作完成 */
mSecondTick=I2C_TRANS_LIMIT;
while((I2C_endFlag == I2C_DEV_BUSY)&&(mSecondTick>1));
if((I2C_endFlag == I2C_DEV_BUSY)) DB_SendString("time overflow in I2C_WriteNByte()");
if (I2C_endFlag == I2C_DEV_FREE) return (TRUE);
else return (FALSE);
}
return (FALSE);
}
/*
**************************************************************************
** 函数名称 :__irq IRQ_I2C_Serving()
** 函数名次 :硬件I2C中断服务程序。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -