用极海MCU ARM M0的APM32F03x实现I2C的主从模式的SMBUS通信

1.SMBUS通信协议

1.1 符号含义

S (1 bit) : 起始位
Sr (1 bit) : 重复的起始位
P (1 bit) : 停止位
R/W# (1 bit) : Read/Write bit,读写位
A, N (1 bit) : 应答位
Address(7 bits): 地址位,7 位地址
Command Code (8 bits): 命令字节,一般用来选择芯片内部的寄存器
Data Byte (8 bits): 数据字节,8 位;如果是 16 位数据的话,用 2 个字节来表示。
Count (8 bits): 在 block 操作总,表示数据长度
[…]: 中括号表示 I2C 设备发送的数据,没有中括号表示 主机 发送的数据
#define SLAVEADDR0 0xB0 从机I2C地址

1.2 SMBus Read Byte

先发从机地址,发出芯片内部的寄存器地址,再读数据,读取设备寄存器地址储存的1个字节的数据。
在这里插入图片描述

1.3 SMBus Write Byte

先发从机地址,发出芯片内部的寄存器地址,再写数据,向设备寄存器地址写1个字节的数据。

在这里插入图片描述

2.主从模式SMBUS通信软件实现

2.1 实现架构

在这里插入图片描述

2.2 主I2C2初始化


/*!
 * @brief       I2C Init   
 *
 * @param       None
 *
 * @retval      None
 *
 * @note
 */
 void I2C2Init(void)
 {
    GPIO_Config_T gpioConfigStruct;
    I2C_Config_T i2cConfigStruct;
     /** Enable I2C related Clock */
    RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOB);
    RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_I2C2);
    RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
  
     
     /** Free I2C_SCL and I2C_SDA */
    gpioConfigStruct.mode = GPIO_MODE_OUT;
    gpioConfigStruct.speed = GPIO_SPEED_50MHz;
    gpioConfigStruct.outtype = GPIO_OUT_TYPE_PP;
    gpioConfigStruct.pupd = GPIO_PUPD_NO;
    gpioConfigStruct.pin = GPIO_PIN_10;
    GPIO_Config(GPIOB, &gpioConfigStruct);    
    
    gpioConfigStruct.pin = GPIO_PIN_11;
    GPIO_Config(GPIOB, &gpioConfigStruct); 
    
    GPIO_SetBit(GPIOB,GPIO_PIN_10);
    GPIO_SetBit(GPIOB,GPIO_PIN_11); 
    
    /** Connect I2C to SCL */
    GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_10, GPIO_AF_PIN1);
    /** Connect I2C to SDA */
    GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_11, GPIO_AF_PIN1); 
    /**  Config I2C2 GPIO */
    gpioConfigStruct.mode = GPIO_MODE_AF;
    gpioConfigStruct.speed = GPIO_SPEED_50MHz;
    gpioConfigStruct.outtype = GPIO_OUT_TYPE_OD;
    gpioConfigStruct.pupd = GPIO_PUPD_NO;
    gpioConfigStruct.pin = GPIO_PIN_10;
    GPIO_Config(GPIOB, &gpioConfigStruct);    
    
    gpioConfigStruct.pin = GPIO_PIN_11;
    GPIO_Config(GPIOB, &gpioConfigStruct);

    /**  Config I2C1 */  
    I2C_Reset(I2C2);
    RCM_ConfigI2CCLK(RCM_I2C1CLK_SYSCLK);
    i2cConfigStruct.ack = I2C_ACK_ENABLE;
    i2cConfigStruct.ackaddress = I2C_ACK_ADDRESS_7BIT;
    i2cConfigStruct.address1 = 0xA0;
    i2cConfigStruct.analogfilter = I2C_ANALOG_FILTER_ENABLE;
    i2cConfigStruct.digitalfilter = I2C_DIGITAL_FILTER_0;
    i2cConfigStruct.mode = I2C_MODE_SMBUSHOST;
    i2cConfigStruct.timing = 0xB0420F13;   //100K 48M	//0x1042F013;
    I2C_Config(I2C2,&i2cConfigStruct);
    
    /** Enable the I2C2 Interrupt */ 
    I2C_EnableInterrupt(I2C2,I2C_INT_RXIE|I2C_INT_ADDRIE|I2C_INT_STOPIE);
    
    /** NVIC configuration */   
    NVIC_EnableIRQRequest(I2C2_IRQn,2); 
    
    /** slave configuration*/
    //I2C_EnableSlaveByteControl(I2C2);
    //I2C_EnableReload(I2C2);
    //I2C_EnableStretchClock(I2C2);
  
    /** Enable I2Cx */    
     I2C_Enable(I2C2);
 }
 

2.3 从I2C1初始化

//--------------------------------------------------------------------------------------------------------------------
// @brief       I2CInit   
// @param       None
// @retval      None
// @note
//--------------------------------------------------------------------------------------------------------------------
 void I2CInit(void)
{
	GPIO_Config_T gpioConfigStruct;
	I2C_Config_T i2cConfigStruct;
	/** Enable I2C related Clock */
	RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOB);
	RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_I2C1);
	RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);


	/** Free I2C_SCL and I2C_SDA */
	gpioConfigStruct.mode = GPIO_MODE_OUT;
	gpioConfigStruct.speed = GPIO_SPEED_50MHz;
	gpioConfigStruct.outtype = GPIO_OUT_TYPE_PP;
	gpioConfigStruct.pupd = GPIO_PUPD_NO;
	gpioConfigStruct.pin = GPIO_PIN_6;
	GPIO_Config(GPIOB, &gpioConfigStruct);    

	gpioConfigStruct.pin = GPIO_PIN_7;
	GPIO_Config(GPIOB, &gpioConfigStruct); 

	GPIO_SetBit(GPIOB,GPIO_PIN_6);
	GPIO_SetBit(GPIOB,GPIO_PIN_7); 

	/** Connect I2C to SCL */
	GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_6, GPIO_AF_PIN1);
	/** Connect I2C to SDA */
	GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_7, GPIO_AF_PIN1); 
	/**  Config I2C1 GPIO */
	gpioConfigStruct.mode = GPIO_MODE_AF;
	gpioConfigStruct.speed = GPIO_SPEED_50MHz;
	gpioConfigStruct.outtype = GPIO_OUT_TYPE_OD;
	gpioConfigStruct.pupd = GPIO_PUPD_NO;
	gpioConfigStruct.pin = GPIO_PIN_6;
	GPIO_Config(GPIOB, &gpioConfigStruct);    

	gpioConfigStruct.pin = GPIO_PIN_7;
	GPIO_Config(GPIOB, &gpioConfigStruct);

	/**  Config I2C1 */  
	I2C_Reset(I2C1);
	RCM_ConfigI2CCLK(RCM_I2C1CLK_SYSCLK);
	i2cConfigStruct.ack = I2C_ACK_ENABLE;
	i2cConfigStruct.ackaddress = I2C_ACK_ADDRESS_7BIT;
	i2cConfigStruct.address1 = SLAVEADDR0;	//0xB0;
	i2cConfigStruct.analogfilter = I2C_ANALOG_FILTER_ENABLE;
	i2cConfigStruct.digitalfilter = I2C_DIGITAL_FILTER_0;
	i2cConfigStruct.mode = I2C_MODE_SMBUSDEVICE;
	i2cConfigStruct.timing = 0xB0420F13;   //100K 48M	//0x1042F013;
	I2C_Config(I2C1,&i2cConfigStruct);

	/** Enable the I2C1 Interrupt */ 
	I2C_EnableInterrupt(I2C1,I2C_INT_RXIE|I2C_INT_ADDRIE|I2C_INT_STOPIE);

	/** NVIC configuration */   
	NVIC_EnableIRQRequest(I2C1_IRQn,1); 

	/** slave configuration*/
	//I2C_EnableSlaveByteControl(I2C1);
	//I2C_EnableReload(I2C1);
	//I2C_EnableStretchClock(I2C1);

	/** Enable I2Cx */    
	I2C_Enable(I2C1);   
}

2.4 I2C主器件主动读写操作处理过程

//----------------------------------------------------------------------------------------------------------
// I2C_MasterReadWrite I2C主器件主动读写操作
// 参数:	uSlaveAdd 器件地址
// 参数:	uCommandCode 	读写指令或寄存器
// 参数:	uCommandData 	读写的数据
// 参数:	uReadWrite 		读写操作 0:写 、1:读
//----------------------------------------------------------------------------------------------------------
uint16_t I2C_MasterReadWrite(uint8_t uSlaveAdd,uint8_t uCommandCode,uint16_t uCommandData,uint8_t uReadWrite)
{
	uint8_t Recev1[4] = {0,0,0,0};
	//uint8_t Recev2 = 0x00;
	uint8_t i = 0x00;
	uint16_t uiCounter1 = 0x00;
	uint16_t uiInputValue = 0x00;
	
	uint8_t uAutoEndLen = 0x03;
	uint8_t uAutoRecLen = 0x01;
	
	uint8_t uMode = 0x00;	//0:写1Byte;1:读1Byte;2:写1Word;3:读1Word
	
	for(i=0;i<=40;i++)
	{
		uI2CData[i]=0;
		uI2C2Data[i]=0;
	}
	
	if((uCommandCode&0x80)==0x80)
			uAutoRecLen =2;	//字节操作
	else
			uAutoRecLen =1;
		
	if(uReadWrite==0)
	{	//写
		if((uCommandCode&0x80)==0x80)
		{	//双字节操作
			uAutoEndLen =4;
			uMode=2;	//写1Word
		}
		else
		{	//写1Byte;
			uMode=0;	//写1Byte
		}
	}
	else 
	{	//读
		if((uCommandCode&0x80)==0x80)
		{	//双字节操作
			uMode=3;	//读1Word
		}
		else
		{	//读1Byte
			uMode=1;	//读1Byte
		}
	}
		
	//---------------------------------------------------------------
	I2CTimeout = I2CT_LONG_TIMEOUT;	
	while(I2C_ReadStatusFlag(I2C2,I2C_FLAG_BUSY) == SET)   //IF BUSY
	{
		I2C2Init();
		if((I2CTimeout--) == 0) 
			return 0;
	}
	//---------------------------------------------------------------
	/** I2C Send Configuration*/
	//I2C_HandlingTransfer(I2C2,uSlaveAdd,2,I2C_RELOAD_MODE_SOFTEND,I2C_GENERATE_START_WRITE);
  /** Disable I2C interrupt  */
	//I2C_DisableInterrupt(I2C2,I2C_INT_RXIE|I2C_INT_ADDRIE|I2C_INT_STOPIE);
	/** I2C Send Configuration*/
	I2C_HandlingTransfer(I2C2,uSlaveAdd,uAutoEndLen,I2C_RELOAD_MODE_AUTOEND,I2C_GENERATE_START_WRITE);
	
	
	//---------------------------------------------------------------
	I2C_TxData(I2C2,uSlaveAdd);	//发地址
	//---------------------------------------------------------------
	uiCounter1 = 0x00;
	//If Write OK
	while(I2C_ReadStatusFlag(I2C2,I2C_FLAG_TXCF) == RESET && uiCounter1<I2CT_LONG_TIMEOUT)
	{
		uiCounter1++;
	}
	//---------------------------------------------------------------
	I2C_TxData(I2C2,uCommandCode);	//发需要读/写的寄存号
	//---------------------------------------------------------------
	uiCounter1 = 0x00;
	while(I2C_ReadStatusFlag(I2C2,I2C_FLAG_TXCF) == RESET && uiCounter1<I2CT_LONG_TIMEOUT)
	{
		uiCounter1++;	//超时检测
	}
	//---------------------------------------------------------------
	if(uReadWrite==0)
	{	//写入
		if(uMode==0)
		{	//1Byte
			I2C_TxData(I2C2,uCommandData&0xFF);	//发数据1Byte
			//---------------------------------------------------------------
			uiCounter1 = 0x00;
			while(I2C_ReadStatusFlag(I2C2,I2C_FLAG_TXCF) == RESET && uiCounter1<I2CT_LONG_TIMEOUT)
			{
				uiCounter1++;	//超时检测
			}
			//---------------------------------------------------------------
		}
		else if(uMode==2)
		{	//1Word
			I2C_TxData(I2C2,uCommandData&0xFF);	//发Low Byte
			//---------------------------------------------------------------
			uiCounter1 = 0x00;
			while(I2C_ReadStatusFlag(I2C2,I2C_FLAG_TXCF) == RESET && uiCounter1<I2CT_LONG_TIMEOUT)
			{
				uiCounter1++;	//超时检测
			}
			//---------------------------------------------------------------
			I2C_TxData(I2C2,((uCommandData>>8)&0xFF));	//发High Byte
			//---------------------------------------------------------------
			uiCounter1 = 0x00;
			while(I2C_ReadStatusFlag(I2C2,I2C_FLAG_TXCF) == RESET && uiCounter1<I2CT_LONG_TIMEOUT)
			{
				uiCounter1++;	//超时检测
			}
			//---------------------------------------------------------------
		}
	}
	else
	{	//读数据
		I2C_TxData(I2C2,uSlaveAdd|0x01);	//发地址+读标置位
		//---------------------------------------------------------------
		uiCounter1 = 0x00;
		while(I2C_ReadStatusFlag(I2C2,I2C_FLAG_TXCF) == RESET && uiCounter1<I2CT_LONG_TIMEOUT)
		{
			uiCounter1++;	//超时检测
		}
		//---------------------------------------------------------------
		I2C_HandlingTransfer(I2C2,uSlaveAdd,uAutoRecLen,I2C_RELOAD_MODE_SOFTEND,I2C_GENERATE_START_READ);
		//---------------------------------------------------------------
		for(i=0;i<uAutoRecLen;i++)
		{
			uiCounter1 = 0x00;
			//If I2C_FLAG_RXBNE OK
			while(I2C_ReadStatusFlag(I2C2,I2C_FLAG_RXBNE) == RESET && uiCounter1<I2CT_LONG_TIMEOUT)
			{
				uiCounter1++;	//超时检测
			}
			Recev1[i]=I2C_RxData(I2C2);	//读数据
		}
		//---------------------------------------------------------------
	}
	
	//---------------------------------------------------------------
	// I2C2 Generate Stop signal
	//I2C_EnableGenerateStop(I2C2);
	//---------------------------------------------------------------
	uiCounter1 = 0x00;
	//If I2C_FLAG_STOP OK
	while(I2C_ReadStatusFlag(I2C2,I2C_FLAG_STOP) == RESET && uiCounter1<I2CT_LONG_TIMEOUT)
	{
		uiCounter1++;	//超时检测
	}
	//---------------------------------------------------------------
 /** I2C Clear Stop Flag */
	I2C_ClearIntFlag(I2C2,I2C_INT_FLAG_STOP); 
	I2C_ConfigNumberOfBytes(I2C2, 1);
	 /** I2C Enable Interrupt */
	//I2C_EnableInterrupt(I2C2,I2C_INT_RXIE|I2C_INT_ADDRIE|I2C_INT_STOPIE);
	//---------------------------------------------------------------
	
	uiInputValue=Recev1[1]<<8|Recev1[0];
	
	return uiInputValue;
	
}

2.5 从器件响应主器件而返回数据操作处理过程

//----------------------------------------------------------------------------------------------------------
// I2C_SlaveSendData I2C从器件响应主器件而返回数据操作
// 参数:	*i2c 从I2C 
// 参数:	uCommandCode 	读写指令或寄存器
// 参数:	uCommandData 	读写的数据
// 参数:	uReadWrite 		读写操作 0:写 、1:读
//----------------------------------------------------------------------------------------------------------
void I2C_SlaveSendData(I2C_T *i2c)
{
	uint16_t uiCounter1 = 0x00;

	if(uSlaveSendFlag==1)
	{
		uSlaveSendFlag =0;
		if((uI2CData[1]&0x80)==0x80)
			uSlaveSendLen =2;
		else
			uSlaveSendLen =1;
		//---------------------------------------------------------------
		//	Send Frist Byte
		switch(uI2CData[1])
		{
			case 0x01:	//单字节0x01寄存器
				I2C_TxData(i2c,0x11);
				break;
			case 0x02:	//单字节0x02寄存器
				I2C_TxData(i2c,0x12);
				break;
			case 0x03:	//单字节0x03寄存器
				I2C_TxData(i2c,0x13);
				break;
			case 0x04:	//单字节0x04寄存器
				I2C_TxData(i2c,0x14);
				break;
			case 0x81:	//双字节0x81寄存器低字节
				I2C_TxData(i2c,0x81);
				break;
			case 0x82:	//双字节0x82寄存器低字节
				I2C_TxData(i2c,0x82);
				break;
			case 0x83:	//双字节0x83寄存器低字节
				I2C_TxData(i2c,0x83);
				break;
			case 0x84:	//双字节0x84寄存器低字节
				I2C_TxData(i2c,0x84);
				break;
			
			default:
				I2C_TxData(i2c,0xFF);
				break;
		}	
		//---------------------------------------------------------------
		uiCounter1 = 0x00;
		while(I2C_ReadStatusFlag(i2c,I2C_FLAG_TXCF) == RESET && uiCounter1<48000)
		{
			uiCounter1++;	//超时检测
		}
		//---------------------------------------------------------------
		if((uI2CData[1]&0x80)==0x80)
		{	// Send Second Byte
			switch(uI2CData[1])
			{
				case 0x81:	//双字节0x81寄存器高字节
					I2C_TxData(i2c,0x91);
					break;
				case 0x82:	//双字节0x82寄存器高字节
					I2C_TxData(i2c,0x92);
					break;
				case 0x83:	//双字节0x83寄存器高字节
					I2C_TxData(i2c,0x93);
					break;
				case 0x84:	//双字节0x84寄存器高字节
					I2C_TxData(i2c,0x94);
					break;
				
				default:
					I2C_TxData(i2c,0xFF);
					break;
			}	
			//---------------------------------------------------------------
			uiCounter1 = 0x00;
			while(I2C_ReadStatusFlag(i2c,I2C_FLAG_TXCF) == RESET && uiCounter1<48000)
			{
				uiCounter1++;	//超时检测
			}
			//---------------------------------------------------------------
		}
		I2C_EnableGenerateStop(i2c);	//发停止信号P
		
	}
	
}

2.6 从I2C1的中断处理过程

/*!
 * @brief       I2C interrupt service routine   
 *
 * @param       None
 *
 * @retval      None
 *
 * @note        This function need to put into I2C1_IRQHandler() in apm32f0xx_int.c
 */
void  I2C_Isr(void)
{
	uint8_t udata;
	static uint16_t uiDir=0;
	static uint8_t uAddMatchFlag=0;


	if(I2C_ReadIntFlag(I2C1,I2C_INT_FLAG_ADDR) == SET)
	{
		I2C_ConfigNumberOfBytes(I2C1, 1);
		I2C_ClearIntFlag(I2C1,I2C_INT_FLAG_ADDR);
		uAddMatchFlag=1;	//地址匹配标志置1
		udata = (uint8_t)I2C_RxData(I2C1);
		uiDir= (udata&0x01);
		if(uiDir==1)
		{	// I2C1: slave enters transmitter mode.
			//udata=0xB0;
		}
		else
		{	// I2C1: slave enters receiver mode.
			uI2CRxPos=0;
		}
	}
	else if(I2C_ReadStatusFlag(I2C1,I2C_FLAG_RXBNE) == SET && uAddMatchFlag==1)
	{
		/** I2C_ConfigNumberOfBytes is necessary*/
		I2C_ConfigNumberOfBytes(I2C1, 1);
		udata = (uint8_t)I2C_RxData(I2C1);
		uI2CData[uI2CRxPos]=udata;
		uI2CRxPos++;
		uI2CRxPos%=40;
		if(uI2CRxPos==3 && uI2CData[0]==SLAVEADDR0 && (uI2CData[0]|0x01)==uI2CData[2])
		{	//对本机的读指令
			uSlaveSendFlag = 1;
			//I2C_TxData(I2C1,0xFF);
			printf("%s\r\n",&uI2CData[1]); 
		}
		else if(uI2CRxPos>2 && uI2CData[0]==SLAVEADDR0)
		{	//对本机的写指令
			if((uI2CData[1]&0x80)==0 && uI2CRxPos==3)
			{	//1Byte
				//--------------------------------------
				//请将数据写入相应的1Byte寄存器
				//...
				//--------------------------------------
				
				I2C_EnableGenerateStop(I2C1);	//发停止信号P
			}
			else if((uI2CData[1]&0x80)==0x80 && uI2CRxPos==4)
			{	//1Word
				//--------------------------------------
				//请将数据写入相应的1Word寄存器
				//...
				//--------------------------------------
				
				I2C_EnableGenerateStop(I2C1);	//发停止信号P
			}
		}
	}
	else if(I2C_ReadIntFlag(I2C1,I2C_INT_FLAG_STOP) == SET && uAddMatchFlag==1)
	{
		I2C_ClearIntFlag(I2C1,I2C_INT_FLAG_STOP);
		uAddMatchFlag =0;
		if(uI2CRxPos>0)
		{
			printf("%s\r\n",&uI2CData[1]);	//串口输出I2C1收来的数据
		}
		uI2CRxPos=0;
	}
      
}

2.7 主I2C2的中断处理过程

/*!
 * @brief       I2C interrupt service routine   
 *
 * @param       None
 *
 * @retval      None
 *
 * @note        This function need to put into I2C1_IRQHandler() in apm32f0xx_int.c
 */
void  I2C2_Isr(void)
{
	uint8_t udata;
	static uint8_t uAdd2MatchFlag=0;	
	static uint8_t uI2C2RxPos=0;
    
    if(I2C_ReadIntFlag(I2C2,I2C_INT_FLAG_ADDR) == SET)
    {
			I2C_ConfigNumberOfBytes(I2C2, 1);
			I2C_ClearIntFlag(I2C2,I2C_INT_FLAG_ADDR);

			uAdd2MatchFlag =1;
			uI2C2RxPos=0;
    }
    else if(I2C_ReadStatusFlag(I2C2,I2C_FLAG_RXBNE) == SET)
    {
			#if(1)
			/** I2C_ConfigNumberOfBytes is necessary*/
			I2C_ConfigNumberOfBytes(I2C2, 1);
			udata = (uint8_t)I2C_RxData(I2C2);
			uI2C2Data[uI2C2RxPos]=udata;
			uI2C2RxPos++;
			uI2C2RxPos%=40;
			if(uI2C2RxPos==uSlaveSendLen)	
			{
				I2C_EnableGenerateStop(I2C2);
			}
			#endif
    }
    else if(I2C_ReadIntFlag(I2C2,I2C_INT_FLAG_STOP) == SET)
    {
			I2C_ClearIntFlag(I2C2,I2C_INT_FLAG_STOP);
			uAdd2MatchFlag =0;
			if(uI2C2RxPos>0)
			{
				printf("%s\r\n",uI2C2Data);	//串口输出I2C2收来的数据
			}
			uI2C2RxPos =0;
			
    }
		
}

2.8 按键的中断处理过程

/*!
 * @brief       BUTTON_KEY interrupt service routine   
 *
 * @param       None
 *
 * @retval      None
 *
 * @note        This function need to put into EINT0_1_IRQHandler()
 *              in apm32f0xx_int.c
 */
 void APM_MINI_PB_I2C_Isr()
{
	//uint8_t uDataTx[]="Hello master\r\n";

	if(EINT_ReadStatusFlag(EINT_LINE1)==SET)
	{
		EINT_ClearStatusFlag(EINT_LINE1);
		if(uButtonDownFlag==0)
		{
			uButtonDownFlag = 1;
			uButtonCounter++;
			uButtonCounter%=5;
			//按键I2C主器件向从器件读写数据
			uSlaveReadData=I2C_MasterReadWrite(SLAVEADDR0,(0x00|uButtonCounter),0x8899,0x00);	//写单字节(测试指令)
			//uSlaveReadData=I2C_MasterReadWrite(SLAVEADDR0,(0x00|uButtonCounter),0x8899,0x01);	//读单字节(测试指令)
			//uSlaveReadData=I2C_MasterReadWrite(SLAVEADDR0,(0x80|uButtonCounter),0x8899,0x00);	//写双字节(测试指令)
			//uSlaveReadData=I2C_MasterReadWrite(SLAVEADDR0,(0x80|uButtonCounter),0x8899,0x01);	//读双字节(测试指令)
			
		}
	}

}

2.9 主程序的处理过程

/*!
 * @brief       Main program
 *
 * @param       None
 *
 * @retval      None
 *
 * @note       
 */
int main(void)
{
    //uint16_t j=0;
	
	SystemClock_PLL_Init();	//PLL 初始化,将系统时钟调整到48MHz
	
    APM_MINI_LEDInit(LED3);	//指示灯的初始化
    APM_MINI_PBInit(BUTTON_KEY1,BUTTON_MODE_EINT);	//按键Key1的端口初始化
    APM_MINI_COMInit(COM1);	//串口1的初始化
	I2C2Init();	//主I2C初始化
    I2CInit();	//从I2C初始化
	
		//I2C_DATATX("TX=%s  Code = %d\r\n","test 4321",1);
  
    while(1)
    { 
			/** Press the BUTTON_KEY1, slave will send data to
			master along with information that showed in serial port*/
			//APM_MINI_LEDToggle(LED3);
			
			if(GPIO_ReadInputBit(GPIOA,GPIO_PIN_1)==BIT_SET)
			{	//防按键重复检测到
				uButtonDownFlag = 0;
			}
			I2C_SlaveSendData(I2C1);	//从I2C返回主器件要求的数据
    }
}

2.10 完整的源代码请下载

https://download.csdn.net/download/kingpower2018/87458548?spm=1001.2014.3001.5503
源代码下载

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
STM32F072RB是一款微控制器,其中包括硬件IIC(Inter-Integrated Circuit)功能。硬件IIC是一种串行通信协议,用于在芯片之间传输数据。在STM32F072RB上使用硬件IIC时,可以使用中断来处理接收和发送数据。常用的硬件IIC中断标志位包括:ADDR、RXNE、TXE和STOPF。 ADDR标志位在主机发送地址并与STM32从机匹配成功时被置位。如果启用了硬件IIC中断,当ADDR标志位被置位时,芯片将进入中断函数。 RXNE标志位在主机发送数据给STM32从机的情况下,每当接收数据寄存器接收到一个字节的数据时被置位。如果启用了硬件IIC中断,当RXNE标志位被置位时,芯片将进入中断函数。当从接收寄存器读取数据后,RXNE标志位将由硬件自动清零。 TXE标志位在作为STM32从机接收数据时,当发送数据寄存器为空时被置位。如果启用了硬件IIC中断,当TXE标志位被置位时,芯片将进入中断函数。一般在中断函数中,可以将数据填入发送数据寄存器,此时TXE标志位将被硬件自动清零。 STOPF标志位在主机发送停止信号结束通信时,当STM32从机接收到停止信号时被置位。如果启用了硬件IIC中断,当STOPF标志位被置位时,芯片将进入中断函数。 通过以上标志位的设置和处理,可以实现硬件IIC的数据接收和发送功能。请注意,每个中断标志位在处理完相关操作后都会由硬件自动清零,以确保正确的中断处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

华为奋斗者精神

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

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

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

打赏作者

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

抵扣说明:

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

余额充值