前言
现在手里负责的一个项目需要用i2c和主芯片进行通信主动发送,中断接收,这就需要支持i2c主机模式和从机模式,先查看原理图
这里我们用到了两条i2c总线进行数据的交替传输,避免在使用一条总线是发送数据和接收数据冲突
初始化i2c控制器
s32_k i2cDevInit(u8 byBusId, TI2cBus *pTI2cBus)
{
//PCLK = 36000000
BOOL retFlg = FALSE;
int I2xSCL = pTI2cBus->byFastMode ? (/*0x2D*/400000) : (/*0xB4*/100000);
u8 I2cadd = gDeviceAddr;
switch(byBusId)
{
case I2C_BUS_STD0:
gpio_af_set(GPIOB, GPIO_AF_4, GPIO_PIN_8 | GPIO_PIN_9); /* 将引脚复用为i2c */
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_8 | GPIO_PIN_9); /* 上拉引脚 */
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_8 | GPIO_PIN_9); //配置引脚为开漏模式
rcu_periph_clock_enable(RCU_I2C0);
i2c_clock_config(I2C0, I2xSCL, I2C_DTCY_2);
i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, i2cGetDevAddr()); //这里的最后一个参数就是i2c作为从片的地址
i2c_enable(I2C0);
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
#if 1
nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3); //配置中断到时候接收是靠中断接收
nvic_irq_enable(I2C0_EV_IRQn, 0, 3);
i2c_interrupt_enable(I2C0, I2C_INT_EV);
i2c_interrupt_enable(I2C0, I2C_INT_ERR);
i2c_interrupt_enable(I2C0, I2C_INT_BUF);
#endif
i2cStructObj[I2C_BUS_STD0].ptRingBuf = pTI2cBus->ptRingBuf;
retFlg = TRUE;
break;
case I2C_BUS_STD1:
gpio_af_set(GPIOF, GPIO_AF_4, GPIO_PIN_0 | GPIO_PIN_1);
gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1);
gpio_output_options_set(GPIOF, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1);
rcu_periph_clock_enable(RCU_I2C1);
i2c_clock_config(I2C1, I2xSCL, I2C_DTCY_2);
i2c_mode_addr_config(I2C1, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, i2cGetDevAddr());
i2c_enable(I2C1);
i2c_ack_config(I2C1, I2C_ACK_ENABLE);
#if 1
nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
nvic_irq_enable(I2C1_EV_IRQn, 0, 2);
i2c_interrupt_enable(I2C1, I2C_INT_EV);
i2c_interrupt_enable(I2C1, I2C_INT_ERR);
i2c_interrupt_enable(I2C1, I2C_INT_BUF);
#endif
i2cStructObj[I2C_BUS_STD1].ptRingBuf = pTI2cBus->ptRingBuf;
retFlg = TRUE;
break;
case I2C_BUS_STD2:
gpio_af_set(GPIOC, GPIO_AF_4, GPIO_PIN_9);
gpio_af_set(GPIOA, GPIO_AF_4, GPIO_PIN_8);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_8);
gpio_output_options_set(GPIOC, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
gpio_output_options_set(GPIOA, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
rcu_periph_clock_enable(RCU_I2C2);
i2c_clock_config(I2C2, I2xSCL, I2C_DTCY_2);
i2c_mode_addr_config(I2C2, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, i2cGetDevAddr());
i2c_enable(I2C2);
i2c_ack_config(I2C2, I2C_ACK_ENABLE);
i2cStructObj[I2C_BUS_STD2].ptRingBuf = pTI2cBus->ptRingBuf;
retFlg = TRUE;
break;
default:
retFlg = FALSE;
break;
}
}
编写i2c作为主机的收发函数
BOOL i2cTransfer(u8 byBusId, u8 slaveAddr, u8 *pWrite, u16 WLen, u8 *pData, u16 dataLen)
{
u32 dwTemp = 0;
BOOL bTimeOutFlg = 0;
u32 times=5;
u32 I2Cid = 0;
switch(byBusId)
{
case I2C_BUS_STD0:
I2Cid = I2C0;
break;
case I2C_BUS_STD1:
I2Cid = I2C1;
break;
case I2C_BUS_STD2:
I2Cid = I2C2;
break;
default:
break;
}
/* disable i2c interrupt */
if (I2Cid == I2C0 || I2Cid == I2C1)
{
i2c_interrupt_disable(I2Cid, I2C_INT_EV);
i2c_interrupt_disable(I2Cid, I2C_INT_ERR);
i2c_interrupt_disable(I2Cid, I2C_INT_BUF);
}
if(byBusId >= I2C_BUS_MAX_NUM)
{
//Printf("%d: bus%d slaveAddr:%d error\r\n", __LINE__, byBusId, slaveAddr);
return FALSE;
}
while(i2cStructObj[byBusId].masterSendFlg != 0)
{
mdelay(10);
if(times-- == 0)
{
//Printf("%d: bus%d slaveAddr:%d error masterSendFlg\r\n", __LINE__, byBusId, slaveAddr, i2cStructObj[byBusId].masterSendFlg);
i2cStructObj[byBusId].masterSendFlg = 0;
break;
}
}
i2cStructObj[byBusId].slaveAddr = (slaveAddr << 1);
if(pWrite != 0)//有数据要写
{
if(dataLen != 0)//有数据要读,先写后读型
{
i2cStructObj[byBusId].terminator = 1;
}
else//只写不读型
{
i2cStructObj[byBusId].terminator = 0;
}
}
else
{
if(dataLen != 0)//只读不写型
{
i2cStructObj[byBusId].terminator = 2;
}
else// 不读不写型
{
// Printf("%d: bus%d slaveAddr:%d error\r\n", __LINE__, byBusId, slaveAddr);
return FALSE;
}
}
i2cStructObj[byBusId].retryCnt = 3;
i2cStructObj[byBusId].pDataBuf = pWrite;
i2cStructObj[byBusId].dataLen = WLen;
i2cStructObj[byBusId].writeIndex = 0;
i2cStructObj[byBusId].pReadBuf = pData;
i2cStructObj[byBusId].readLen = dataLen;
i2cStructObj[byBusId].readIndex = 0;
i2cStructObj[byBusId].masterSendFlg = 1;
i2cStructObj[byBusId].end = 0;
//*i2cStructObj[byBusId].pI2xCONSET = I2CONSET_STA;
dwTemp = TIME_MSEC;
i2c_start_on_bus(I2Cid);
while(!i2c_flag_get(I2Cid, I2C_FLAG_SBSEND));
if(i2cStructObj[byBusId].terminator == 2)//只读不写
{
i2c_master_addressing(I2Cid, i2cStructObj[byBusId].slaveAddr | 1, I2C_TRANSMITTER);
}
else//包含写操作(只写,先写后读)
{
i2c_master_addressing(I2Cid, i2cStructObj[byBusId].slaveAddr, I2C_TRANSMITTER);
while(!i2c_flag_get(I2Cid, I2C_FLAG_ADDSEND)); /* 等待从机地址发送完成 */
i2c_flag_clear(I2Cid, I2C_FLAG_ADDSEND); /* 清除从机地址发送完成标志位 */
while(i2cStructObj[byBusId].writeIndex < i2cStructObj[byBusId].dataLen)
{
while(!i2c_flag_get(I2Cid, I2C_FLAG_TBE));
i2c_data_transmit(I2Cid, i2cStructObj[byBusId].pDataBuf[i2cStructObj[byBusId].writeIndex++]); /* 如果是读寄存器地址的话这里已经告诉从片你需要读的寄存器地址 */
}
while(!i2c_flag_get(I2Cid, I2C_FLAG_TBE));
}
if(i2cStructObj[byBusId].terminator == 1 || i2cStructObj[byBusId].terminator == 2)
{
i2c_start_on_bus(I2Cid); /* 再次发送一个起始位到I2C总线 */
while(!i2c_flag_get(I2Cid, I2C_FLAG_SBSEND));
i2c_master_addressing(I2Cid, i2cStructObj[byBusId].slaveAddr | 1, I2C_RECEIVER);
while(!i2c_flag_get(I2Cid, I2C_FLAG_ADDSEND));
i2c_flag_clear(I2Cid, I2C_FLAG_ADDSEND);
while(i2cStructObj[byBusId].readIndex < i2cStructObj[byBusId].readLen)
{
if(i2cStructObj[byBusId].readLen - i2cStructObj[byBusId].readIndex == 1)
{
i2c_ack_config(I2Cid, I2C_ACK_DISABLE);
}
while(!i2c_flag_get(I2Cid, I2C_FLAG_RBNE));
i2cStructObj[byBusId].pReadBuf[i2cStructObj[byBusId].readIndex++] = i2c_data_receive(I2Cid);
//i2c_ack_config(I2Cid, I2C_ACK_ENABLE);
}
i2c_ack_config(I2Cid, I2C_ACK_ENABLE);
i2c_ackpos_config(I2Cid, I2C_ACKPOS_CURRENT);
}
i2c_stop_on_bus(I2Cid);
i2cStructObj[byBusId].masterSendFlg = 0;// 数据发送完毕==============================
i2cStructObj[byBusId].end = 1;
if(I2Cid == I2C1 || I2Cid == I2C0)
{
i2c_interrupt_enable(I2Cid, I2C_INT_EV);
i2c_interrupt_enable(I2Cid, I2C_INT_ERR);
i2c_interrupt_enable(I2Cid, I2C_INT_BUF);
}
}
编写作为从机的中断接收函数
void I2C0_EV_IRQHandler (void)
{
//Printf("enter 1 irq\r\n");
interruptHandler(I2C_BUS_STD0);
//VICVectAddr = 0; /* Acknowledge Interrupt */
}
void I2C1_EV_IRQHandler (void)
{
//Printf("enter 1 irq\r\n");
interruptHandler(I2C_BUS_STD1);
//VICVectAddr = 0; /* Acknowledge Interrupt */
}
void interruptHandler(u8 byBusId)
{
u32 I2Cid = 0;
switch(byBusId)
{
case I2C_BUS_STD0:
I2Cid = I2C0;
break;
case I2C_BUS_STD1:
I2Cid = I2C1;
break;
case I2C_BUS_STD2:
I2Cid = I2C2;
break;
default:
break;
}
if(i2cStructObj[byBusId].masterSendFlg == 0)
{
//Printf("slave reciver------- \r\n");
/* 中断接收主机发送的数据 */
if (i2c_flag_get(I2Cid, I2C_FLAG_ADDSEND)) /* 收到地址请求 */
{
i2c_flag_clear(I2Cid, I2C_FLAG_ADDSEND);
}
else if (i2c_flag_get(I2Cid, I2C_FLAG_RBNE)) /* 收到主机写入有2个可能,写地址/写数据. */
{
/*数据读取*/
if(i2cStructObj[byBusId].ptRingBuf)
{
i2cStructObj[byBusId].ptRingBuf = i2c_data_receive(I2Cid);
}
else
{
u8 temp = i2c_data_receive(I2Cid);
}
//i2c_ack_config(I2Cid, I2C_ACK_ENABLE);
}
else if (i2c_flag_get(I2Cid, I2C_FLAG_STPDET))
{
if(i2cStructObj[byBusId].ptRingBuf)
{
RingBufferWriteOne(i2cStructObj[byBusId].ptRingBuf, 0xFF);
}
i2c_enable(I2Cid);
}
else if (i2c_flag_get(I2C0, I2C_FLAG_AERR))
{
i2c_stop_on_bus(I2Cid);
}
//i2c_ack_config(I2Cid, I2C_ACK_ENABLE);
}
//Printf("stop------------\r\n");
}
版权声明:本文为Enosji原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。