【GD32F407】i2c主机发送,从机中断接收

  • Post author:
  • Post category:其他




前言

现在手里负责的一个项目需要用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 版权协议,转载请附上原文出处链接和本声明。