4019 views|2 replies

565

Posts

0

Resources
The OP
 

[AT-START-F425 Review] + Hardware I2C and software simulation I2C speed comparison [Copy link]

 

1. Introduction

This article uses AT32F425 to drive SSD1306 OLED to test the I2C rate. For detailed code operations on OLED, please refer to [GD32L233C-START Review] 6. Hardware I2C drive 0.96-inch OLED .

2. About I2C of AT32F425

There are two I2Cs, this article uses I2C1.

3. I2C rate

Standard mode ( up to 100kHz )
Fast mode ( up to 400kHz )
Fast mode plus ( up to 1 MHz )
4. I2C clock
Here PCLK1 is 96MHZ
I2C clock configuration is relatively complex, so the official tool is provided
The I2C clock frequency in the tool is PCLK1, which is 96000KHZ.
5. Code implementation
(1) Hardware 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);

}

When using hardware I2C, configure it to a 1MHz rate.

(2) Software 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. Speed test
Here we use the logic analyzer to capture packets directly.
(1) Hardware I2C
It can be seen that the rate jumps between 800kHz and 1MHz.

(2) Software I2C

It can be seen that the rate is between 58kHz and 59kHz.

From the above comparative measurements, we can find that the hardware I2C rate is greater than the software I2C. Therefore, in order to improve the CPU utilization, hardware I2C should be used as much as possible.

This post is from Domestic Chip Exchange

Latest reply

If there is no bug in hardware i2c, hardware peripherals are still preferred.   Details Published on 2022-4-20 18:44
Personal signaturestm32/LoRa物联网:304350312
 
 

7422

Posts

2

Resources
2
 

If there is no bug in hardware i2c, hardware peripherals are still preferred.

This post is from Domestic Chip Exchange

Comments

Yes  Details Published on 2022-4-20 18:50
Personal signature

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

 
 
 

565

Posts

0

Resources
3
 
freebsder posted on 2022-4-20 18:44 If there is no bug in the hardware i2c, hardware peripherals are still preferred

Yes

This post is from Domestic Chip Exchange
Personal signaturestm32/LoRa物联网:304350312
 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list