// ============================================================================= // 功能: 结束本次读写回调函数,区分读写的不同停止时序,当属于发送时,则直接停止时序, // 若为读,则先停止回复ACK,再停止 // 参数: reg,个性标记,本模块内即IIC寄存器基址 // 返回: 无 // ============================================================================= static void __IIC_GenerateEnd(tagI2CReg *reg) { if(reg == NULL) return; if((reg->SR1 & I2C_SR1_TxE_MASK )&& (reg->SR1 & I2C_SR1_BTF_MASK))//发送 { __IIC_GenerateStop(reg); } else //接收 { reg->CR1 &= ~(I2C_CR1_ACK_MASK);//停止回复ACK __IIC_GenerateStop(reg); } }
// ============================================================================= // 功能:IIC接收与发送中断服务函数。该函数实现的功能如下: // 1.每发送与接收一个或若干字节发生一次中断; // 2.若有多个中断使用同一个中断号,则需根据具体情况区分使用的是哪个中断; // 3.清中断标志,并判断ACK信号,每读写字节,计数器都需相应修改; // 4.接收达到倒数第一个字节时,需配置不发送ACK信号; // 5.接收或发送完成时,需post信号量IntParam->pDrvPostSemp; // 6.接收或发送完成时,需产生停止时序。 // 参数:i2c_int_line,中断号,本函数没用到 // 返回:无意义 // ============================================================================= static u32 __IIC_ISR(ufast_t i2c_int_line) { static struct tagIIC_IntParamSet *IntParam; static struct tagIIC_CB *ICB; tagI2CReg *reg; u8 ch; u32 IicErrorNo; u32 irptl_temp=*rTWIIRPTL;//read IRPTL reg = (tagI2CReg*)CN_IIC_REGISTER_BADDR0; ICB=&s_IIC0_CB; IntParam=&IntParamset0; //MASTER TX\RX COMPLETE if( (irptl_temp & TWITXINT) != 0 ) //发送中断 { if(!(CHKBIT(reg->rTWIMSTAT, TWIANAK)|CHKBIT(reg->rTWIMSTAT, TWIDNAK))) { //从泛设备读一个字节的数据,并发送 if(IIC_PortRead(ICB,&ch,1) > 0) { *rTXTWI8 = ch; IntParam->TransCount++; } else if(IntParam->TransCount == IntParam->TransTotalLen) { //in Master TX Mode , we need to STOP TWI by ourself Lock_SempPost(IntParam->pDrvPostSemp); __IIC_GenerateStop(reg); } else { IicErrorNo = CN_IIC_NO_ACK_ERR;//调用错处处理API函数 IIC_ErrPop(ICB,IicErrorNo); } } else //TX no ACK { IicErrorNo = CN_IIC_NO_ACK_ERR;//调用错处处理API函数 IIC_ErrPop(ICB,IicErrorNo); return 1; } //clear IIC interrupt irptl_temp = TWITXINT; *rTWIIRPTL = irptl_temp; } else if( (irptl_temp & TWIRXINT) != 0 ) //接收中断 { if(!(CHKBIT(reg->rTWIMSTAT, TWIANAK)|CHKBIT(reg->rTWIMSTAT, TWIDNAK))) { ch = *rRXTWI8; IIC_PortWrite(ICB,&ch,1); IntParam->TransCount ++; if(IntParam->TransCount == IntParam->TransTotalLen) { __IIC_GenerateStop(reg); Lock_SempPost(IntParam->pDrvPostSemp);//释放总线信号量 } } else //RX no ACK { } //clear IIC interrupt irptl_temp = TWIRXINT; *rTWIIRPTL = irptl_temp; } else //TWIMERR { } irptl_temp==*rTWIIRPTL; //update TWI_IRPTL //MASTER TRANS COMPLETE if( (irptl_temp & TWIMCOM) != 0 ) { _IIC_GenerateDisable(reg); Lock_SempPost(ICB->iic_bus_semp);//释放总线信号量 //clear STOP CLRBIT(reg->rTWIMCTL, TWISTOP); //clear IIC interrupt irptl_temp |= TWIMCOM; *rTWIIRPTL = irptl_temp; } return 0; }
// ============================================================================= // 功能: IIC接收与发送中断服务函数。该函数实现的功能如下: // 1.每发送与接收一个或若干字节发生一次中断; // 2.若有多个中断使用同一个中断号,则需根据具体情况区分使用的是哪个中断; // 3.清中断标志,并判断ACK信号,每读写字节,计数器都需相应修改; // 4.接收达到倒数第一个字节时,需配置不发送ACK信号; // 5.接收或发送完成时,需post信号量IntParam->pDrvPostSemp; // 6.接收或发送完成时,需产生停止时序。 // 参数:i2c_int_line,中断号,本函数没用到 // 返回:true falst // ============================================================================= static u32 __IIC_ISR(ufast_t i2c_int_line) { static struct IIC_CB *ICB; static struct IIC_IntParamSet *IntParam; tagI2CReg *reg; u8 ch; u32 IicErrorNo; switch (i2c_int_line) { case CN_INT_LINE_I2C1_EV: reg = (tagI2CReg*)CN_IIC1_BASE; ICB = &s_IIC1_CB; IntParam = &IntParamset0; break; case CN_INT_LINE_I2C2_EV: reg = (tagI2CReg*)CN_IIC2_BASE; ICB = &s_IIC2_CB; IntParam = &IntParamset1; break; default: return false; } if(reg->SR1 & I2C_SR1_BTF_MASK) //已经启动传输 { if(reg->SR1 & I2C_SR1_TxE_MASK) //发送中断 { if(!(reg->SR1 & I2C_SR1_RxNE_MASK)) { //从发送缓冲区读一个字节的数据,并发送 if(IIC_PortRead(ICB,&ch,1) > 0) { reg->DR = ch; IntParam->TransCount ++;; } else if(IntParam->TransCount == IntParam->TransTotalLen) { Lock_SempPost(IntParam->pDrvPostSemp); __IIC_IntDisable(reg);//关中断 __IIC_GenerateStop(reg); } } else //未收到ACK信号 { IicErrorNo = CN_IIC_POP_NO_ACK_ERR;//调用错处处理API函数 IIC_ErrPop(ICB,IicErrorNo); return 1; } } else //接收中断 { while((IntParam->TransCount < IntParam->TransTotalLen)) { // 最后一个字节master不发ACK,表示读操作终止 if(IntParam->TransCount == IntParam->TransTotalLen - 1) { reg->CR1 &=~ I2C_CR1_ACK_MASK; } while (!(reg->SR1 & I2C_SR1_RxNE_MASK));//等待接收完成 ch = reg->DR; //写数据 IIC_PortWrite(ICB,&ch,1); IntParam->TransCount ++; } if((IntParam->TransCount == IntParam->TransTotalLen) && (reg->SR1 & I2C_SR1_BTF_MASK)) { __IIC_GenerateStop(reg); __IIC_IntDisable(reg);//关中断 Lock_SempPost(IntParam->pDrvPostSemp);//释放总线信号量 } } } else//未启动通信 { if(reg->SR1 & I2C_SR1_ARLO_MASK)//仲裁丢失中断 { reg->SR1 &= ~I2C_SR1_ARLO_MASK;//清除仲裁丢失中断标志位 IicErrorNo = CN_IIC_POP_MAL_LOST_ERR; IIC_ErrPop(ICB,IicErrorNo); } } return true; }