[MCU] 【AT-START-F425测评】+硬件SPI与软件模拟SPI速率对比

freeelectron   2022-4-19 17:24 楼主

1、前言

本文使用AT32F425驱动RC522来测试SPI1的速率,关于RC522的详细代码操作可查帖子【GD32L233C-START评测】7、硬件SPI1驱动RC522

 

2、关于AT32F425的SPI

image.png   image.png  AT32F425系列最多有3个spi,本文使用SPI1。

 

3、SPI1的最大速率

image.png  SPI1挂在APB2总线上,APB2总线的最大速率是96MHz;

image.png  SPI的最大速率为fPCLK/2,即48Mhz。

 

4、代码实现

    /*SPI1 :  
        PA4/CS  
        PA5/SCK    
        PA6/MISO   
        PA7/MOSI    
    */

(1)模拟SPI

#define SET_SPI_CS      gpio_bits_set(GPIOA, GPIO_PINS_4)
#define CLR_SPI_CS      gpio_bits_reset(GPIOA, GPIO_PINS_4) 

#define SET_SPI_SCLK() gpio_bits_set(GPIOA,GPIO_PINS_5)
#define CLR_SPI_SCLK() gpio_bits_reset(GPIOA,GPIO_PINS_5)//SCL=SCLK

#define SET_SPI_MOSI() gpio_bits_set(GPIOA,GPIO_PINS_7)
#define CLR_SPI_MOSI() gpio_bits_reset(GPIOA,GPIO_PINS_7)//SDO=MOSI

#define READ_SPI_MISO() gpio_input_data_bit_read(GPIOA,GPIO_PINS_6) //SDI=MISO

void SpiIoInit(void)
{	
	crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

	gpio_init_type gpio_initstructure;
	
    /* configure the lcd gpio */
	gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_initstructure.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
	gpio_initstructure.gpio_mode = GPIO_MODE_OUTPUT;
	gpio_initstructure.gpio_pins = GPIO_PINS_4|GPIO_PINS_5|GPIO_PINS_7;
	gpio_initstructure.gpio_pull = GPIO_PULL_NONE;
	gpio_init(GPIOA, &gpio_initstructure);
	
	gpio_bits_set(GPIOA,GPIO_PINS_4|GPIO_PINS_5|GPIO_PINS_7);
	
	gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_initstructure.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
	gpio_initstructure.gpio_mode = GPIO_MODE_INPUT;
	gpio_initstructure.gpio_pins = GPIO_PINS_6;
	gpio_initstructure.gpio_pull = GPIO_PULL_NONE;
	gpio_init(GPIOA, &gpio_initstructure);
	
	gpio_bits_set(GPIOA,GPIO_PINS_6);
	
}

uint8_t  SPIWriteByte(uint8_t dat)
{
	uint16_t ret=0;

	u8 i;
	
	for(i=0;i<8;i++)
	{			  
		if(dat&0x80)
		{
		   SET_SPI_MOSI();
		}
		else
		{
		   CLR_SPI_MOSI();
		}
		dat<<=1;
//		delay_us(1);
	
		SET_SPI_SCLK();
		ret<<=1;
		
		if(READ_SPI_MISO())
		{
			ret+=1;
		}
//		delay_us(1);
		CLR_SPI_SCLK();
	}

	return (ret&0x0ff);
}

(2)硬件SPI

void SpiIoInit(void)
{	
	gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
	gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
	gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;
	gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_initstructure.gpio_pins = GPIO_PINS_4;
	gpio_init(GPIOA, &gpio_initstructure);
  
	gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE5, GPIO_MUX_0);
	gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE6, GPIO_MUX_0);
	gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE7, GPIO_MUX_0);

	gpio_default_para_init(&gpio_initstructure);

	gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
	gpio_initstructure.gpio_pull           = GPIO_PULL_DOWN;
	gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
	gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_initstructure.gpio_pins = GPIO_PINS_5;
	gpio_init(GPIOA, &gpio_initstructure);

	gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
	gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
	gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
	gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_initstructure.gpio_pins = GPIO_PINS_6;
	gpio_init(GPIOA, &gpio_initstructure);

	gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
	gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
	gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
	gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_initstructure.gpio_pins = GPIO_PINS_7;
	gpio_init(GPIOA, &gpio_initstructure);
	
	spi_init_type spi_init_struct;

	crm_periph_clock_enable(CRM_SPI1_PERIPH_CLOCK, TRUE);

	spi_default_para_init(&spi_init_struct);
	spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
	spi_init_struct.master_slave_mode = SPI_MODE_MASTER;
	spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_8;
	spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
	spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
	spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_LOW;
	spi_init_struct.clock_phase = SPI_CLOCK_PHASE_1EDGE;
	spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
	spi_init(SPI1, &spi_init_struct);

	spi_enable(SPI1, TRUE);
}


uint8_t  SPIWriteByte(uint8_t dat)
{
	uint16_t ret=0;

	while(spi_i2s_flag_get(SPI1, SPI_I2S_TDBE_FLAG) == RESET) {};
    spi_i2s_data_transmit(SPI1, dat);
		
    while(spi_i2s_flag_get(SPI1, SPI_I2S_RDBF_FLAG) == RESET) {};
    ret=spi_i2s_data_receive(SPI1);
			
	return (ret&0x0ff);
}

使用硬件SPI测试时,RC522的最大速率只能到12MHZ,也就是8分频,速率再大会导致通信不上。

5、速率测量

这里直接用示波器抓CLK的波形

(1)模拟SPI
image.png image.png  可以看出,使用模拟SPI的时候是1.8MHz,用逻辑分析仪抓取也是这个结果。

(2)硬件SPI
image.png image.png  可以看出,使用硬件SPI的时候是12MHz,与软件设定的一致,用逻辑分析仪抓取也是这个结果。

 

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

 

 

本帖最后由 freeelectron 于 2022-4-19 17:31 编辑
stm32/LoRa物联网:304350312

回复评论 (5)

一般IIC会用软件的,SPI一般采用硬件的。

用SPI讲究的就是快!

点赞  2022-4-19 18:19
引用: wangerxian 发表于 2022-4-19 18:19 一般IIC会用软件的,SPI一般采用硬件的。 用SPI讲究的就是快!

对比一下,看看到底能有多快

stm32/LoRa物联网:304350312
点赞  2022-4-19 19:15
引用: freeelectron 发表于 2022-4-19 19:15 对比一下,看看到底能有多快

哈哈,那你应该试试48MHz的,看看输出的准不准。

点赞  2022-4-19 19:23

可能很少有模块支持48MHz,不过你只写数据的话,不接模块应该也没问题。

点赞  2022-4-19 19:24
引用: wangerxian 发表于 2022-4-19 19:24 可能很少有模块支持48MHz,不过你只写数据的话,不接模块应该也没问题。

有写有读的,大于12mhz,器件就通信异常了

stm32/LoRa物联网:304350312
点赞  2022-4-19 19:27
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复