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

前言

现在手里负责的一个项目需要用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");
}
  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
stm8si2c程序,调试通过 INTERRUPT_HANDLER(I2C_IRQHandler, 19) { /* In order to detect unexpected events during development, it is recommended to set a breakpoint on the following instruction. */ struct SCB_T *system=&system_process; unsigned char i,i2c_sr1,i2c_sr2,i2c_event,i2c__status=0,temp,sr1_analysis_int_resource[8],sr2_analysis_int_resource[8]; char i2c_interrupt_type=0,p;//在一次I2中断中,I2C中断中的中断标志位个数; disableInterrupts();//关总中断 i2c_sr1=I2C->SR1; p=I2C->SR3; i2c_sr2=I2C->SR2; //temp=I2C->SR3; //analysis interrupt resource in i2c->sr1 register sr1_analysis_int_resource[0]=i2c_sr1&I2C_SR1_SB; sr1_analysis_int_resource[1]=i2c_sr1&I2C_SR1_ADDR; sr1_analysis_int_resource[2]=i2c_sr1&I2C_SR1_BTF; sr1_analysis_int_resource[3]=i2c_sr1&I2C_SR1_ADD10; sr1_analysis_int_resource[4]=i2c_sr1&I2C_SR1_STOPF; // sr1_i2c__state[5]=i2c_state&((u8)I2C_SR1_BIT6); sr1_analysis_int_resource[6]=i2c_sr1&I2C_SR1_RXNE; sr1_analysis_int_resource[7]=i2c_sr1&I2C_SR1_TXE; //analysis interrupt resource in i2c->sr2 register sr2_analysis_int_resource[0]=i2c_sr2&I2C_SR2_BERR; sr2_analysis_int_resource[1]=i2c_sr2&I2C_SR2_ARLO; sr2_analysis_int_resource[2]=i2c_sr2&I2C_SR2_AF; sr2_analysis_int_resource[3]=i2c_sr2&I2C_SR2_OVR; sr2_analysis_int_resource[5]=i2c_sr2&I2C_SR2_WUFH; if(sr1_analysis_int_resource[0]==I2C_SR1_SB) {i2c__status=0x01;i2c_interrupt_type++;} if(sr1_analysis_int_resource[1]==I2C_SR1_ADDR) {i2c__status=0x02;i2c_interrupt_type++;} if(sr1_analysis_int_resource[2]==I2C_SR1_BTF) {i2c__status=0x03;i2c_interrupt_type++;} if(sr1_analysis_int_resource[3]==I2C_SR1_ADD10) {i2c__status=0x04;i2c_interrupt_type++;} if(sr1_analysis_int_resource[4]==I2C_SR1_STOPF) {i2c__status=0x05;i2c_interrupt_type++;} if(sr1_analysis_int_resource[6]==I2C_SR1_RXNE) {i2c__status=0x06;i2c_interrupt_type++;} if(sr1_analysis_int_resource[7]==I2C_SR1_TXE) {i2c__status=0x07;i2c_interrupt_type++;} if(sr2_analysis_int_resource[0]==I2C_SR2_BERR) {i2c__status=0x08;i2c_interrupt_type++;} if(sr2_analysis_int_resource[1]==I2C_SR2_ARLO) {i2c__status=0x09;i2c_interrupt_type++;} if(sr2_analysis_int_resource[2]==I2C_SR2_AF) {i2c__status=0x0a;i2c_interrupt_type++;} if(sr2_analysis_int_resource[3]==I2C_SR2_OVR) {i2c__status=0x0b;i2c_interrupt_type++;} if(sr2_analysis_int_resource[5]==I2C_SR2_WUFH) {i2c__status=0x0c;i2c_interrupt_type++;} if(i2c_interrupt_type>=2) /*there are more than one interrupt resource in the time*/ { if(i2c_interrupt_type==2) { if((sr1_analysis_int_resource[1]==I2C_SR1_ADDR)&&(sr1_analysis_int_resource[7]==I2C_SR1_TXE)) { I2C->DR=system->i2c.send_frame.data[system->i2c.send_frame.proc]; system->i2c.send_frame.proc++; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x62; } else if((sr1_analysis_int_resource[7]==I2C_SR1_TXE)&&(sr1_analysis_int_resource[2]==I2C_SR1_BTF)) { system->i2c.send_frame.terminate=0; //set I2C transfer terminate bit; system->i2c.send_frame.mod=0; system->i2c.send_frame.write=0; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x64; } else if((sr1_analysis_int_resource[7]==I2C_SR1_TXE)&&(sr2_analysis_int_resource[2]==I2C_SR2_AF)) { I2C->CR2|=I2C_CR2_STOP; I2C->SR2&=(~I2C_SR2_AF);//clear AF bit; system->i2c.error=1; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x64; } else { system->i2c.error=1; I2C_ITConfig(I2C_IT_EVT, DISABLE); system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x37; } } else { system->i2c.error=1; I2C_ITConfig(I2C_IT_EVT, DISABLE); system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x37; } } else { switch(i2c__status) { case I2C_SR1_SB_proc: //如果是发送模式 if(system->i2c.send_frame.mod==1)//说明本次中断之前是从模式,说明这是在从模式下发的起始位; { //EV5 p=I2C->SR1; I2C->DR=system->i2c.send_frame.add__L; //自动清除I2C_SR1_SB标志 system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x38; } else { if(system->i2c.rev_frame.mod==1) //说明本次中断之间是主模式,这次发的是重复起始位; { //EV6如果是接收模式 p=I2C->SR1; I2C->DR=system->i2c.rev_frame.add__L;//自动清除I2C_SR1_SB标志; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x51; } else { system->i2c.error=1; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x36; } } break; case I2C_SR1_ADDR_proc: p=I2C->SR1; temp=I2C->SR3;//软件读取SR1寄存器后,对SR3寄存器的读操作将清除该位 temp&=(u8)I2C_SR3_TRA; I2C->CR2|=(u8)I2C_CR2_ACK;// 使能应答位 I2C->CR2&=(u8)(~I2C_CR2_POS);//设置接受到当字节应答 //如果是发送模式 if(system->i2c.send_frame.mod==1) { if(temp==(u8)I2C_SR3_TRA) {; } else { system->i2c.error=1; } } else { if(system->i2c.rev_frame.mod==1) { if(temp==0)//machine at a master-receive mod { system->i2c.rev_frame.proc=0; } else { system->i2c.error=1; } } else { system->i2c.error=1; } } system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x52; break; case I2C_SR1_RXNE_proc: if(system->i2c.rev_frame.proci2c.rev_frame.num-3)) { system->i2c.rev_frame.data[system->i2c.rev_frame.proc]=I2C->DR; system->i2c.rev_frame.proc++; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x57; } else if(system->i2c.rev_frame.proc==(u8)(system->i2c.rev_frame.num-2)) { system->i2c.rev_frame.data[system->i2c.rev_frame.proc]=I2C->DR; system->i2c.rev_frame.proc++; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x58; I2C->CR2&=(u8)(~I2C_CR2_ACK);//不返回应答 I2C->CR2|=I2C_CR2_STOP; //发停止位结束这次数据接收; } else if(system->i2c.rev_frame.proc>=(u8)(system->i2c.rev_frame.num-1)) { system->i2c.rev_frame.data[system->i2c.rev_frame.proc]=I2C->DR; system->i2c.rev_frame.proc++; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x59; system->i2c.rev_frame.terminate=0; //set I2C transfer terminate bit; system->i2c.rev_frame.mod=0; system->i2c.rev_frame.read=0; } else { system->i2c.error=1; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0xfb; } break; case I2C_SR1_TXE_proc: if(system->i2c.send_frame.proci2c.send_frame.num-1)) { I2C->DR=system->i2c.send_frame.data[system->i2c.send_frame.proc]; system->i2c.send_frame.proc++; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x61; } else if(system->i2c.send_frame.proc=(u8)(system->i2c.send_frame.num)) { I2C->CR2|=I2C_CR2_STOP; // 发停止位结束 这次数据接收I2C_ITConfig(I2C_IT_BUF, DISABLE); system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x60; } else { system->i2c.error=1; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0xfc; } break; case I2C_SR2_AF_proc: I2C->CR2|=I2C_CR2_STOP; I2C->SR2&=(~I2C_SR2_AF);//clear AF bit; system->i2c.error=1; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x63; break; default: system->i2c.error=1; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0xfd; break; } } system->i2c.int_debug_count++; enableInterrupts();//开总中断 }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Enosji

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值