芯旺微chipon KF32A156系列 IIC(I2C)模块的基本使用

本文免费开放,也请尊重原创,转载需注明源出处!!!

芯旺微chipon KF32A156系列 IIC(I2C)模块的基本使用

我们在实际的使用过程中,IIC也是较为常用的通讯方式,像eepron,传感器等会使用到这种通讯方式。
当然啦,很多工程师也会喜欢使用IO口模拟IIC来做通讯,毕竟很多片子的IIC真的很不好用,而且这个IO口模拟的方式可移植性也是比较强,开源的代码也比较多,本文章主要是说说芯旺微CHIPON156型号的硬件IIC外设,以供参考。

**本次主要讲解IIC外设的使用,文章使用中断收发的方式来对芯旺微32位机的KF32A156系列配置为主机、从机进行讲解。**本篇幅较长,需要耐心看完。
如有需要工程代码,还请私聊留下联系方式邮箱等。本文主要是接口函数代码

主机配置(以7位地址配置讲解)

这里强烈建议,做为主机使用时,尽量使用主循环发送接收的方式,同步通讯,可以不用太担心被其他中断打断导致数据不正确。本次主要在讲解这种方式。

**配置步骤:**老生常谈三步骤

1、配置IO口:将对应的IO口进行重映射模式,并重映射为IIC(iic_sck,iic_sda).本文以PG0和PF15为例,由于demo板没有外部上拉,注意下引脚要配置为开漏模式,并启用内部上拉,程序如下:

void I2c_IO_Init()
{
    GPIO_InitTypeDef GpioConfigPtr;

    /* Configure GPIO remapping function */
    GpioConfigPtr.m_Mode = GPIO_MODE_RMP;
    /* Configyre GPIO open drain output */
    GpioConfigPtr.m_OpenDrain = GPIO_POD_OD;
    /* PG0,SCL */
    GpioConfigPtr.m_Pin = GPIO_PIN_MASK_0;
    /* Configure pull up */
    GpioConfigPtr.m_PullUp = GPIO_PULLUP;
    /* Configure drop down */
    GpioConfigPtr.m_PullDown = GPIO_NOPULL;
    /* Configure PG0 as I2C0 SCL */
    GPIO_Pin_RMP_Config(GPIOG_SFR, GPIO_Pin_Num_0, GPIO_RMP_AF5);

    GPIO_Configuration(GPIOG_SFR, &GpioConfigPtr);

    /* PF15,SDA */
    GpioConfigPtr.m_Pin = GPIO_PIN_MASK_15;

    /* Configure PF15 as I2C0 SDA */
    GPIO_Pin_RMP_Config(GPIOF_SFR, GPIO_Pin_Num_15, GPIO_RMP_AF5);
    GPIO_Configuration(GPIOF_SFR, &GpioConfigPtr);
}

2、配置IIC外设,其实这里可以直接调用官方提供的历程里面的库即可。这里我也并未做修改,直接拿过来使用,配置为主机,波特率接近400k,程序如下:

void I2c_Init(I2C_SFRmap *I2cx)
{
    I2C_InitTypeDef I2cConfigPtr;

    /* I2c mode */
    I2cConfigPtr.m_Mode = I2C_MODE_I2C;
    /* I2c clock */
    I2cConfigPtr.m_ClockSource = I2C_CLK_SCLK;
/* Configure slave address width */
    I2cConfigPtr.m_BADR10 = I2C_BUFRADDRESS_7BIT;
    /* SMBus type */
    I2cConfigPtr.m_MasterSlave = I2C_MODE_SMBUSHOST;
    /* I2c baud rate low level time */
    I2cConfigPtr.m_BaudRateL = 115;
    /* I2c baud rate high level time */
    I2cConfigPtr.m_BaudRateH = 115;
    /* Enable ACK */
    I2cConfigPtr.m_AckEn = TRUE;
    /* Select the response signal as ACK */
    I2cConfigPtr.m_AckData = I2C_ACKDATA_ACK;

    I2C_Reset(I2cx);
    /* Configue I2C */
    I2C_Configuration(I2cx, &I2cConfigPtr);

    //    /* Enable I2C HW module */
    I2C_Cmd(I2cx, TRUE);
    /* Clear Interrupt flag */
    I2C_Clear_INTERRUPT_Flag(I2cx);

    /* Enable I2C address match */
    I2C_MATCH_ADDRESS_Config(I2cx, TRUE);

    /* Enable I2C HW module */
    I2C_Cmd(I2cx, TRUE);
}

3、配置中断。由于主机这里推荐使用循环里面跑接收发送,所以中断暂无配置。

主机发送函数:就是主机对从机写

写的流程就是 :发送起始位 – 地址(最后一位为0) – 数据 – 停止位
这里面注意的是,有时候等待ISIF会卡死,这里可能是因为未释放总线或者有干扰之类,导致数据或者起始停止位发送失败了。所以,本次提供的东西也是进行了超时处理,同时数据手册说是会硬件清除起始位和停止位,但是为了安全起见,我依然是进行了软件清除,这样也许更加保险。

在这里插入图片描述
在这里插入图片描述

代码如下:

IIC_SEND_TypeDef I2C_Buffer_write(uint16_t Write_i2c_Addr,uint8_t *p_buffer,uint16_t number_of_byte)
{
//	volatile uint32_t j;
	volatile uint16_t   u16TickCount = 0;

	I2C_Choose=I2C0_SFR;//选择I2C0_SFR I2C1_SFR

	I2C_Cmd(I2C_Choose,TRUE);               //使能I2C模块
	/*起始位*/
	//使能后延迟一会
	asm("NOP");
	asm("NOP");
	asm("NOP");
	asm("NOP");
	asm("NOP");
	asm("NOP");
	asm("NOP");
	asm("NOP");
	I2C_Clear_INTERRUPT_Flag(I2C_Choose);   //清I2C中断标志位ISIF位
	I2C_Generate_START(I2C_Choose,TRUE);    //使能起始信号
	Iic_Test_Flag=1;

	//等待isif标志位
	wait_cnt = 0;
	while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)) //等待起始信号稳定
		{
			if(wait_cnt++ > IIC_TIMOUT){
				Iic_error_Flag = 1 ;
				break;
			}
		}

//清掉起始信号
	I2C_Generate_START(I2C_Choose,FALSE);    //使能起始信号
	I2C_Clear_Start_Flag (I2C_Choose);
	Iic_Test_Flag=2;

#if IIC_10BIT_Address
	static uint8_t I2C_SLAVE_ADDRESS10BH=0;
	static uint8_t I2C_SLAVE_ADDRESS10BL=0;
	I2C_SLAVE_ADDRESS10BL=Write_i2c_Addr& 0xff;       //低8位I2C地址
	I2C_SLAVE_ADDRESS10BH=(Write_i2c_Addr>>8)& 0xff;  //高8位I2C地址


	/*发送从机10位高位地址*/
	I2C_SendData(I2C_Choose,I2C_SLAVE_ADDRESS10BH); //发送从机地址  I2C_SLAVE_ADDRESS10BH_W
	I2C_Clear_INTERRUPT_Flag(I2C_Choose);        //清I2C中断标志位ISIF位
	while(!I2C_Get_INTERRUPT_Flag(I2C_Choose));  //等待发送完成

	/*发送从机10位低位地址*/
	I2C_SendData(I2C_Choose,I2C_SLAVE_ADDRESS10BL); //发送从机地址  I2C_SLAVE_ADDRESS10BH_W
	I2C_Clear_INTERRUPT_Flag(I2C_Choose);        //清I2C中断标志位ISIF位
	while(!I2C_Get_INTERRUPT_Flag(I2C_Choose));  //等待发送完成
	while(I2C_Get_Ack_Fail_Flag(I2C_Choose));    //判断是否有ACK应答,如没有则停止,如果有则继续发


#else
	/*发送7位从机地址*/
	I2C_SendData8(I2C_Choose,Write_i2c_Addr); //发送从机地址  I2C_SLAVE_ADDRESS10BH_W
	I2C_Clear_INTERRUPT_Flag(I2C_Choose);        //清I2C中断标志位ISIF位
	//等待isif标志位
	wait_cnt = 0;
	while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)) //等待起始信号稳定
		{
			if(wait_cnt++ > IIC_TIMOUT){
				Iic_error_Flag = 1 ;
				break;
			}
		}
//nACK处理
	wait_cnt = 0;
	while(I2C_Get_Ack_Fail_Flag(I2C_Choose))   //判断是否有ACK应答,如没有则停止,如果有则继续发
		{
			if(wait_cnt++ > IIC_TIMOUT){
				Iic_ack_error_Flag = 1 ;
				break;
				}
		}
//应答错误或者ISIF超时处理
	if((Iic_ack_error_Flag==1) || (Iic_error_Flag == 1))
	{
		I2C_Clear_Ack_Fail_Flag (I2C_Choose);
		Iic_ack_error_Flag = 0 ;
		Iic_error_Flag = 0;
		I2C_Generate_STOP(I2C_Choose,TRUE);         //使能停止信号
		I2C_Clear_INTERRUPT_Flag(I2C_Choose);       //清I2C中断标志位ISIF位
		wait_cnt = 0;
		while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)) //等待起始信号稳定
			{
				if(wait_cnt++ > IIC_TIMOUT){
//					Iic_error_Flag = 1 ;
					break;
				}
			}
		I2C_Generate_STOP(I2C_Choose,FALSE);         //使能停止信号
		I2C_Clear_INTERRUPT_Flag(I2C_Choose);       //清I2C中断标志位ISIF位
		I2C_Clear_Stop_Flag(I2C_Choose);            //清I2C停止标志位PIF位
		I2C_Cmd(I2C_Choose,FALSE);                  //关闭I2C模组
	return IIC_SEND_ERROR;
	}
//	以上为nack,isif不置位处理

#endif


    /*循环写数据 */
    while(number_of_byte--)
    {
    	I2C_SendData8(I2C_Choose, *p_buffer);    //发送数据
    	I2C_Clear_INTERRUPT_Flag(I2C_Choose);     	//清I2C中断标志位ISIF位
        /* 指向下一个要写的字节*/
        p_buffer++;
//        j=0xFFFFFF;    //测试使用
//        GPIOD_SFR->POR |= (uint32_t)GPIO_PIN_MASK_5 ;    //测试使用
        Iic_Test_Flag=3;
        wait_cnt = 0;
        while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)) //等待释放总线
			{
				if(wait_cnt++ > IIC_TIMOUT){
					Iic_error_Flag = 1 ;
					break;
				}
			}
        //nACK处理
		wait_cnt = 0;
		while(I2C_Get_Ack_Fail_Flag(I2C_Choose))   //判断是否有ACK应答,如没有则停止,如果有则继续发
			{
				if(wait_cnt++ > IIC_TIMOUT){
					Iic_ack_error_Flag = 1 ;
					break;
					}
			}
		if((Iic_ack_error_Flag==1) || (Iic_error_Flag == 1))
		{
			I2C_Clear_Ack_Fail_Flag (I2C_Choose);
			Iic_ack_error_Flag = 0 ;
			Iic_error_Flag = 0;
			I2C_Generate_STOP(I2C_Choose,TRUE);         //使能停止信号
			I2C_Clear_INTERRUPT_Flag(I2C_Choose);       //清I2C中断标志位ISIF位
			wait_cnt = 0;
			while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)) //等待起始信号稳定
				{
					if(wait_cnt++ > IIC_TIMOUT){
//						Iic_error_Flag = 1 ;
						break;
					}
				}
			I2C_Generate_STOP(I2C_Choose,FALSE);         //使能停止信号
			I2C_Clear_INTERRUPT_Flag(I2C_Choose);       //清I2C中断标志位ISIF位
			I2C_Clear_Stop_Flag(I2C_Choose);            //清I2C停止标志位PIF位
			I2C_Cmd(I2C_Choose,FALSE);                  //关闭I2C模组
		return IIC_SEND_ERROR;
		}
        //	以上为nack,isif不置位处理
        Iic_Test_Flag=4;
    }

	/*停止位*/
    asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");
	I2C_Generate_STOP(I2C_Choose,TRUE);         //使能停止信号
	Iic_Test_Flag=5;
	I2C_Clear_INTERRUPT_Flag(I2C_Choose);       //清I2C中断标志位ISIF位
	Iic_Test_Flag=6;
	wait_cnt = 0;
	while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)) //等待起始信号稳定
			{
				if(wait_cnt++ > IIC_TIMOUT){
					Iic_error_Flag = 1 ;
					break;
				}
			}
	if(Iic_error_Flag == 1)
	{
		Iic_error_Flag = 0;
		return IIC_SEND_ERROR ;
	}
	Iic_Test_Flag=7;
	I2C_Generate_STOP(I2C_Choose,FALSE);         //使能停止信号
	I2C_Clear_INTERRUPT_Flag(I2C_Choose);       //清I2C中断标志位ISIF位
	Iic_Test_Flag=8;
	I2C_Clear_Stop_Flag(I2C_Choose);            //清I2C停止标志位PIF位
	Iic_Test_Flag=9;
	I2C_Cmd(I2C_Choose,FALSE);                  //关闭I2C模组
	return IIC_SEND_OK;
}

主机接收函数:就是主机对从机读

写的流程就是 :发送起始位 – 地址(最后一位为1) – 数据(最后一个字节回NACK) – 停止位
同样的函数里面也是做了超时处理,以及对最后一个字节的数据进行NACK的回复操作。
在这里插入图片描述

程序如下:

IIC_SEND_TypeDef I2C_Buffer_read(uint16_t Read_I2C_Addr, uint8_t *p_buffer, uint16_t number_of_byte)
{
	if(number_of_byte == 1)
	{
		I2C_Ack_DATA_Config(I2C_Choose, I2C_ACKDATA_NO_ACK);
	}

    I2C_Choose = I2C0_SFR;
    static uint8_t I2C_SLAVE_ADDRESS10BH = 0;
    static uint8_t I2C_SLAVE_ADDRESS10BL = 0;

    /* Enable I2C HW module*/
    I2C_Cmd(I2C_Choose, TRUE);
		asm("NOP");
		asm("NOP");
		asm("NOP");
		asm("NOP");
		asm("NOP");
		asm("NOP");
		asm("NOP");
		asm("NOP");

	
    /* Clear interrupt flag ISIF */
    I2C_Clear_INTERRUPT_Flag(I2C_Choose);
    /* Start bit */
    I2C_Generate_START(I2C_Choose, TRUE);
    /* Wait for the start signal to stabilize */
    read_wait_cnt = 0;
	while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)) //获取isif标志位
	{
		if(read_wait_cnt++ > IIC_TIMOUT){
			read_Iic_error_Flag = 1 ;
			break;
		}
	}
	I2C_Generate_START(I2C_Choose,FALSE);    //失能起始位
	I2C_Clear_Start_Flag (I2C_Choose);

#if (I2C_ADDRESS_WIDTH == I2C_10BIT)
    /* Low 8 bit register address */
    I2C_SLAVE_ADDRESS10BL = Read_I2C_Addr& 0xff;
    /* High bit address */
    I2C_SLAVE_ADDRESS10BH = (Read_I2C_Addr>> 8) & 0xff;
    /* Send slave address */
    I2C_SendData(I2C_Choose, I2C_SLAVE_ADDRESS10BH | 0x01);
    /* Clear the ISIF bit of the I2C interrupt flag */
    I2C_Clear_INTERRUPT_Flag(I2C_Choose);
    /* Wait for sending to complete */
    while (!I2C_Get_INTERRUPT_Flag(I2C_Choose))
        ;

    /* Send slave 10-bit low address */
    I2C_SendData(I2C_Choose, I2C_SLAVE_ADDRESS10BL);
    /* Clear the ISIF bit of the I2C interrupt flag */
    I2C_Clear_INTERRUPT_Flag(I2C_Choose);
    /* Wait for sending to complete */
    while (!I2C_Get_INTERRUPT_Flag(I2C_Choose))
        ;
    /* Determine whether there is an ACK response, if not, stop, if there is, continue to send */
    while (I2C_Get_Ack_Fail_Flag(I2C_Choose))
        ;

#else
    /* Send 7-bit slave address */
    I2C_SendData8(I2C_Choose, Read_I2C_Addr | 0x01);
    /* Clear the ISIF bit of the I2C interrupt flag */
    I2C_Clear_INTERRUPT_Flag(I2C_Choose);
    /* Wait for sending to complete */
    read_wait_cnt = 0;
	while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)) //获取isif标志位
	{
		if(read_wait_cnt++ > IIC_TIMOUT){
			read_Iic_error_Flag = 1 ;
			break;
		}
	}
    /* Determine whether there is an ACK response, if not, stop, if there is, continue to send */
    //nACK处理
	read_wait_cnt = 0;
	while(I2C_Get_Ack_Fail_Flag(I2C_Choose))   //获取ack失败标志位
	{
		if(read_wait_cnt++ > IIC_TIMOUT){
			read_Iic_ack_error_Flag = 1 ;
			break;
			}
	}
//ISIF和ack有任意失败的情况下
	if((read_Iic_ack_error_Flag==1) || (read_Iic_error_Flag == 1))
	{
		I2C_Clear_Ack_Fail_Flag (I2C_Choose);
		read_Iic_ack_error_Flag = 0 ;
		read_Iic_error_Flag = 0;
		I2C_Generate_STOP(I2C_Choose,TRUE);         //启动停止位
		I2C_Clear_INTERRUPT_Flag(I2C_Choose);       //清除isif标志位
		read_wait_cnt = 0;
		while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)) //获取isif标志位
			{
				if(read_wait_cnt++ > IIC_TIMOUT){
//					read_Iic_error_Flag = 1 ;
					break;
				}
			}
		I2C_Generate_STOP(I2C_Choose,FALSE);         //失能停止位
		I2C_Clear_INTERRUPT_Flag(I2C_Choose);       //获取isif标志位
		I2C_Clear_Stop_Flag(I2C_Choose);            //清除stop标志位
		I2C_Cmd(I2C_Choose,FALSE);                  //失能iic模块
	return IIC_SEND_ERROR;
	}
#endif

    /* Send read command */
    /* Send slave address and read operation */
    //I2C_SendData8(I2C_Choose, Read_I2C_Addr);
    /* Clear the ISIF bit of the I2C interrupt flag */
   // I2C_Clear_INTERRUPT_Flag(I2C_Choose);

    /* Wait for sending to complete */
    //while (!I2C_Get_INTERRUPT_Flag(I2C_Choose))
        ;
    /* Clear the ISIF bit of the I2C interrupt flag */
    I2C_Clear_INTERRUPT_Flag(I2C_Choose);

    while (number_of_byte)
    {

        /* Wait for sending to complete */
    	read_wait_cnt = 0;
    	while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)) //获取isif标志位
    		{
    			if(read_wait_cnt++ > IIC_TIMOUT){
    				read_Iic_error_Flag = 1 ;
    				break;
    			}
    		}

    	if((read_Iic_error_Flag == 1))
    		{
//    			I2C_Clear_Ack_Fail_Flag (I2C_Choose);
//    			read_Iic_ack_error_Flag = 0 ;
    			read_Iic_error_Flag = 0;
    			I2C_Generate_STOP(I2C_Choose,TRUE);         //启动停止位
    			I2C_Clear_INTERRUPT_Flag(I2C_Choose);       //清除isif标志位
    			read_wait_cnt = 0;
    			while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)) //获取isif标志位
				{
					if(read_wait_cnt++ > IIC_TIMOUT){
	//					read_Iic_error_Flag = 1 ;
						break;
					}
				}
    			I2C_Generate_STOP(I2C_Choose,FALSE);         //失能停止位
    			I2C_Clear_INTERRUPT_Flag(I2C_Choose);       //获取isif标志位
    			I2C_Clear_Stop_Flag(I2C_Choose);            //清除stop标志位
    			I2C_Cmd(I2C_Choose,FALSE);                  //失能iic模块
    		return IIC_SEND_ERROR;
    		}


        	/* Determine whether the Buff is full */
			if (I2C_Get_Receive_Buff_Flag(I2C_Choose))
			{
				if(number_of_byte <= 1)
				{
					I2C_Ack_DATA_Config(I2C_Choose, I2C_ACKDATA_ACK);

					*p_buffer = I2C_ReceiveData(I2C_Choose);
				}
				else
				{
					I2C_Ack_DATA_Config(I2C_Choose, I2C_ACKDATA_ACK);
					*p_buffer = I2C_ReceiveData(I2C_Choose);
					/* Clear the ISIF bit of the I2C interrupt flag */
					I2C_Clear_INTERRUPT_Flag(I2C_Choose);
					if(number_of_byte <= 2)
					{
						I2C_Ack_DATA_Config(I2C_Choose, I2C_ACKDATA_ACK);
						I2C_Ack_DATA_Config(I2C_Choose, I2C_ACKDATA_NO_ACK);
						*p_buffer = I2C_ReceiveData(I2C_Choose);
					}
					/* Point to the location where the next read byte will be saved */
					p_buffer++;
				}
				/* Reply ACK */


			}

        /* Decrement read byte counter */
			number_of_byte--;
    }

    /* Stop bit */
	asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");

    I2C_Generate_STOP(I2C_Choose, TRUE);
	asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");

    /* Clear the ISIF bit of the I2C interrupt flag */
    I2C_Clear_INTERRUPT_Flag(I2C_Choose);
    /* Wait for the stop to complete */
    read_wait_cnt = 0;
    while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)) //获取isif标志位
	{
		if(read_wait_cnt++ > IIC_TIMOUT){
			read_Iic_error_Flag = 1 ;
			break;
		}
	}
    if(read_Iic_error_Flag == 1)
	{
	I2C_Generate_STOP(I2C_Choose,FALSE);         //失能停止位
	I2C_Clear_INTERRUPT_Flag(I2C_Choose);       //获取isif标志位
	I2C_Clear_Stop_Flag(I2C_Choose);            //清除stop标志位
	I2C_Cmd(I2C_Choose,FALSE);
	read_Iic_error_Flag = 0;
	return IIC_SEND_ERROR ;
	}
    I2C_Generate_STOP(I2C_Choose, FALSE);
    /* Clear the ISIF bit of the I2C interrupt flag */
    I2C_Clear_INTERRUPT_Flag(I2C_Choose);
    /* Clear the I2C stop flag PIF bit */
    I2C_Clear_Stop_Flag(I2C_Choose);
    /* Turn off the I2C module */
    I2C_Cmd(I2C_Choose, FALSE);
    return IIC_SEND_OK ;
}

从机配置(以7位地址配置讲解)

做为从机使用时,由于没有控制权,接收数据的时候为了更加及时,这里建议从机用中断来进行收发。

1、从机配置IO口配置和IIC外设配置不再赘述,基本和主机相同,建议是直接调用例程里面IIC从机的配置接口函数

示意程序如下:

I2c_IO_Init();   //io口初始化
I2c_Init(I2C0_SFR, I2C_SLAVE_ADDR);  //从机iIC外设初始化,第二个参数为从机地址

2、开启中断,建议看起从机的ISIF中断,因为无论哪种位置,都会产生ISIF。再去中段里面判断标志位再处理。

void I2c_Interrupt_Init()
{
    /* Enable I2c receive interrupt */
    INT_Interrupt_Enable(INT_I2C0, TRUE);
    /* Enable I2c interrupt */
    I2C_ISIE_INT_Enable(I2C0_SFR, TRUE);
    INT_All_Enable(TRUE);
}

3、这里主要说一下从机的中断里面的操作
当ISIF置位以后去判断 I2C读/ 写信息状态位状态,如果是写,那直接将数据读出,再进行判断当前是否为数据位,如果是数据位则接收放置数据到软件buff里面。地址读了可直接丢弃 ; 如果是读,那就将数据放置到硬件发送buff里面,清空isif释放总线等待发送成功即可。
程序如下:

void __attribute__((interrupt)) _I2C0_exception(void)
{

    volatile uint32_t I2C0_DATA = 0x11;
    volatile uint8_t I2C0_REDATA = 0;
    volatile uint32_t I2C0_ADD = 0;
    i2c_data_temp = 0;

    /* Clear the I2C0 interrupt flag bit */
//    I2C_Clear_INTERRUPT_Flag(I2C0_SFR);
    /* Reply ACK */


#if (I2C_ADDRESS_WIDTH == I2C_10BIT)
    if (I2C_Get_Write_Read_Flag(I2C0_SFR))
    {
        I2C_SendData(I2C0_SFR, I2C0_DATA);
    }
    else
    {
        if (I2C_Get_HighAddress_Flag(I2C0_SFR))
        { /* High address, skip */
            ;
        }
        else
        { /* Not high address, perform other actions */
            i2c_data_temp = I2C_ReceiveData(I2C0_SFR);
            if (I2C_Get_Data_Flag(I2C0_SFR))
            {
                /* Read data */
                I2C_receive_input(i2c_data_temp);
                I2C0_DATA = i2c_data_temp;
            }
            else
            {
                I2C0_ADD = i2c_data_temp;
                I2C_RecNum = 0;
            }
        }
    }
#else
    if (I2C_Get_Write_Read_Flag(I2C0_SFR))
    { /* The host reads the status bit, and sends from the slave */

        I2C_SendData(I2C0_SFR, I2C0_DATA);
        I2C_Clear_INTERRUPT_Flag(I2C0_SFR);
    }
    else
    {
    	I2C_Clear_INTERRUPT_Flag(I2C0_SFR);
    	/* Host write status bit, slave receive */
    	I2C_Ack_DATA_Config(I2C0_SFR, I2C_ACKDATA_ACK);

        i2c_data_temp = I2C_ReceiveData(I2C0_SFR);

        if (I2C_Get_Data_Flag(I2C0_SFR))
        {

            I2C0_REDATA = i2c_data_temp & 0xff;
            I2C_receive_input(I2C0_REDATA);
        }
        else
        {
            I2C0_ADD = i2c_data_temp;
            I2C_RecNum = 0;
        }
    }
#endif
}

这里再粘贴一下用户手册上的配置步骤
主机发送接收:
在这里插入图片描述
在这里插入图片描述

从机发送:
在这里插入图片描述

从机接收:
在这里插入图片描述

以上基本已经将IIC的主从机配置和发送接收等流程配置完毕,用户可再根据自身需求进行优化。

这里

本次更新时间20230507

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 0.96寸I2C IIC通信128*64 OLED液晶屏模块的原理图是一张用电子元器件和连接线路等表示的图表,用于显示该液晶屏模块的电路连接和工作原理。 在原理图中,可以看到模块的主要组成部分。首先是液晶屏,它是整个模块的显示部分,具有128列和64行的像素点阵,通过I2C IIC通信方式与主控芯片连接。 主控芯片位于模块的核心位置,它负责控制液晶屏的工作,并与外部设备进行通信。主控芯片通过I2C IIC通信总线与其他硬件连接,如外部存储器、传感器等。在原理图中,可以看到主控芯片周围的连接电阻、电容、晶振等元件,这些元件在整个电路中起到支持、稳定等作用。 另外,模块中还包含了电源管理部分,用于提供电压和电流给液晶屏和主控芯片。这部分包括电源开关、稳压电路、滤波电容等。 此外,原理图还显示了模块的连接方式,如I2C IIC通信接口、电源接口、外设连接接口等。这些接口可以连接到外部设备,如单片机、传感器等,实现与其他电子设备的互联。 总体来说,0.96寸I2C IIC通信128*64 OLED液晶屏模块原理图展示了该模块的电路连接和工作原理,帮助开发人员理解模块的组成和功能,为进一步的开发和应用提供参考。 ### 回答2: 0.96寸i2c iic通信128*64 OLED液晶屏模块原理图,通常包含以下主要组成部分:控制芯片、显示面板、I2C接口以及电源电路。 首先,液晶屏模块通常集成了一个控制芯片,这个芯片负责处理从主控制器接收到的显示数据,并将其转化为适合显示的信号。控制芯片通常是通过I2CIIC通信接口与主控制器进行连接。通过这个接口,主控制器可以向液晶屏发送指令和数据,控制显示内容和格式。 其次,液晶屏模块中的显示面板是显示信息的最重要组成部分。这个面板通常由128行和64列的液晶像素点阵组成,每个像素点可以显示不同的颜色和亮度。显示面板是被控制芯片驱动的,根据控制芯片的指令和数据,液晶屏会相应地点亮或熄灭每一个像素点,从而实现显示功能。 此外,I2C接口是液晶屏模块与主控制器之间的通信接口。I2C接口是一种串行通信协议,用于在不同设备之间传送数据。通过I2C接口,主控制器可以向液晶屏模块发送指令、数据和其他控制信号,从而控制液晶屏的显示内容和操作。 最后,液晶屏模块还包含一个电源电路,用于提供液晶屏驱动所需的电源。这个电路通常由电源管理芯片、电容、电阻等组成,确保液晶屏能够正常运行并保持稳定的工作电压和电流。 综上所述,0.96寸i2c iic通信128*64 OLED液晶屏模块原理图主要包含控制芯片、显示面板、I2C接口以及电源电路等组成部分,通过这些部件的协同工作,液晶屏模块能够接收主控制器发送的指令和数据,并在显示面板上显示相应的内容。 ### 回答3: 0.96寸I2C IIC通信128*64 OLED液晶屏模块的原理图是用来描述该模块内部电路连接关系和工作原理的图纸。液晶屏模块主要由屏幕控制芯片、驱动芯片和显示屏组成。 在原理图中,屏幕控制芯片是连接OLED显示屏的主要接口,通过I2CIIC通信协议与外部主控芯片进行通信。该芯片负责接收来自主控芯片的命令和数据,并将其转化为对显示屏的控制信号和图像信号。 驱动芯片是连接显示屏的关键组件,负责将屏幕控制芯片发出的信号转化为驱动显示屏所需的电流和电压信号。驱动芯片还可以控制液晶屏模块的亮度、对比度、颜色等参数,以及完成像素点的颜色变化。 显示屏是液晶屏模块的重要设备,由128行和64列的像素点构成,每个像素点可以显示不同的颜色和亮度。在原理图中,显示屏的每个像素点与驱动芯片通过细丝连接,通过控制电路可以控制每个像素点的亮灭和颜色。 除了以上核心组件,原理图中还可能包含其他辅助电路,例如电源电路、电容电路、电阻电路等。这些辅助电路可以提供所需的电压和电流,确保液晶屏模块正常工作。 总之,0.96寸I2C IIC通信128*64 OLED液晶屏模块的原理图是解释了该模块内部各个电路之间的连接关系和工作原理,为开发人员提供了设计和调试参考。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值