4085|2

565

帖子

0

TA的资源

一粒金砂(高级)

楼主
 

【AT-START-F425测评】+硬件I2C与软件模拟I2C速率对比 [复制链接]

 

1、前言

本文使用AT32F425驱动SSD1306 OLED来测试I2C的速率,关于OLED的详细代码操作可查【GD32L233C-START评测】6、硬件I2C驱动0.96吋OLED

 

2、关于AT32F425的I2C

  两个I2C,本文使用I2C1。

 

3、I2C速率

标准模式(standard mode,最高 100kHz
快速模式(fast mode,最高 400kHz
增强快速模式(fast mode plus,最高 1 MHz
 
4、I2C时钟
 这里PCLK1为96MHZ
I2C时钟配置比较复杂,所以官方提供了工具 
 工具里面的I2C时钟频率就是PCLK1,即就是96000KHZ。
 
5、代码实现
(1)硬件I2C
#define I2C_OWN_ADDRESS7     0x72
#define I2C_SLAVE_ADDRESS7   0x78  

 

void I2cInit(void)
{
	gpio_init_type gpio_init_structure;
  
    /* i2c periph clock enable */
    crm_periph_clock_enable(CRM_I2C1_PERIPH_CLOCK, TRUE);    
    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
    
    /* gpio configuration */  
    gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE6, GPIO_MUX_1);
    gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE7, GPIO_MUX_1);
    
    /* configure i2c pins: scl */
    gpio_init_structure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_structure.gpio_mode           = GPIO_MODE_MUX;
    gpio_init_structure.gpio_out_type       = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_structure.gpio_pull           = GPIO_PULL_UP;  
                                            
    gpio_init_structure.gpio_pins           = GPIO_PINS_6;
    gpio_init(GPIOB, &gpio_init_structure);

    /* configure i2c pins: sda */
    gpio_init_structure.gpio_pins           = GPIO_PINS_7;
    gpio_init(GPIOB, &gpio_init_structure); 
    
	/* reset i2c peripheral */
	i2c_reset(I2C1);
	
    /* config i2c */ 
	
	//0x2170FAFA   //10K
	//0x80E06565   //50K
	//0x80E03030   //100K
	//0x20E0355F   //200K
	//0x20E0192C   //400k
	//0x10900E19   //1000k
	//0x10900C16   //1000k

    i2c_init(I2C1, 0, 0x10900C16); 
    
    i2c_own_address1_set(I2C1, I2C_ADDRESS_MODE_7BIT, I2C_OWN_ADDRESS7);
  
	/* i2c peripheral enable */   
	i2c_enable(I2C1, TRUE);
}
void OledWriteCmd(uint8_t var)
{
  /* wait for the busy falg to be reset */
  while(i2c_flag_get(I2C1, I2C_BUSYF_FLAG) );
  
  /* start transfer */
  i2c_transmit_set(I2C1, I2C_SLAVE_ADDRESS7, 2, I2C_SOFT_STOP_MODE, I2C_GEN_START_WRITE);
  
  i2c_start_generate(I2C1);
  while(i2c_flag_get(I2C1, I2C_ADDRF_FLAG) );
  
  while(!i2c_flag_get(I2C1, I2C_TDIS_FLAG) );
  i2c_data_send(I2C1, 0x00);
  
  while(!i2c_flag_get(I2C1, I2C_TDIS_FLAG) );
  i2c_data_send(I2C1, var);
  
  i2c_stop_generate(I2C1);

  while(!i2c_flag_get(I2C1, I2C_STOPF_FLAG) );
  i2c_flag_clear(I2C1, I2C_STOPF_FLAG);
  
}

void OledWriteData(uint8_t var)
{
  /* wait for the busy falg to be reset */
  while(i2c_flag_get(I2C1, I2C_BUSYF_FLAG) );
  /* start transfer */
  i2c_transmit_set(I2C1, I2C_SLAVE_ADDRESS7, 2, I2C_AUTO_STOP_MODE, I2C_GEN_START_WRITE);

  while(!i2c_flag_get(I2C1, I2C_TDIS_FLAG) );
  i2c_data_send(I2C1, 0x40);
  
  while(!i2c_flag_get(I2C1, I2C_TDIS_FLAG) );
  i2c_data_send(I2C1, var);
  
  while(!i2c_flag_get(I2C1, I2C_STOPF_FLAG) );
  i2c_flag_clear(I2C1, I2C_STOPF_FLAG);

}

使用硬件I2C的时候,配置为1MHz速率。

(2)软件I2C

#define _SCL_PORT  GPIOB
#define _SCL_PIN   GPIO_PINS_6  

#define _SDA_PORT  GPIOB
#define _SDA_PIN   GPIO_PINS_7

void _I2C_Init(void)
{
	gpio_init_type gpio_init_struct;

	/* enable the led clock */
	crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

	/* set default parameter */
	gpio_default_para_init(&gpio_init_struct);

	/* configure the led gpio */
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
	gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
	gpio_init_struct.gpio_pins = GPIO_PINS_6|GPIO_PINS_7;
	gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
	gpio_init(GPIOB, &gpio_init_struct);
}


void _SDA_IN(void)
{
	gpio_init_type gpio_init_struct;

	/* enable the led clock */
	crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

	/* set default parameter */
	gpio_default_para_init(&gpio_init_struct);

	/* configure the led gpio */
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
	gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
	gpio_init_struct.gpio_pins = GPIO_PINS_7;
	gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
	gpio_init(GPIOB, &gpio_init_struct);
}


void _SDA_OUT(void)
{
	gpio_init_type gpio_init_struct;

	/* enable the led clock */
	crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

	/* set default parameter */
	gpio_default_para_init(&gpio_init_struct);

	/* configure the led gpio */
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
	gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
	gpio_init_struct.gpio_pins = GPIO_PINS_7;
	gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
	gpio_init(GPIOB, &gpio_init_struct);
}

void _I2C_Start(void)
{
	_SDA_OUT();  //
	gpio_bits_set(_SDA_PORT,_SDA_PIN);  //SDA=1
	delay_us(10);
	gpio_bits_set(_SCL_PORT,_SCL_PIN);  //SCL=1
	delay_us(10);
	gpio_bits_reset(_SDA_PORT,_SDA_PIN);//SDA=0
	delay_us(10);
	gpio_bits_reset(_SCL_PORT,_SCL_PIN);//SCL=0
	delay_us(10);
}

void _I2C_Stop(void)
{
	_SDA_OUT();
	
	gpio_bits_reset(_SDA_PORT,_SDA_PIN);//SDA=0
	delay_us(10);
	gpio_bits_set(_SCL_PORT,_SCL_PIN);  //SCL=1
	delay_us(10);
	gpio_bits_set(_SDA_PORT,_SDA_PIN);  //SDA=1
	delay_us(10);
}


void _I2C_Ack(void)
{
	_SDA_OUT();
	gpio_bits_reset(_SDA_PORT,_SDA_PIN);//SDA=0
	delay_us(5);
	gpio_bits_set(_SCL_PORT,_SCL_PIN);  //SCL=1
	delay_us(5);
	gpio_bits_reset(_SCL_PORT,_SCL_PIN); //SCL=0
}


void _I2C_NAck(void)
{
	gpio_bits_set(_SDA_PORT,_SDA_PIN);  //SDA=1
    delay_us(10);
    gpio_bits_set(_SCL_PORT,_SCL_PIN);  //SCL=1
    delay_us(10);
    gpio_bits_reset(_SCL_PORT,_SCL_PIN);  //SCL=0
	delay_us(10);	
}


uint8_t _I2C_Wait_Ack(void)
{
	uint8_t ucErrTime=0;

	gpio_bits_set(_SDA_PORT,_SDA_PIN);  //释放总线
	 _SDA_IN();

	delay_us(5);
	gpio_bits_set(_SCL_PORT,_SCL_PIN);  //SCL=1
	delay_us(5);
	while(gpio_input_data_bit_read(_SDA_PORT,_SDA_PIN))  //gpio_input_data_bit_read
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			_I2C_Stop();
			return 1;
		}
	}
	gpio_bits_reset(_SCL_PORT,_SCL_PIN);  //SCL=0
	delay_us(5);
	return 0;
}


uint8_t _I2C_Read_Byte(uint8_t ack)
{
	uint8_t i,rxdata=0;

	gpio_bits_set(_SDA_PORT,_SDA_PIN);  //释放总线
	_SDA_IN();

	for(i=0;i<8;i++ )
	{
		gpio_bits_reset(_SCL_PORT,_SCL_PIN);  //SCL=0
		delay_us(5);
		gpio_bits_set(_SCL_PORT,_SCL_PIN);  //SCL=1
		delay_us(5);
		rxdata<<=1;
		if(gpio_input_data_bit_read(_SDA_PORT,_SDA_PIN))
		{
			rxdata|=0x01;
		}
		delay_us(5);
	}
    if (!ack)
		_I2C_NAck();//nACK
    else
		_I2C_Ack(); //ACK
		
    return rxdata;
}

void _I2C_Send_Byte(uint8_t txd)
{
	uint8_t i;
	
	_SDA_OUT();
	gpio_bits_reset(_SCL_PORT,_SCL_PIN);  //SCL=0

	for(i=0;i<8;i++)
	{
		if((txd&0x80)==0x80)
			gpio_bits_set(_SDA_PORT,_SDA_PIN);
		else
			gpio_bits_reset(_SDA_PORT,_SDA_PIN);
				
		txd<<=1;
		delay_us(5);
		gpio_bits_set(_SCL_PORT,_SCL_PIN);  //SCL=1
		delay_us(5);
		gpio_bits_reset(_SCL_PORT,_SCL_PIN);  //SCL=0
		delay_us(5);
	}
}
void _SSD1306_WriteCmd(uint8_t var)
{
	_I2C_Start();
	_I2C_Send_Byte(I2C_SLAVE_ADDRESS7); //write addr
	_I2C_Wait_Ack();
	_I2C_Send_Byte(0x00);
	_I2C_Wait_Ack();
	_I2C_Send_Byte(var);
	_I2C_Wait_Ack();
	_I2C_Stop();
}


void _SSD1306_WriteData(uint8_t var)
{
	_I2C_Start();
	_I2C_Send_Byte(I2C_SLAVE_ADDRESS7); //write addr
	_I2C_Wait_Ack();
	_I2C_Send_Byte(0x40);
	_I2C_Wait_Ack();
	_I2C_Send_Byte(var);
	_I2C_Wait_Ack();
	_I2C_Stop();
}

 

6、速率测试
这里直接使用逻辑分析仪抓包。
(1)硬件I2C
   可以看出速率在800kHz到1MHz之间跳动。

(2)软件I2C

 

 可以看出速率在58kHz到59kHz之间。

 

从以上对比测量,可以发现,硬件I2C速率大于软件I2C,因此为了提高cpu的利用率,应尽量选择使用硬件2C。

 

 

最新回复

硬件i2c没bug的情况下还是优选硬件外设   详情 回复 发表于 2022-4-20 18:44
点赞 关注
个人签名stm32/LoRa物联网:304350312
 
 

回复
举报

7452

帖子

2

TA的资源

五彩晶圆(高级)

沙发
 

硬件i2c没bug的情况下还是优选硬件外设

点评

是的  详情 回复 发表于 2022-4-20 18:50
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 
 

回复

565

帖子

0

TA的资源

一粒金砂(高级)

板凳
 
freebsder 发表于 2022-4-20 18:44 硬件i2c没bug的情况下还是优选硬件外设

是的

个人签名stm32/LoRa物联网:304350312
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表