GD32MCU硬件I2C学习(一)

1.1 硬件I2C介绍
在项目中遇见与MCU通信接口协议为I2C的设备时,可通过GPIO口软件模拟I2C和使用MCU自身的硬件I2C资源。两者各有优势,软件模拟可以不受GPIO口限制,也可以主控制器MCU的选择上降低成本,但也存在I2C设备对通信速率有特定的要求或者需要较高的传输速率时,会存在时序调试困难、start/stop/ack/noack/read/write等都需要软件实现、GPIO口翻转速率限制等原因导致软件模拟I2C通信速率有一定的限制。硬件I2C则不存在上述问题,I2C通信速率可配置100k/400k/1M(NXP芯片做到了3.4M),通信时序中的绝大部分都由硬件完成,我们只需要按照逻辑配置好相应的寄存器即可,但也存在受特定GPIO口限制、相应成本高等缺点。本文主要是基GD32MCU介绍硬件I2C的配置和注意的事项,关于I2C协议概念介绍只是简要提及。
1.2 GD32 mcu硬件I2C的主要特性
1、同一接口既可实现主机功能又可实现从机功能;
2、主从机之间的双向数据传输;
3、支持7位和10位的地址模式和广播寻址;
4、支持I2C多主机模式;
5、速率100k\400k\1M;
6、从机模式下可配置SCL主动拉低;
7、支持DMA模式;
8、支持SMBUS;
9、事件中断和错误中断;
10、支持PEC错误校验。
1.3 主机发送和接收实现(速率100k/400k/1M 地址10bit or 7bit)

 //.h文件
#ifndef MAIN_H
#define MAIN_H
#include "gd32f3x0.h"
#define I2Cx_Pinx_AFx_BIT(gpiox,pinx,afx) (((uint32_t)gpiox)|((uint32_t)(pinx)<<4)|(uint32_t)(afx))
/*send_slaver address*/
typedef enum
{
  Send_7Address=0x42,
  Send_7Address_2=0x44,	
  send_gual=0x00,
  Send_10Address=0x232
}Send_Address_Enum;
/*define pin speed enum*/
typedef enum
{
 standard_speed=100000,
 High_speed=400000,
 More_HighSpeed=1000000
}I2Cx_Speed_enum;

/*define I2Cx SDA Pin enum*/
typedef enum
{
 //define I2C0
 I2C0_SDA_GPIOx1=I2Cx_Pinx_AFx_BIT(GPIOA,10,4),
 I2C0_SDA_GPIOx2=I2Cx_Pinx_AFx_BIT(GPIOB,7,1),	
 I2C0_SDA_GPIOx3=I2Cx_Pinx_AFx_BIT(GPIOB,9,1),	
 //define I2C1
 I2C1_SDA_GPIOx4=I2Cx_Pinx_AFx_BIT(GPIOA,1,4),
 I2C1_SDA_GPIOx5=I2Cx_Pinx_AFx_BIT(GPIOB,11,1),
 I2C1_SDA_GPIOx6=I2Cx_Pinx_AFx_BIT(GPIOF,7,0)
}I2Cx_PinSDA_Enum;

/*define I2Cx SCL Pin enum*/
typedef enum
{
 //define I2C0	
 I2C0_SCL_GPIOy1=I2Cx_Pinx_AFx_BIT(GPIOA,9,4),
 I2C0_SCL_GPIOy2=I2Cx_Pinx_AFx_BIT(GPIOB,6,1),
 I2C1_SCL_GPIOy3=I2Cx_Pinx_AFx_BIT(GPIOB,8,1),
 //define I2C1
 I2C1_SCL_GPIOy4=I2Cx_Pinx_AFx_BIT(GPIOA,0,4),
 I2C1_SCL_GPIOy5=I2Cx_Pinx_AFx_BIT(GPIOB,10,1),
 I2C1_SCL_GPIOy6=I2Cx_Pinx_AFx_BIT(GPIOB,6,0)
}I2Cx_PinSCL_Enum;
/*define I2Cx address model*/
typedef enum
{
  I2Cx_Address_7bit=I2C_ADDFORMAT_7BITS,
  I2Cx_Address_10bit=I2C_ADDFORMAT_10BITS	
}Address_Model_Enum;
/*define I2Cx slaver address*/
typedef enum
{
    Slaver_7Address=0x40,              
	Slaver_10Address=0x230
}Slaver_Address_Enum;
/*define I2CX init param*/
typedef struct 
{
	uint32_t Memory_address;
	I2Cx_PinSDA_Enum gpio_sdapin;
	I2Cx_PinSCL_Enum gpio_sclpin;
	rcu_periph_enum I2Cx_Periph;
	I2Cx_Speed_enum I2c_speed;
	Address_Model_Enum address_model;
	Send_Address_Enum address;
	Slaver_Address_Enum slaver_address;
}Param_Typedef;
/*I2C gpio init function*/
void I2Cx_Init(Param_Typedef* i2c_init);
/*I2C gpiopin enable*/
void I2Cx_Pin_ClockEnable(I2Cx_PinSDA_Enum gpio_sdapin,I2Cx_PinSCL_Enum gpio_sclpin);
/*I2C master send buffer 7 and 10 address*/
void Master_SendData_address(uint8_t* SendBuffer,uint8_t DataNum,Param_Typedef *i2c_init);
/*I2C master receive data 7 and 10 address*/
void Master_ReceiveData(uint8_t* ReceiveBuffer,uint8_t DataNum,Param_Typedef *i2c_init);
/*I2C 7 bit address prepare send*/
void Send_7Prepare(Param_Typedef *i2c_init);
/*I2C 10 bit address prepare send*/
void Send_10Prepare(Param_Typedef *i2c_init);
/*I2C 10 bit address prepare receive*/
void Receive_10Prepare(Param_Typedef *i2c_init);
/*Master receive 7 address prepare*/
void Receive_7Prepare(Param_Typedef *i2c_init);

#endif /* MAIN_H */
//.c文件
#include "gd32f3x0.h"
#include <stdio.h>
#include "gd32f350r_eval.h"
#include "main.h"
#include "systick.h"
#define I2C0_Measure
//#define I2C1_Measure
#define BufferNum 20
uint8_t write_buffer[BufferNum]={0};//send data buffer
uint8_t receive_buffer[BufferNum]={0};//receive data buffer
Param_Typedef I2Cx_Param;

/*define I2Cx Param struct array*/
static Param_Typedef Para_Aarry[]=
{
	/*I2C0 param array*/
	{I2C0,I2C0_SDA_GPIOx2,I2C0_SCL_GPIOy2,RCU_I2C0,standard_speed,I2Cx_Address_7bit,Send_7Address,Slaver_7Address},
	{I2C0,I2C0_SDA_GPIOx2,I2C0_SCL_GPIOy2,RCU_I2C0,standard_speed,I2Cx_Address_10bit,Send_10Address,Slaver_10Address},
	{I2C0,I2C0_SDA_GPIOx2,I2C0_SCL_GPIOy2,RCU_I2C0,High_speed,I2Cx_Address_7bit,Send_7Address,Slaver_7Address},
	{I2C0,I2C0_SDA_GPIOx2,I2C0_SCL_GPIOy2,RCU_I2C0,High_speed,I2Cx_Address_10bit,Send_10Address,Slaver_10Address},
	{I2C0,I2C0_SDA_GPIOx2,I2C0_SCL_GPIOy2,RCU_I2C0,More_HighSpeed,I2Cx_Address_7bit,Send_7Address,Slaver_7Address},
	/*I2C1 param array*/
	{I2C1,I2C1_SDA_GPIOx5,I2C1_SCL_GPIOy5,RCU_I2C1,standard_speed,I2Cx_Address_7bit,Send_7Address,Slaver_7Address},
	{I2C1,I2C1_SDA_GPIOx5,I2C1_SCL_GPIOy5,RCU_I2C1,standard_speed,I2Cx_Address_10bit,Send_10Address,Slaver_10Address},
	{I2C1,I2C1_SDA_GPIOx5,I2C1_SCL_GPIOy5,RCU_I2C1,High_speed,I2Cx_Address_7bit,Send_7Address,Slaver_7Address},
	{I2C1,I2C1_SDA_GPIOx5,I2C1_SCL_GPIOy5,RCU_I2C1,High_speed,I2Cx_Address_10bit,Send_10Address,Slaver_10Address},
	{I2C1,I2C1_SDA_GPIOx5,I2C1_SCL_GPIOy5,RCU_I2C1,More_HighSpeed,I2Cx_Address_7bit,Send_7Address,Slaver_7Address},
};

/*testing sequence enum*/
typedef enum
{
	/*Measure I2C0*/
	I2C0_Seven_Address_standard=0,
	I2C0_Ten_Address_standard,
	I2C0_Seven_Address_high,
	I2C0_Ten_Address_high,
	I2C0_Seven_Address_more_high,
	/*Measure I2C1*/
	I2C1_Seven_Address_standard,
	I2C1_Ten_Address_standard,
	I2C1_Seven_Address_high,
	I2C1_Ten_Address_high,
	I2C1_Seven_Address_more_high
}Test_Sequence_Enum;
/*Configure Param of I2Cx Send data*/
void Configure_I2CX_Send(Test_Sequence_Enum measure_sequence);
/*Configure Param of I2Cx receive data*/
void Configure_I2CX_Receive(Test_Sequence_Enum measure_sequence);
/*I2Cx param init*/
void Param_Init(Param_Typedef* i2c_param,Param_Typedef* Param_Array,Test_Sequence_Enum measure_sequence);
/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
int main(void)
{
	 uint8_t num=0;
   /*configure EVAL_COM1*/
   gd_eval_com_init(EVAL_COM);
	 systick_config();
	 for(num=0;num<BufferNum;num++){
		 write_buffer[num]=num;
	 }
	 #ifdef I2C0_Measure
	 /*Test Sequence I2C0 send*/
	 Configure_I2CX_Send(I2C0_Seven_Address_standard);
	 Configure_I2CX_Send(I2C0_Ten_Address_standard);
	 Configure_I2CX_Send(I2C0_Seven_Address_high);
	 Configure_I2CX_Send(I2C0_Ten_Address_high);
	 Configure_I2CX_Send(I2C0_Seven_Address_more_high);
	 /*Test Sequence I2C0 receive*/
	 Configure_I2CX_Receive(I2C0_Seven_Address_standard);
	 Configure_I2CX_Receive(I2C0_Ten_Address_standard);
	 Configure_I2CX_Receive(I2C0_Seven_Address_high);
	 Configure_I2CX_Receive(I2C0_Ten_Address_high);
	 Configure_I2CX_Receive(I2C0_Seven_Address_more_high);
	 #elif defined I2C1_Measure
	 /*Test Sequence I2C1 send*/
	 Configure_I2CX_Send(I2C1_Seven_Address_standard);
	 Configure_I2CX_Send(I2C1_Ten_Address_standard);
	 Configure_I2CX_Send(I2C1_Seven_Address_high);
	 Configure_I2CX_Send(I2C1_Ten_Address_high);
	 Configure_I2CX_Send(I2C1_Seven_Address_more_high);
	 /*Test Sequence I2C1 receive*/
	 Configure_I2CX_Receive(I2C1_Seven_Address_standard);
	 Configure_I2CX_Receive(I2C1_Ten_Address_standard);
	 Configure_I2CX_Receive(I2C1_Seven_Address_high);
	 Configure_I2CX_Receive(I2C1_Ten_Address_high);
	 Configure_I2CX_Receive(I2C1_Seven_Address_more_high);
	 #endif
   while(1){
      
   }
}

/*!
    \brief      Configure Param of I2Cx I2Cx Send data
    \param[in]  Test_Sequence_Enum measure_sequence //test sequence
    \param[out] none
    \retval     none
*/
void Configure_I2CX_Send(Test_Sequence_Enum measure_sequence)
{	
	switch(measure_sequence)
	{
		case I2C0_Seven_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Seven_Address_standard);
      I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C0 Seven Address standard send success\n");
	  break;
		case I2C0_Ten_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Ten_Address_standard);
      I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
      printf("I2C0_Ten_Address_standard send success\n");		
	  break;
		case I2C0_Seven_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Seven_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
      printf("I2C0_Seven_Address_high send success\n");		
	  break;
		case I2C0_Ten_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Ten_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C0_Ten_Address_high send success\n");
	  break;
		case I2C0_Seven_Address_more_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Seven_Address_more_high);	
		  I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C0_Seven_Address_more_high send success\n");
	  break;
		case I2C1_Seven_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Seven_Address_standard);	
      I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1 Seven Address standard send success\n");
	  break;
		case I2C1_Ten_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Ten_Address_standard);
      I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Ten_Address_standard send success\n");	
	  break;
		case I2C1_Seven_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Seven_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Seven_Address_high send success\n");
	  break;
		case I2C1_Ten_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Ten_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Ten_Address_high send success\n");
	  break;
		case I2C1_Seven_Address_more_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Seven_Address_more_high);	
		  I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Seven_Address_more_high send success\n");
	  break;
		default:
		break;
	}
}

/*!
    \brief      Configure Param of receive data
    \param[in]  Test_Sequence_Enum measure_sequence //test sequence
    \param[out] none
    \retval     none
*/
void Configure_I2CX_Receive(Test_Sequence_Enum measure_sequence)
{
 	switch(measure_sequence)
	{
		case I2C0_Seven_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Seven_Address_standard);
      I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_ReceiveData(receive_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C0_Seven_Address_standard receive data success!!\n");
	  break;
		case I2C0_Ten_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Ten_Address_standard);
      I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_ReceiveData(receive_buffer,BufferNum,&I2Cx_Param);	
		  printf("I2C0_Ten_Address_standard receive data success!!\n");
	  break;
		case I2C0_Seven_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Seven_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_ReceiveData(receive_buffer,BufferNum,&I2Cx_Param);	
		  printf("I2C0_Seven_Address_high receive data success!!\n");
	  break;
		case I2C0_Ten_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Ten_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_ReceiveData(receive_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C0_Ten_Address_high receive data success!!\n");
	  break;
		case I2C0_Seven_Address_more_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Seven_Address_more_high);	
		  I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_ReceiveData(receive_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C0_Ten_Address_high receive data success!!\n");
	  break;
		case I2C1_Seven_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Seven_Address_standard);	
      I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_ReceiveData(receive_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Seven_Address_standard receive data success!!\n");
	  break;
		case I2C1_Ten_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Ten_Address_standard);
      I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_ReceiveData(receive_buffer,BufferNum,&I2Cx_Param);
	    printf("I2C1_Ten_Address_standard receive data success!!\n");
	  break;
		case I2C1_Seven_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Seven_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_ReceiveData(receive_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Seven_Address_high receive data success!!\n");
	  break;
		case I2C1_Ten_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Ten_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_ReceiveData(receive_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Ten_Address_high receive data success!!\n");
	  break;
		case I2C1_Seven_Address_more_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Seven_Address_more_high);	
		  I2Cx_Init(&I2Cx_Param);
		  delay_1ms(3000);//delay 3s wait slaver init success!
      Master_ReceiveData(receive_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Ten_Address_high receive data success!!\n");
	  break;
		default:
		break;
	}
}

/*!
    \brief      Configure Param of I2Cx receive data
    \param[in]  Test_Sequence_Enum measure_sequence //test sequence
    \param[out] none
    \retval     none
*/
void Param_Init(Param_Typedef* i2c_param,Param_Typedef* Param_Array,Test_Sequence_Enum measure_sequence)
{
   i2c_param->Memory_address=Param_Array[measure_sequence].Memory_address;
	 i2c_param->gpio_sclpin=Param_Array[measure_sequence].gpio_sclpin;
	 i2c_param->gpio_sdapin=Param_Array[measure_sequence].gpio_sdapin;
	 i2c_param->address=Param_Array[measure_sequence].address;
	 i2c_param->address_model=Param_Array[measure_sequence].address_model;
	 i2c_param->I2Cx_Periph=Param_Array[measure_sequence].I2Cx_Periph;
	 i2c_param->I2c_speed=Param_Array[measure_sequence].I2c_speed;
	 i2c_param->slaver_address=Param_Array[measure_sequence].slaver_address;
}

/*!
    \brief      I2C init
    \param[in]  I2Cx_PinSDA_Enum SDA pin
		            I2Cx_PinSCL_Enum SCL pin
								rcu_periph_enum  I2C periph
		            I2Cx_Speed_enum check clock frequence
								Address_Model_Enum 7 or 10 address check 
								Slaver_Address_Enum 7 or 10 address 
    \param[out] none
    \retval     none
*/
void I2Cx_Init(Param_Typedef *i2c_init)
{
	uint32_t gpiox_sda,pinx_sda,afx_sda,gpiox_scl,pinx_scl,afx_scl;
	I2Cx_Pin_ClockEnable(i2c_init->gpio_sdapin,i2c_init->gpio_sclpin);//SCL and SDA GPIO enable
	/*GPIO sda configure*/
	gpiox_sda=(uint32_t)((i2c_init->gpio_sdapin)& 0xffffff00);
	pinx_sda=(0x01<<((i2c_init->gpio_sdapin & 0xf0) >> 4));
	afx_sda=AF((i2c_init->gpio_sdapin & 0x0f));
	I2Cx_Pin_ClockEnable(i2c_init->gpio_sdapin,i2c_init->gpio_sclpin);
	gpio_af_set(gpiox_sda, afx_sda, pinx_sda);//IO口引脚复用功能
	gpio_mode_set(gpiox_sda, GPIO_MODE_AF, GPIO_PUPD_PULLUP,pinx_sda);//GPIO口、备用功能、端口上拉模式、具体引脚
	gpio_output_options_set(gpiox_sda, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,pinx_sda);//GPIO口、推挽输出及开漏输出、输出速率、具体引脚
	/*GPIO scl configure*/
	gpiox_scl=(uint32_t)((i2c_init->gpio_sclpin)& 0xffffff00);
	pinx_scl=(0x01<<((i2c_init->gpio_sclpin & 0xf0) >> 4));
	afx_scl=AF((i2c_init->gpio_sclpin & 0x0f));
	gpio_af_set(gpiox_scl, afx_scl,pinx_scl);//IO口引脚复用功能
	gpio_mode_set(gpiox_scl, GPIO_MODE_AF, GPIO_PUPD_PULLUP,pinx_scl);//GPIO口、备用功能、端口上拉模式、具体引脚
	/*--------------------------------I2C module initaial configure------------------------------------*/
	/*enable I2C clock*/
	rcu_periph_clock_enable(i2c_init->I2Cx_Periph);//使能I2C时钟
	/*configure I2C clock*/
  i2c_clock_config(i2c_init->Memory_address,i2c_init->I2c_speed,I2C_DTCY_2);//I2C的基地址、I2C数据传输速度、I2C的快速模式
	/*configure I2C address*/
  i2c_mode_addr_config(i2c_init->Memory_address,I2C_I2CMODE_ENABLE,i2c_init->address_model,i2c_init->slaver_address);//I2C基地址、I2C模式、7位地址模式、I2C从机地址
	/*enable I2C0*/
  i2c_enable(i2c_init->Memory_address);//I2C外设使能
  /*enable acknowledge*/
	i2c_ack_config(i2c_init->Memory_address,I2C_ACK_ENABLE);//选择是否发送应答信号
}

/*!
    \brief      I2C GPIO Clock enable
    \param[in]  I2Cx_PinSDA_Enum SDA pin
		            I2Cx_PinSCL_Enum SCL pin
    \param[out] none
    \retval     none
*/
void I2Cx_Pin_ClockEnable(I2Cx_PinSDA_Enum gpio_sdapin,I2Cx_PinSCL_Enum gpio_sclpin)
{
	uint32_t gpiox_sda,gpiox_scl;
	gpiox_sda=(uint32_t)(gpio_sdapin & 0xffffff00);
	gpiox_scl=(uint32_t)(gpio_sclpin & 0xffffff00);
	/*SDA enable*/
	if(gpiox_sda==GPIOB){
	  rcu_periph_clock_enable(RCU_GPIOB);	
	}else if(gpiox_sda==GPIOA){
	  rcu_periph_clock_enable(RCU_GPIOC);	
	}else if(gpiox_sda==GPIOF){
		rcu_periph_clock_enable(RCU_GPIOF);	
	}
	/*SCL enable*/
	if(gpiox_scl==GPIOB){
	  rcu_periph_clock_enable(RCU_GPIOB);	
	}else if(gpiox_scl==GPIOA){
	  rcu_periph_clock_enable(RCU_GPIOA);	
	}
}

/*!
    \brief      Master send data 7 and 10 address
    \param[in]  SendBuffer send array
		            DataNum send data num
    \param[out] none
    \retval     none
*/
void Master_SendData_address(uint8_t* SendBuffer,uint8_t DataNum,Param_Typedef *i2c_init)
{
 	uint8_t num;
	/*wait until I2C bus is idle*/
	while(i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_I2CBSY)){
	}
	/*send a start condition to I2C bus*/
	i2c_start_on_bus(i2c_init->Memory_address);//在I2C总线上产生一个开始信号
	/*wait until SBSEND bit is set  judge start whether send*/
  while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_SBSEND)){
	}
	//I2C_STAT0(i2c_init->Memory_address);//read I2C_STAT0 to clear ADDSEND
	if(i2c_init->address_model==I2Cx_Address_7bit){
	  Send_7Prepare(i2c_init);
	}
	else if(i2c_init->address_model==I2Cx_Address_10bit){
	  Send_10Prepare(i2c_init);
	}
	/*wait until the transmit data buffer is empty */
  while(SET != i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_TBE)){
	}
	for(num=0;num<DataNum;num++){
	  i2c_data_transmit(i2c_init->Memory_address,SendBuffer[num]);	
		while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_BTC)){
		}
	}
  /*send a stop condition to I2C bus*/
  i2c_stop_on_bus(i2c_init->Memory_address);//在总线上发送停止信号位  
  /*wait until the stop condition is finished*/
  while(I2C_CTL0(i2c_init->Memory_address)&0x0200);//等待结束信号发送
  //printf("master send data success");
}

/*!
    \brief      Master receive data
    \param[in]  ReceiveBuffer receive data array
		            DataNum receive data num
                address  slaver address
    \param[out] none
    \retval     none
*/
void Master_ReceiveData(uint8_t* ReceiveBuffer,uint8_t DataNum,Param_Typedef *i2c_init)
{
	/*wait until I2C bus is idle*/
	while(i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_I2CBSY));
	/*send a start condition to I2C bus*/
	i2c_start_on_bus(i2c_init->Memory_address);//在I2C总线上产生一个开始信号
	/*wait until SBSEND bit is set  judge start whether send*/
  while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_SBSEND));
	if(i2c_init->address==Send_7Address){
	 Receive_7Prepare(i2c_init);
	}
	else if(i2c_init->address==Send_10Address){
	 Receive_10Prepare(i2c_init);
	}
	if(DataNum==1){
	 /*disable acknowledge*/
	 i2c_ack_config(i2c_init->Memory_address,I2C_ACK_DISABLE);//选择是否发送应答信号
	 /*send a stop condition to I2C bus*/
     i2c_stop_on_bus(i2c_init->Memory_address);//在总线上发送停止信号位
	 /*I2C_DATA is not empty*/
	  while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_RBNE));
	  *ReceiveBuffer=i2c_data_receive(i2c_init->Memory_address);//read data from I2C_DATA
  }
	 while(DataNum){
      if(DataNum==2){
          while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_RBNE));
         *ReceiveBuffer=i2c_data_receive(i2c_init->Memory_address);//read data from I2C_DATA
		  DataNum-=1;
          ReceiveBuffer++;	
		  /*disable acknowledge*/
	      i2c_ack_config(i2c_init->Memory_address,I2C_ACK_DISABLE);//选择是否发送应答信号
	      /*send a stop condition to I2C bus*/
        i2c_stop_on_bus(i2c_init->Memory_address);//在总线上发送停止信号位 
	   }
		 /*I2C_DATA is not empty*/
	    while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_RBNE));
     *ReceiveBuffer=i2c_data_receive(i2c_init->Memory_address);//read data from I2C_DATA
     DataNum-=1;
     ReceiveBuffer++;		 
   }		 
  /*wait until the stop condition is finished*/
  while(I2C_CTL0(i2c_init->Memory_address)&0x0200);//判断stop结束位已经发送
  /*enable acknowledge*/
  i2c_ack_config(i2c_init->Memory_address,I2C_ACK_ENABLE);//软件发送应答信号使能
  i2c_ackpos_config(i2c_init->Memory_address,I2C_ACKPOS_CURRENT);//ACKEN位决定对当前正在接收的字节是否发送ACK/NACK;PECTRANS位表明PEC 是否处于移位寄存器中
	//printf("master receive data success");
}

/*!
    \brief      Master send 7 address prepare
    \param[in]  none
    \param[out] none
    \retval     none
*/
void Send_7Prepare(Param_Typedef *i2c_init)
{
 /*send slave address to I2C bus*/
 i2c_master_addressing(i2c_init->Memory_address,i2c_init->address,I2C_TRANSMITTER);//发送从机地址+写、清除SBSEND位、I2C设备发送方
 /*wait until ADDSEND bit is set*/
 while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_ADDSEND)){
 }
 /*read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND*/
 i2c_flag_clear(i2c_init->Memory_address,I2C_FLAG_ADDSEND);//清除ADDSEND位	
}

/*!
    \brief      Master receive 7 address prepare
    \param[in]  none
    \param[out] none
    \retval     none
*/
void Receive_7Prepare(Param_Typedef *i2c_init)
{
 /*send slave address to I2C bus */
 i2c_master_addressing(i2c_init->Memory_address,i2c_init->address,I2C_RECEIVER);//发送从机地址+写、清除SBSEND位、I2C设备发送方
 /* wait until ADDSEND bit is set */
 while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_ADDSEND)){
 }
 /*read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND*/
 i2c_flag_clear(i2c_init->Memory_address,I2C_FLAG_ADDSEND);//清除ADDSEND位	
}

/*!
    \brief      Master send 10 address prepare
    \param[in]  none
    \param[out] none
    \retval     none
*/
void Send_10Prepare(Param_Typedef *i2c_init)
{
  uint32_t adrH10,adrL10;
  adrH10=(((i2c_init->address & 0x300)>>7)|0xf0);//10位地址头(高2位)	
  adrL10=i2c_init->address & 0xff;//10位地址(低8位)
  /*send slave  address adr10 to I2C bus */
  i2c_master_addressing(i2c_init->Memory_address,(uint8_t)adrH10, I2C_TRANSMITTER);
  /* wait until ADDSEND bit is set */
  while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_ADD10SEND));
  i2c_data_transmit(i2c_init->Memory_address,adrL10);
  /*wait until ADDSEND bit is set*/
  while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_ADDSEND));
   /*read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND*/
  i2c_flag_clear(i2c_init->Memory_address,I2C_FLAG_ADDSEND);//清除ADDSEND位
}

/*!
    \brief      Master receive 10 address prepare
    \param[in]  none
    \param[out] none
    \retval     none
*/
void Receive_10Prepare(Param_Typedef *i2c_init)
{
    uint32_t adrH10,adrL10;
    adrH10=(((i2c_init->address & 0x300)>>7)|0xf0);//10位地址头(高2位)	
	adrL10=i2c_init->address & 0xff;//10位地址(低8位)
	/*send slave address to I2C bus*/
  i2c_master_addressing(i2c_init->Memory_address,(uint8_t)adrH10, I2C_TRANSMITTER);//发送从机10地址头+写、清除SBSEND位、I2C设备发送方
	/*wait until ADDSEND bit is set*/
  while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_ADD10SEND));
	i2c_data_transmit(i2c_init->Memory_address,adrL10);
	/* wait until ADDSEND bit is set */
  while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_ADDSEND));
	/*read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND*/
  i2c_flag_clear(i2c_init->Memory_address,I2C_FLAG_ADDSEND);//清除ADDSEND位
  /*send a start condition to I2C bus*/
	i2c_start_on_bus(i2c_init->Memory_address);//在I2C总线上产生一个开始信号
	/*wait until SBSEND bit is set  judge start whether send*/
  while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_SBSEND));
	i2c_master_addressing(i2c_init->Memory_address,(uint8_t)adrH10,I2C_RECEIVER);
	  while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_ADDSEND));//等待ADDSEND位置1 硬件置1
	/*read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND*/
  i2c_flag_clear(i2c_init->Memory_address,I2C_FLAG_ADDSEND);//清除ADDSEND位
}

/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
    usart_data_transmit(EVAL_COM, (uint8_t)ch);
    while(RESET == usart_flag_get(EVAL_COM, USART_FLAG_TBE));
    return ch;
}

/*!
    \brief      this function handles SysTick exception
    \param[in]  none
    \param[out] none
    \retval     none
*/
void SysTick_Handler(void)
{
    delay_decrement();
}

上述程序实现了主机发送和接收,速率100k/400k/1M,发送从机地址10bit、7bit,程序方便移植,只需将对应的.c和.h添加到工程中即可。当I2C的通信速率为1M时,需配置I2C模块所挂载的pclk时钟为3的整数倍或者25的整数倍,否则主机的SCL实际的时钟会有一定的误差,大于或者小于1M,大于1M可能导致通信失败(GD mcu官方手册有提到)。I2C总线空闲时,默认为高电平,因为GPIO口内部自带的上拉驱动能力不够,配置为开漏输出,需外接上拉电阻,GPIO的输出速率要选择最大(代码中选择的是50M)增加GPIO口输出能力,否则通过示波器查看发现SCL时钟波形不是正规的波形,也可能造成通信失败。不同GPIO口输出速率下,SCL时钟输出波形如下图所示。
上图为上到下GPIO口输出速率依次增大SCL输出波形图
1.4 从机发送和接收(速率100k\400k\1M,地址10bit or 7bit)
I2C的从机的通信时钟由主机提供,故不需要配置时钟,I2C初始化后默认为从机模式,发送start信号后,由从机模式转换为主机模式。

#include "gd32f3x0.h"
#include <stdio.h>
#include "gd32f350r_eval.h"
#include "main.h"
#include "systick.h"
#define I2C0_Measure
//#define I2C1_Measure
#define BufferNum 20
uint8_t write_buffer[BufferNum]={0};//send data buffer
uint8_t receive_buffer[BufferNum]={0};//receive data buffer
Param_Typedef I2Cx_Param;

/*define I2Cx Param struct array*/
static Param_Typedef Para_Aarry[]=
{
	/*I2C0 param array*/
	{I2C0,I2C0_SDA_GPIOx2,I2C0_SCL_GPIOy2,RCU_I2C0,standard_speed,I2Cx_Address_7bit,Send_7Address,Slaver_7Address},
	{I2C0,I2C0_SDA_GPIOx2,I2C0_SCL_GPIOy2,RCU_I2C0,standard_speed,I2Cx_Address_10bit,Send_10Address,Slaver_10Address},
	{I2C0,I2C0_SDA_GPIOx2,I2C0_SCL_GPIOy2,RCU_I2C0,High_speed,I2Cx_Address_7bit,Send_7Address,Slaver_7Address},
	{I2C0,I2C0_SDA_GPIOx2,I2C0_SCL_GPIOy2,RCU_I2C0,High_speed,I2Cx_Address_10bit,Send_10Address,Slaver_10Address},
	{I2C0,I2C0_SDA_GPIOx2,I2C0_SCL_GPIOy2,RCU_I2C0,More_HighSpeed,I2Cx_Address_7bit,Send_7Address,Slaver_7Address},
	/*I2C1 param array*/
	{I2C1,I2C1_SDA_GPIOx5,I2C1_SCL_GPIOy5,RCU_I2C1,standard_speed,I2Cx_Address_7bit,Send_7Address,Slaver_7Address},
	{I2C1,I2C1_SDA_GPIOx5,I2C1_SCL_GPIOy5,RCU_I2C1,standard_speed,I2Cx_Address_10bit,Send_10Address,Slaver_10Address},
	{I2C1,I2C1_SDA_GPIOx5,I2C1_SCL_GPIOy5,RCU_I2C1,High_speed,I2Cx_Address_7bit,Send_7Address,Slaver_7Address},
	{I2C1,I2C1_SDA_GPIOx5,I2C1_SCL_GPIOy5,RCU_I2C1,High_speed,I2Cx_Address_10bit,Send_10Address,Slaver_10Address},
	{I2C1,I2C1_SDA_GPIOx5,I2C1_SCL_GPIOy5,RCU_I2C1,More_HighSpeed,I2Cx_Address_7bit,Send_7Address,Slaver_7Address},
};

/*testing sequence enum*/
typedef enum
{
	/*Measure I2C0*/
	I2C0_Seven_Address_standard=0,
	I2C0_Ten_Address_standard,
	I2C0_Seven_Address_high,
	I2C0_Ten_Address_high,
	I2C0_Seven_Address_more_high,
	/*Measure I2C1*/
	I2C1_Seven_Address_standard,
	I2C1_Ten_Address_standard,
	I2C1_Seven_Address_high,
	I2C1_Ten_Address_high,
	I2C1_Seven_Address_more_high
}Test_Sequence_Enum;
/*Configure Param of I2Cx Send data*/
void Configure_I2CX_Send(Test_Sequence_Enum measure_sequence);
/*Configure Param of I2Cx receive data*/
void Configure_I2CX_Receive(Test_Sequence_Enum measure_sequence);
/*I2Cx param init*/
void Param_Init(Param_Typedef* i2c_param,Param_Typedef* Param_Array,Test_Sequence_Enum measure_sequence);
/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
int main(void)
{
	 uint8_t num=0;
	 for(num=0;num<BufferNum;num++){
		 write_buffer[num]=num;
	 }
   //printf("I2C slaver measuring\n");
	 #ifdef I2C0_Measure
	 /*Test Sequence I2C0 receive*/
	 Configure_I2CX_Receive(I2C0_Seven_Address_standard);
	 Configure_I2CX_Receive(I2C0_Ten_Address_standard);
	 Configure_I2CX_Receive(I2C0_Seven_Address_high);
	 Configure_I2CX_Receive(I2C0_Ten_Address_high);
	 Configure_I2CX_Receive(I2C0_Seven_Address_more_high);
	 /*Test Sequence I2C0 send*/
	 Configure_I2CX_Send(I2C0_Seven_Address_standard);
	 Configure_I2CX_Send(I2C0_Ten_Address_standard);
	 Configure_I2CX_Send(I2C0_Seven_Address_high);
	 Configure_I2CX_Send(I2C0_Ten_Address_high);
	 Configure_I2CX_Send(I2C0_Seven_Address_more_high);
	 #elif defined I2C1_Measure
	 /*Test Sequence I2C1 receive*/
	 Configure_I2CX_Receive(I2C1_Seven_Address_standard);
	 Configure_I2CX_Receive(I2C1_Ten_Address_standard);
	 Configure_I2CX_Receive(I2C1_Seven_Address_high);
	 Configure_I2CX_Receive(I2C1_Ten_Address_high);
	 Configure_I2CX_Receive(I2C1_Seven_Address_more_high);
	 /*Test Sequence I2C1 send*/
	 Configure_I2CX_Send(I2C1_Seven_Address_standard);
	 Configure_I2CX_Send(I2C1_Ten_Address_standard);
	 Configure_I2CX_Send(I2C1_Seven_Address_high);
	 Configure_I2CX_Send(I2C1_Ten_Address_high);
	 Configure_I2CX_Send(I2C1_Seven_Address_more_high);
	 #endif
   while(1){
      
   }
}

/*!
    \brief      Configure Param of I2Cx I2Cx Send data
    \param[in]  Test_Sequence_Enum measure_sequence //test sequence
    \param[out] none
    \retval     none
*/
void Configure_I2CX_Send(Test_Sequence_Enum measure_sequence)
{	
	switch(measure_sequence)
	{
		case I2C0_Seven_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Seven_Address_standard);
      I2Cx_Init(&I2Cx_Param);
      Slaver_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C0 Seven Address standard send success\n");
	  break;
		case I2C0_Ten_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Ten_Address_standard);
      I2Cx_Init(&I2Cx_Param);
      Slaver_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
      printf("I2C0_Ten_Address_standard send success\n");		
	  break;
		case I2C0_Seven_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Seven_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
      Slaver_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
      printf("I2C0_Seven_Address_high send success\n");		
	  break;
		case I2C0_Ten_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Ten_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
      Slaver_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C0_Ten_Address_high send success\n");
	  break;
		case I2C0_Seven_Address_more_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Seven_Address_more_high);	
		  I2Cx_Init(&I2Cx_Param);
      Slaver_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C0_Seven_Address_more_high send success\n");
	  break;
		case I2C1_Seven_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Seven_Address_standard);	
      I2Cx_Init(&I2Cx_Param);
      Slaver_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1 Seven Address standard send success\n");
	  break;
		case I2C1_Ten_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Ten_Address_standard);
      I2Cx_Init(&I2Cx_Param);
      Slaver_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Ten_Address_standard send success\n");	
	  break;
		case I2C1_Seven_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Seven_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
      Slaver_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Seven_Address_high send success\n");
	  break;
		case I2C1_Ten_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Ten_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
      Slaver_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Ten_Address_high send success\n");
	  break;
		case I2C1_Seven_Address_more_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Seven_Address_more_high);	
		  I2Cx_Init(&I2Cx_Param);
      Slaver_SendData_address(write_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Seven_Address_more_high send success\n");
	  break;
		default:
		break;
	}
}

/*!
    \brief      Configure Param of receive data
    \param[in]  Test_Sequence_Enum measure_sequence //test sequence
    \param[out] none
    \retval     none
*/
void Configure_I2CX_Receive(Test_Sequence_Enum measure_sequence)
{
 	switch(measure_sequence)
	{
		case I2C0_Seven_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Seven_Address_standard);
      I2Cx_Init(&I2Cx_Param);
      Slaver_ReceiveData_address(receive_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C0_Seven_Address_standard receive data success!!\n");
	  break;
		case I2C0_Ten_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Ten_Address_standard);
      I2Cx_Init(&I2Cx_Param);
      Slaver_ReceiveData_address(receive_buffer,BufferNum,&I2Cx_Param);	
		  printf("I2C0_Ten_Address_standard receive data success!!\n");
	  break;
		case I2C0_Seven_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Seven_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
      Slaver_ReceiveData_address(receive_buffer,BufferNum,&I2Cx_Param);	
		  printf("I2C0_Seven_Address_high receive data success!!\n");
	  break;
		case I2C0_Ten_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Ten_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
      Slaver_ReceiveData_address(receive_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C0_Ten_Address_high receive data success!!\n");
	  break;
		case I2C0_Seven_Address_more_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C0_Seven_Address_more_high);	
		  I2Cx_Init(&I2Cx_Param);
      Slaver_ReceiveData_address(receive_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C0_Ten_Address_high receive data success!!\n");
	  break;
		case I2C1_Seven_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Seven_Address_standard);	
      I2Cx_Init(&I2Cx_Param);
      Slaver_ReceiveData_address(receive_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Seven_Address_standard receive data success!!\n");
	  break;
		case I2C1_Ten_Address_standard:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Ten_Address_standard);
      I2Cx_Init(&I2Cx_Param);
      Slaver_ReceiveData_address(receive_buffer,BufferNum,&I2Cx_Param);
	    printf("I2C1_Ten_Address_standard receive data success!!\n");
	  break;
		case I2C1_Seven_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Seven_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
      Slaver_ReceiveData_address(receive_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Seven_Address_high receive data success!!\n");
	  break;
		case I2C1_Ten_Address_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Ten_Address_high);	
		  I2Cx_Init(&I2Cx_Param);
      Slaver_ReceiveData_address(receive_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Ten_Address_high receive data success!!\n");
	  break;
		case I2C1_Seven_Address_more_high:
		  Param_Init(&I2Cx_Param,Para_Aarry,I2C1_Seven_Address_more_high);	
		  I2Cx_Init(&I2Cx_Param);
      Slaver_ReceiveData_address(receive_buffer,BufferNum,&I2Cx_Param);
		  printf("I2C1_Ten_Address_high receive data success!!\n");
	  break;
		default:
		break;
	}
}

/*!
    \brief      Configure Param of I2Cx receive data
    \param[in]  Test_Sequence_Enum measure_sequence //test sequence
    \param[out] none
    \retval     none
*/
void Param_Init(Param_Typedef* i2c_param,Param_Typedef* Param_Array,Test_Sequence_Enum measure_sequence)
{
   i2c_param->Memory_address=Param_Array[measure_sequence].Memory_address;
	 i2c_param->gpio_sclpin=Param_Array[measure_sequence].gpio_sclpin;
	 i2c_param->gpio_sdapin=Param_Array[measure_sequence].gpio_sdapin;
	 i2c_param->address=Param_Array[measure_sequence].address;
	 i2c_param->address_model=Param_Array[measure_sequence].address_model;
	 i2c_param->I2Cx_Periph=Param_Array[measure_sequence].I2Cx_Periph;
	 i2c_param->I2c_speed=Param_Array[measure_sequence].I2c_speed;
	 i2c_param->slaver_address=Param_Array[measure_sequence].slaver_address;
}

/*!
    \brief      I2C init
    \param[in]  I2Cx_PinSDA_Enum SDA pin
		            I2Cx_PinSCL_Enum SCL pin
								rcu_periph_enum  I2C periph
		            I2Cx_Speed_enum check clock frequence
								Address_Model_Enum 7 or 10 address check 
								Slaver_Address_Enum 7 or 10 address 
    \param[out] none
    \retval     none
*/
void I2Cx_Init(Param_Typedef *i2c_init)
{
	uint32_t gpiox_sda,pinx_sda,afx_sda,gpiox_scl,pinx_scl,afx_scl;
	I2Cx_Pin_ClockEnable(i2c_init->gpio_sdapin,i2c_init->gpio_sclpin);//SCL and SDA GPIO enable
	/*GPIO sda configure*/
	gpiox_sda=(uint32_t)((i2c_init->gpio_sdapin)& 0xffffff00);
	pinx_sda=(0x01<<((i2c_init->gpio_sdapin & 0xf0) >> 4));
	afx_sda=AF((i2c_init->gpio_sdapin & 0x0f));
	I2Cx_Pin_ClockEnable(i2c_init->gpio_sdapin,i2c_init->gpio_sclpin);
	gpio_af_set(gpiox_sda, afx_sda, pinx_sda);//IO口引脚复用功能
	gpio_mode_set(gpiox_sda, GPIO_MODE_AF, GPIO_PUPD_PULLUP,pinx_sda);//GPIO口、备用功能、端口上拉模式、具体引脚
	gpio_output_options_set(gpiox_sda, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,pinx_sda);//GPIO口、推挽输出及开漏输出、输出速率、具体引脚
	/*GPIO scl configure*/
	gpiox_scl=(uint32_t)((i2c_init->gpio_sclpin)& 0xffffff00);
	pinx_scl=(0x01<<((i2c_init->gpio_sclpin & 0xf0) >> 4));
	afx_scl=AF((i2c_init->gpio_sclpin & 0x0f));
	gpio_af_set(gpiox_scl, afx_scl,pinx_scl);//IO口引脚复用功能
	gpio_mode_set(gpiox_scl, GPIO_MODE_AF, GPIO_PUPD_PULLUP,pinx_scl);//GPIO口、备用功能、端口上拉模式、具体引脚
	gpio_output_options_set(gpiox_scl, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,pinx_scl);//GPIO口、推挽输出及开漏输出、输出速率、具体引脚
	/*--------------------------------I2C module initaial configure------------------------------------*/
	/*enable I2C clock*/
	rcu_periph_clock_enable(i2c_init->I2Cx_Periph);//使能I2C时钟
	/*configure I2C clock*/
  i2c_clock_config(i2c_init->Memory_address,i2c_init->I2c_speed,I2C_DTCY_2);//I2C的基地址、I2C数据传输速度、I2C的快速模式
	/*configure I2C address*/
  i2c_mode_addr_config(i2c_init->Memory_address,I2C_I2CMODE_ENABLE,i2c_init->address_model,i2c_init->slaver_address);//I2C基地址、I2C模式、7位地址模式、I2C从机地址
	/*enable I2C0*/
  i2c_enable(i2c_init->Memory_address);//I2C外设使能
  /*enable acknowledge*/
	i2c_ack_config(i2c_init->Memory_address,I2C_ACK_ENABLE);//选择是否发送应答信号
}

/*!
    \brief      I2C GPIO Clock enable
    \param[in]  I2Cx_PinSDA_Enum SDA pin
		            I2Cx_PinSCL_Enum SCL pin
    \param[out] none
    \retval     none
*/
void I2Cx_Pin_ClockEnable(I2Cx_PinSDA_Enum gpio_sdapin,I2Cx_PinSCL_Enum gpio_sclpin)
{
	uint32_t gpiox_sda,gpiox_scl;
	gpiox_sda=(uint32_t)(gpio_sdapin & 0xffffff00);
	gpiox_scl=(uint32_t)(gpio_sclpin & 0xffffff00);
	/*SDA enable*/
	if(gpiox_sda==GPIOB){
	  rcu_periph_clock_enable(RCU_GPIOB);	
	}else if(gpiox_sda==GPIOA){
	  rcu_periph_clock_enable(RCU_GPIOC);	
	}else if(gpiox_sda==GPIOF){
		rcu_periph_clock_enable(RCU_GPIOF);	
	}
	/*SCL enable*/
	if(gpiox_scl==GPIOB){
	  rcu_periph_clock_enable(RCU_GPIOB);	
	}else if(gpiox_scl==GPIOA){
	  rcu_periph_clock_enable(RCU_GPIOA);	
	}
}

/*!
    \brief      Slaver receive data
    \param[in]  uint8_t* SendBuffer //receive buffer
		            uint8_t DataNum //receive data num
                Param_Typedef *i2c_init //define I2CX init param
    \param[out] none
    \retval     none
*/
void Slaver_ReceiveData_address(uint8_t* ReceiveBuffer,uint8_t DataNum,Param_Typedef *i2c_init)
{
	/*waiting I2C_FLAG_ADDSEND is set 1*/
	  while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_ADDSEND));
  /*read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND*/
  i2c_flag_clear(i2c_init->Memory_address,I2C_FLAG_ADDSEND);//清除ADDSEND位	
  while(DataNum){
		/*I2C_DATA is not empty*/
	  while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_RBNE));
		*ReceiveBuffer=i2c_data_receive(i2c_init->Memory_address);//read data from I2C_DATA
		ReceiveBuffer+=1;
		DataNum-=1;
	}
	while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_STPDET));
	/*clear STPDET flag*/
	I2C_STAT0(i2c_init->Memory_address);
	I2C_CTL0(i2c_init->Memory_address)=0x0000;
	//printf("slaver receive data success!!\n");
}

/*!
    \brief      I2C slaver send buffer 7 and 10 address
    \param[in]  uint8_t* SendBuffer  //receive buffer
		            uint8_t DataNum      //receive data num
                Param_Typedef *i2c_init //define I2CX init param
    \param[out] none
    \retval     none
*/
void Slaver_SendData_address(uint8_t* SendBuffer,uint8_t DataNum,Param_Typedef *i2c_init)
{
	uint8_t num;
	/*waiting I2C_FLAG_ADDSEND is set 1*/
	  while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_ADDSEND));
  /*read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND*/
  i2c_flag_clear(i2c_init->Memory_address,I2C_FLAG_ADDSEND);//清除ADDSEND位	
	if(i2c_init->address_model==I2Cx_Address_10bit){
	  /*wait until ADDSEND bit is set*/
    while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_ADDSEND));
		/*read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND*/
    i2c_flag_clear(i2c_init->Memory_address,I2C_FLAG_ADDSEND);//清除ADDSEND位	
	}
	/*wait until the transmit data buffer is empty*/
  while(SET != i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_TBE));
	//send one byte to I2C BUS
	i2c_data_transmit(i2c_init->Memory_address,*SendBuffer);
	SendBuffer+=1;
	while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_BTC));
	//send two byte to I2C BUS
	i2c_data_transmit(i2c_init->Memory_address,*SendBuffer);
	SendBuffer+=1;
	for(num=0;num<(DataNum-2);num++){
	  /*I2C_DATA is not empty*/
	  while(!i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_BTC));
		i2c_data_transmit(i2c_init->Memory_address,*SendBuffer);
    SendBuffer+=1;
	}
	/*wait until the transmit data buffer is empty*/
  while(SET != i2c_flag_get(i2c_init->Memory_address,I2C_FLAG_AERR));
	//clear I2C AERR flag
	i2c_flag_clear(i2c_init->Memory_address,I2C_FLAG_AERR);
}

/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
    usart_data_transmit(EVAL_COM, (uint8_t)ch);
    while(RESET == usart_flag_get(EVAL_COM, USART_FLAG_TBE));
    return ch;
}

/*!
    \brief      this function handles SysTick exception
    \param[in]  none
    \param[out] none
    \retval     none
*/
void SysTick_Handler(void)
{
    delay_decrement();
}

以上从机接收和发送代码和主机一一对应,两者可作为测试使用。I2C从机支持双地址、10bit地址和广播地址模式(0x00)。双地址模式:I2C从机设备可对两个地址响应。广播地址模式:所有I2C从机设备默认的响应地址。

//双地址模式
 i2c_dualaddr_enable(I2C0,0x44);
//广播地址
 i2c_slave_response_to_gcall_config(I2C0, I2C_GCEN_ENABLE);

1.5 主机中断接收发送程序

//主机中断发送
int main(void)
{
	 uint8_t num=0;
   /*configure EVAL_COM1*/
   gd_eval_com_init(EVAL_COM);
	 systick_config();
	 for(num=0;num<BufferNum;num++){
		 write_buffer[num]=num;
	 }
	 printf("I2C master send by interrupt measuring!!!");
	 Param_Init(&I2Cx_Param,Para_Aarry,I2C_Measuring);
	 I2Cx_Init(&I2Cx_Param);
	 nvic_irq_enable(I2Cx_EV_IRQn,0,0);/*!< I2C0 event interrupt priority and enable*/  
	 nvic_irq_enable(I2Cx_ER_IRQn,0,1);/*!< I2C0 erro  interrupt priority and enable*/
	 i2c_interrupt_enable(I2C_x,I2C_INT_ERR);//error interrupt enable 
	 i2c_interrupt_enable(I2C_x,I2C_INT_EV);//event interrupt enable
	 i2c_interrupt_enable(I2C_x,I2C_INT_BUF);//buffer interrupt enable
   delay_1ms(3000);
    /*wait until I2C bus is idle*/
	   while(i2c_flag_get(I2C_x,I2C_FLAG_I2CBSY));
	 /*send a start condition to I2C bus*/
	i2c_start_on_bus(I2C_x);//在I2C总线上产生一个开始信号
	  while(!Send_InterruptFlag);
	/*wait until the stop condition is finished*/
  while(I2C_CTL0(I2C_x)&0x0200);//等待结束信号发送
  printf("I2C0 master interrupt send success!!");		 
   while(1){
      
   }
}
/*!
    \brief      this function handles I2C0 Event
    \param[in]  none
    \param[out] none
    \retval     none
*/
void I2C0_EV_IRQHandler(void)
{
	if(i2c_flag_get(I2C_x,I2C_FLAG_SBSEND)){
		 I2C_STAT0(I2C_x);
		 /*send slave address to I2C bus */
     i2c_master_addressing(I2C_x,0x42,I2C_TRANSMITTER);//发送从机地址+写、清除SBSEND位、I2C设备发送方
	}else if(i2c_flag_get(I2C_x,I2C_FLAG_ADDSEND)){
	   i2c_flag_clear(I2C_x,I2C_FLAG_ADDSEND);//清除ADDSEND位	
	}else if(i2c_flag_get(I2C_x,I2C_FLAG_TBE)){
		if(Data<20){
	     i2c_data_transmit(I2C_x,write_buffer[Data]);
		   Data+=1;
		}else{
			 i2c_stop_on_bus(I2C_x);//在总线上发送停止信号位
       Send_InterruptFlag=1;	
       i2c_interrupt_disable(I2C_x,I2C_INT_ERR);//error interrupt enable 
	     i2c_interrupt_disable(I2C_x,I2C_INT_EV);//event interrupt enable
	     i2c_interrupt_disable(I2C_x,I2C_INT_BUF);//buffer interrupt enable	
		}
	}
}

/*!
    \brief      this function handles I2C0 Error
    \param[in]  none
    \param[out] none
    \retval     none
*/
void I2C0_ER_IRQHandler(void)
{
	//SMBus Alert status
	if(i2c_flag_get(I2C_x,I2C_FLAG_SMBALT)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_SMBALT);
	}
	//timeout signal in SMBus mode
	if(i2c_flag_get(I2C_x,I2C_FLAG_SMBTO)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_SMBTO);
	}
	//PEC error when receiving data
	if(i2c_flag_get(I2C_x,I2C_FLAG_PECERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_PECERR);
	}
	//over-run or under-run situation occurs in slave mode
	if(i2c_flag_get(I2C_x,I2C_FLAG_OUERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_OUERR);
	}
	//acknowledge error
	if(i2c_flag_get(I2C_x,I2C_FLAG_AERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_AERR);
	}
	//arbitration lost in master mode
	if(i2c_flag_get(I2C_x,I2C_FLAG_LOSTARB)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_LOSTARB);
	}
	//a bus error 
	if(i2c_flag_get(I2C_x,I2C_FLAG_BERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_BERR);
	}
}
//主机接收中断
/*!
    \brief      this function handles I2C0 Event
    \param[in]  none
    \param[out] none
    \retval     none
*/
void I2C0_EV_IRQHandler(void)
{
	if(i2c_flag_get(I2C_x,I2C_FLAG_SBSEND)){
		 I2C_STAT0(I2C_x);
		 /*send slave address to I2C bus */
     i2c_master_addressing(I2C_x,0x42,I2C_RECEIVER);//发送从机地址+写、清除SBSEND位、I2C设备发送方
	}
	if(i2c_flag_get(I2C_x,I2C_FLAG_ADDSEND)){
	   i2c_flag_clear(I2C_x,I2C_FLAG_ADDSEND);//清除ADDSEND位	
	}
	if(i2c_flag_get(I2C_x,I2C_FLAG_RBNE)){
		 if(Data==18){
			 receive_buffer[Data]=i2c_data_receive(I2C_x);
			 Data+=1;
			 /*disable acknowledge*/
	     i2c_ack_config(I2C_x,I2C_ACK_DISABLE);//选择是否发送应答信号
			 i2c_stop_on_bus(I2C_x);//在总线上发送停止信号位
		 }else if(Data<18){
	     receive_buffer[Data]=i2c_data_receive(I2C_x);
		   Data+=1;
		 }else if(Data==19)
		 {
		   receive_buffer[Data]=i2c_data_receive(I2C_x);
       Receive_InterruptFlag=1;	
       i2c_interrupt_disable(I2C_x,I2C_INT_ERR);//error interrupt enable 
	     i2c_interrupt_disable(I2C_x,I2C_INT_EV);//event interrupt enable
	     i2c_interrupt_disable(I2C_x,I2C_INT_BUF);//buffer interrupt enable			 			 
		 }	 
	}
}

/*!
    \brief      this function handles I2C0 Error
    \param[in]  none
    \param[out] none
    \retval     none
*/
void I2C0_ER_IRQHandle(void)
{
	//SMBus Alert status
	if(i2c_flag_get(I2C_x,I2C_FLAG_SMBALT)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_SMBALT);
	}
	//timeout signal in SMBus mode
	if(i2c_flag_get(I2C_x,I2C_FLAG_SMBTO)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_SMBTO);
	}
	//PEC error when receiving data
	if(i2c_flag_get(I2C_x,I2C_FLAG_PECERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_PECERR);
	}
	//over-run or under-run situation occurs in slave mode
	if(i2c_flag_get(I2C_x,I2C_FLAG_OUERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_OUERR);
	}
	//acknowledge error
	if(i2c_flag_get(I2C_x,I2C_FLAG_AERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_AERR);
	}
	//arbitration lost in master mode
	if(i2c_flag_get(I2C_x,I2C_FLAG_LOSTARB)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_LOSTARB);
	}
	//a bus error 
	if(i2c_flag_get(I2C_x,I2C_FLAG_BERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_BERR);
	}
}

如果项目程序有多个中断,尽可能将I2C主机接收的中断优先级设为最高,否则会存在主机多接收一个数据,原因:当主机接收一个数据时,RBNE置1,在未读取DATA寄存器中的数据时,被更高的优先级任务打断,I2C总线上又接收一个数据到移位寄存器,此时BTC标志位置1。当中断恢复时,主机读取DATA寄存器中的数据。因为此时BTC已经置1,BTC清除的条件是需先读state状态寄存器,再读DATA寄存器,此时读DATA寄存器,无法清除BTC,使移位寄存器中的数据无法移到数据寄存器,I2C总线SCL被拉低,已阻止接收下一个数据,此时I2C还认为接收两个数据,会再次进中断读取DATA寄存器,BTC清零,移位寄存器数据移到Data寄存器,再次读取下一个数据,会造成接收的数据中有两个前后重复的数据。
1.6 从机中断接收和发送

//从机中断接收
/*!
    \brief      this function handles I2C0 Event
    \param[in]  none
    \param[out] none
    \retval     none
*/
void I2C0_EV_IRQHandler(void)
{
	if(i2c_interrupt_flag_get(I2C_x,I2C_INT_FLAG_ADDSEND)){
		/*read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND*/
    i2c_flag_clear(I2C_x,I2C_FLAG_ADDSEND);//清除ADDSEND位	
	}else if(i2c_interrupt_flag_get(I2C_x,I2C_INT_FLAG_TBE)){	
		 if(Data<20){
       i2c_data_transmit(I2C_x,writer_buffer[Data]);
       Data+=1;			 
		 }else{
			 Send_InterruptFlag=1;
			 i2c_interrupt_disable(I2C_x,I2C_INT_ERR);
	     i2c_interrupt_disable(I2C_x,I2C_INT_EV);
	     i2c_interrupt_disable(I2C_x,I2C_INT_BUF);
		 }	 
	}
}

/*!
    \brief      this function handles I2C0 Error
    \param[in]  none
    \param[out] none
    \retval     none
*/
void I2C0_ER_IRQHandle(void)
{
	//SMBus Alert status
	if(i2c_flag_get(I2C_x,I2C_FLAG_SMBALT)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_SMBALT);
	}
	//timeout signal in SMBus mode
	if(i2c_flag_get(I2C_x,I2C_FLAG_SMBTO)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_SMBTO);
	}
	//PEC error when receiving data
	if(i2c_flag_get(I2C_x,I2C_FLAG_PECERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_PECERR);
	}
	//over-run or under-run situation occurs in slave mode
	if(i2c_flag_get(I2C_x,I2C_FLAG_OUERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_OUERR);
	}
	//acknowledge error
	if(i2c_flag_get(I2C_x,I2C_FLAG_AERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_AERR);
	}
	//arbitration lost in master mode
	if(i2c_flag_get(I2C_x,I2C_FLAG_LOSTARB)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_LOSTARB);
	}
	//a bus error 
	if(i2c_flag_get(I2C_x,I2C_FLAG_BERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_BERR);
	}
}
//从机中断发送
/*!
    \brief      this function handles I2C0 Event
    \param[in]  none
    \param[out] none
    \retval     none
*/
void I2C0_EV_IRQHandler(void)
{
	if(i2c_interrupt_flag_get(I2C_x,I2C_INT_FLAG_ADDSEND)){
		/*read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND*/
    i2c_flag_clear(I2C_x,I2C_FLAG_ADDSEND);//清除ADDSEND位	
	}else if(i2c_interrupt_flag_get(I2C_x,I2C_INT_FLAG_TBE)){	
		 if(Data<20){
       i2c_data_transmit(I2C_x,writer_buffer[Data]);
       Data+=1;			 
		 }else{
			 Send_InterruptFlag=1;
			 i2c_interrupt_disable(I2C_x,I2C_INT_ERR);
	     i2c_interrupt_disable(I2C_x,I2C_INT_EV);
	     i2c_interrupt_disable(I2C_x,I2C_INT_BUF);
		 }	 
	}
}

/*!
    \brief      this function handles I2C0 Error
    \param[in]  none
    \param[out] none
    \retval     none
*/
void I2C0_ER_IRQHandle(void)
{
	//SMBus Alert status
	if(i2c_flag_get(I2C_x,I2C_FLAG_SMBALT)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_SMBALT);
	}
	//timeout signal in SMBus mode
	if(i2c_flag_get(I2C_x,I2C_FLAG_SMBTO)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_SMBTO);
	}
	//PEC error when receiving data
	if(i2c_flag_get(I2C_x,I2C_FLAG_PECERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_PECERR);
	}
	//over-run or under-run situation occurs in slave mode
	if(i2c_flag_get(I2C_x,I2C_FLAG_OUERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_OUERR);
	}
	//acknowledge error
	if(i2c_flag_get(I2C_x,I2C_FLAG_AERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_AERR);
	}
	//arbitration lost in master mode
	if(i2c_flag_get(I2C_x,I2C_FLAG_LOSTARB)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_LOSTARB);
	}
	//a bus error 
	if(i2c_flag_get(I2C_x,I2C_FLAG_BERR)){ 
	  i2c_flag_clear(I2C_x,I2C_FLAG_BERR);
	}
}

主机发送每一个byte数据时,从机都需发送ACK信号,而从机发送数据时,当主机接收到最后一个字节的数据时,给从机发NACK信号,从机接收到NACK信号后,就知道主机要结束通信了。从机SCL拉低功能作用是:从机在接收数据时,由于需要处理其他事情,比如打印一些调试信息,可能没有及时读取DATA寄存器中的数据,这时从机会拉低SCL时钟线已阻止主机发送下一个字节数据,也就是再告诉主机“我正在忙啦!您稍等片刻”,I2C中对这个拉低时间没有具体要求,但是在SMBUS中,对SCL拉低的时间规定为25ms,如果25ms从机还在拉低SCL硬件就会强制发送stop信号结束此次通信(也就是说主机的忍耐是有限度的哈!!)。
这篇就先写这么多,I2C硬件的其他主要特性及代码实现在后面介绍。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值