📄 drv_i2c.c
字号:
** 入口参数 :无
** 出口参数 :无
** 说明 :注意处理子地址为2字节的情况。
**************************************************************************
//定义用于和I2C中断传递信息的全局变量
volatile uint8 I2C_dveAddr; //I2C器件从地址
volatile uint32 I2C_subAddr; //I2C器件内部子地址
volatile uint8 I2C_subAddrNum; //I2C子地址字节数
volatile uint8 *I2C_dbuf_Pt; //数据缓冲区指针
volatile uint8 I2C_byteNum; //要读取/写入的数据个数
volatile uint8 I2C_endFlag; //I2C总线结束标志:结束总线是置1
volatile uint8 I2C_subAddrFlag; // 子地址控制。
// 0--子地址已经处理或者不需要子地址
// 1--读取操作
// 2--写操作
*/
/////////////////////////////////////////////////////////////////////////
/* 读取I2C状态寄存器I2STAT */
/* 按照全局变量的设置进行操作及设置软件标志 */
/* 清除中断逻辑,中断返回 */
void __irq IRQ_I2C_Serving(void)
{
switch (I2STAT & 0xF8) { /* 根据状态码进行相应的处理 */
/*(1)*/ case 0x08: /* 已发送起始条件 */ //will send SLA+W and receive ACK
/*[1]*/
/*[4]*/
if(I2C_subAddrFlag == 1){ /* SLA+R */ /* 指定子地址,读*/
/*[1]*/ I2DAT = I2C_dveAddr & I2C_W; //0xFE; /* 先写入地址 */
}else{ //will send SLA+W or SLA+R.
/*(1)*/ I2DAT = I2C_dveAddr; /* 直接发送从机地址 */
/*[4]*/
}
/* 清零SI位 */
I2CONCLR = I2C_SI|I2C_STA; /* clr SI STA */
break;
////
case 0x10: /*已发送重复起始条件 */ /* 主发送和主接收都有 */
//will send SLA+W or SLA+R.
I2DAT = I2C_dveAddr; /* 重起总线后,重发从地址*/
I2CONCLR = I2C_SI|I2C_STA; //0x28; clr SI,STA
break;
/*(2)*/ case 0x18: // sended SLA+W, got ACK.
/*[2]*/
/*(3)*/ case 0x28: /* 已发送I2DAT中的数据,已接收ACK */
/*(3)*/ if (I2C_subAddrFlag == 0){ //sub address have been sent out.
if (I2C_byteNum > 0){ //data treatment.
I2DAT = *I2C_dbuf_Pt++;
I2CONCLR = I2C_STA|I2C_SI; //0x28; /* 清零SI,STA */
I2C_byteNum--;
}else{ //data sent over, stop I2C bus.
I2CONSET = I2C_STO; //(1 << 4); /* STO */
I2CONCLR = I2C_STA|I2C_SI; //0x28; /* 清零SI,STA */
I2C_endFlag = I2C_DEV_FREE; //1; /*总线已经停止*/
}
/*[2]*/ }else if(I2C_subAddrFlag == 1){ /* 若是指定地址读,则重新启动总线 */
if (I2C_subAddrNum == 2){
I2DAT = ((I2C_subAddr >> 8) & 0xff); //will send high address.
I2CONCLR = I2C_STA|I2C_SI; //0x28; /* 清零SI,STA */
I2C_subAddrNum--;
// break;
}else if(I2C_subAddrNum == 1){
I2DAT = (I2C_subAddr & 0xff); //will send low address.
I2CONCLR = I2C_STA|I2C_SI; //0x28; /* 清零SI,STA */
I2C_subAddrNum--;
// break;
/*[3]*/ }else if (I2C_subAddrNum == 0){ //sub address sent out.
I2CONSET = I2C_STA; //0x20; //resend START condition.
I2CONCLR = I2C_SI; //0x08;
I2C_subAddrFlag = 0; /* 子地址己处理 */
// break;
}
/*(2)*/ }else if (I2C_subAddrFlag == 2){ //will send subaddress and get ACK
// if (I2C_subAddrNum>0){ //sub_address treatment.
if (I2C_subAddrNum == 2){
I2DAT = ((I2C_subAddr>>8) & 0xff); //will send high address
I2CONCLR = I2C_STA|I2C_SI; //0x28;
I2C_subAddrNum--;
// break;
}else if (I2C_subAddrNum == 1){
I2DAT = (I2C_subAddr & 0xff); //will send low address.
I2CONCLR = I2C_STA|I2C_SI; //0x28;
I2C_subAddrNum--;
I2C_subAddrFlag = 0; //have treated sub address.
// break;
}
// }
}
break;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//// read data treatment.
/*[5]*/ case 0x40: /* 已发送SLA+R,已接收ACK */
if (I2C_byteNum <= 1){ /* 如果是最后一个字节 */
I2CONCLR = I2C_AA; //1 << 2; /* 下次发送非应答信号 */
}else{
I2CONSET = I2C_AA; //1 << 2; /* 下次发送应答信号 */
}
I2CONCLR = I2C_STA|I2C_SI; //0x28; /* 清零SI,STA */
break;
/*[6]*/ case 0x50: /* 已接收数据字节,已返回ACK */
*I2C_dbuf_Pt++ = I2DAT; //get received data
I2C_byteNum--;
if (I2C_byteNum == 1){ /* 接收最后一个字节 */
I2CONCLR = I2C_STA|I2C_SI|I2C_AA; //0x2C; /* STA,SI,AA = 0 */
}else{
I2CONSET = I2C_AA; //0x04; /* AA=1 */
I2CONCLR = I2C_STA|I2C_SI; //0x28;
}
break;
/*[7]*/ case 0x58: /* 已接收数据字节,已返回非应答 */
*I2C_dbuf_Pt++ = I2DAT; /* 读取最后一字节数据 */
I2CONSET = I2C_STO ; //0x10; /* 结束总线 */
I2CONCLR = I2C_STA|I2C_SI; //0x28;
I2C_endFlag = I2C_DEV_FREE; //1; //end I2C memory accessing.
break;
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//// erro case treatment.
case 0x20: /* 已发送SLA+W,已接收非应答 */
case 0x30: /* 已发送I2DAT中的数据,已接收非应答 */
case 0x38: /* 在SLA+R/W或数据字节中丢失仲裁 */
case 0x48: /* 已发送SLA+R,已接收非应答 */
I2CONCLR = I2C_STA|I2C_SI; //0x28;
I2C_endFlag = I2C_DEV_FREE; // //0xFF; original
break;
////
default:
break;
}
VICVectAddr = 0x00; /* 中断处理结束*/
}
/*
/////////////////////////////////////////////////////////////////////////////
** 函数名称:I2C_SendByte()
** 函数功能:向无子地址器件发送1字节数据。
** 入口参数:sla 器件地址
** dat 要发送的数据
** 出口参数:返回值为0时表示出错,为1时表示操作正确。
** 说明: 使用前要初始化好I2C引脚功能和I2C中断,并已使能I2C主模式
/////////////////////////////////////////////////////////////////////////////
*/
/*
uint8 I2C_SendByte(uint8 sla, uint8 dat)
{
I2C_StopAct();
DelayMS_(10);
// 参数设置
I2C_dveAddr = sla & I2C_W; // 写操作的器件地址
I2C_dbuf_Pt = &dat; // 待发送的数据
I2C_byteNum = 1; // 发送1字节数据
I2C_subAddrFlag = 0; // 无子地址
I2C_endFlag = I2C_DEV_BUSY; //0;
I2CONCLR = I2C_STA|I2C_SI |I2C_AA; //0x2C;
I2CONSET = I2C_EN |I2C_STA; //0x60; // 设置为主机,并启动总线
mSecondTick=I2C_TRANS_LIMIT;
while((I2C_endFlag==I2C_DEV_BUSY)&&(mSecondTick>1));
if(I2C_endFlag ==I2C_DEV_BUSY) DB_SendString("time overflow in I2C_SendByte()");
if(I2C_endFlag==I2C_DEV_FREE) return(TRUE);
else return(FALSE);
}
*/
/*
/////////////////////////////////////////////////////////////////////////////
** 函数名称:I2C_RcvByte()
** 函数功能:向无子地址器件读取1字节数据。
** 入口参数:sla 器件地址
** dat 接收数据的变量指针
** 出口参数:返回值为0时表示操作出错,为1时表示操作正确。
** 说明:使用前要初始化好I2C引脚功能和I2C中断,并已使能I2C主模式
/////////////////////////////////////////////////////////////////////////////
*/
/*
uint8 I2C_RcvByte(uint8 sla, uint8 *dat)
{
I2C_StopAct();
DelayMS_(10);
// 参数设置
I2C_dveAddr = sla | I2C_R; //+1; // 读操作的器件地址
I2C_dbuf_Pt = dat;
I2C_byteNum = 1;
I2C_subAddrFlag = 0; // 无子地址
I2C_endFlag = I2C_DEV_BUSY; //0;
I2CONCLR = I2C_STA|I2C_SI|I2C_AA; //0x2C;
I2CONSET = I2C_EN |I2C_STA; //0x60; // 设置为主机,并启动总线
mSecondTick=I2C_TRANS_LIMIT;
while((I2C_endFlag==I2C_DEV_BUSY)&&(mSecondTick>1));
if(I2C_endFlag ==I2C_DEV_BUSY) DB_SendString("time overflow in I2C_RcvByte()");
if(I2C_endFlag==I2C_DEV_FREE) return(TRUE);
else return(FALSE);
}
*/
/////////////////////////////////////////////////////////////////////////////
//// end of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -