lulugl 发表于 2023-11-7 12:27

【AT-START-F423测评】 硬件SPI与模拟spi中时钟信号与分频之疑惑

@21小跑堂

今天在调试spi驱动TFT屏,发现spi的硬件spi时钟时序与软件的时序的波形是有大的差别。
【测试环境】
IDE:MDK5.38
spi的驱动,使用摸拟与硬件通过条件编译来选择切换,代码如下:

//作    者   : 刘建华
//生成日期   : 2023-11-7
//最近修改   :
//功能描述   :AT32F435 GC9306
//            说明:
//            ----------------------------------------------------------------
//            GND   电源地
//            VCC   3.3v电源
//            SCL   PA13(SCLK)
//            SDA   PA14(MOSI)
//            RES   PA0
//            DC    PA1
//            CS    PA12
//            BLK   PA3
//            ----------------------------------------------------------------
// 修改历史   :
// 日    期   :
//All rights reserved
//******************************************************************************/


#define SOFTWARE_SPI_ENABLE 0

void LCD_GPIO_Init(void)
{
   gpio_init_type gpio_init_struct;

   spi_init_type spi_init_struct;

    /* 使能GPIOA GPIOB时钟 */

                crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
                crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

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

#if SOFTWARE_SPI_ENABLE      

      /* 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_4|GPIO_PINS_5|GPIO_PINS_7;
      gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
      gpio_init(GPIOA, &gpio_init_struct);      
      gpio_bits_set(GPIOA,GPIO_PINS_4|GPIO_PINS_5|GPIO_PINS_7);

#else      

      /*SPI1 :
                PA4/CS
                PA5/SCK   
                PA6/MISO   
                PA7/MOSI   
      */   
      gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
      gpio_init_struct.gpio_pull         = GPIO_PULL_UP;
      gpio_init_struct.gpio_mode         = GPIO_MODE_OUTPUT;
      gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
      gpio_init_struct.gpio_pins = GPIO_PINS_4;
      gpio_init(GPIOA, &gpio_init_struct);
      
      gpio_bits_set(GPIOA,GPIO_PINS_4);

      gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE5, GPIO_MUX_5);
      gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE6, GPIO_MUX_5);
      gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE7, GPIO_MUX_5);
      gpio_default_para_init(&gpio_init_struct);

      gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;

      gpio_init_struct.gpio_pull         = GPIO_PULL_NONE;
      gpio_init_struct.gpio_mode         = GPIO_MODE_MUX;
      gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
      gpio_init_struct.gpio_pins = GPIO_PINS_5;
      gpio_init(GPIOA, &gpio_init_struct);


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


      gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
      gpio_init_struct.gpio_pull         = GPIO_PULL_NONE;
      gpio_init_struct.gpio_mode         = GPIO_MODE_MUX;
      gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
      gpio_init_struct.gpio_pins = GPIO_PINS_7 | GPIO_PINS_6;
      gpio_init(GPIOA, &gpio_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_2;
      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_HIGH;//SPI_CLOCK_POLARITY_HIGH
      spi_init_struct.clock_phase = SPI_CLOCK_PHASE_2EDGE;       //SPI_CLOCK_PHASE_2EDGE
      spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
      spi_init(SPI1, &spi_init_struct);

      spi_enable(SPI1, TRUE);
      
#endif      
      
      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_0|GPIO_PINS_1|GPIO_PINS_2;
      gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
      gpio_init(GPIOB, &gpio_init_struct);      
      gpio_bits_set(GPIOB,GPIO_PINS_0|GPIO_PINS_1|GPIO_PINS_2);       
}

/******************************************************************************
      函数说明:LCD串行数据写入函数
      入口数据:dat要写入的串行数据
      返回值:无
******************************************************************************/
void LCD_Writ_Bus(uint8_t dat)
{       
        LCD_CS_Clr;
//gpio_bits_reset( GPIOA, GPIO_PINS_4 );
        #if SOFTWARE_SPI_ENABLE      
      u8 i;
      for(i=0;i<8;i++)
      {                        
                LCD_SCLK_LOW();
                if(dat&0x80)
                {
                   LCD_MOSI_HIGH();
                }
                else
                {
                   LCD_MOSI_LOW();
                }
                LCD_SCLK_HIGH();
                dat<<=1;
                                }
#else
spi_i2s_data_transmit(SPI1, dat );
        while(spi_i2s_flag_get(SPI1, SPI_I2S_TDBE_FLAG) == RESET) {};

#endif

}

测试结果:
使用软件摸的SPI,时钟可以达到5MHz显示图像正常,用逻辑分仪器捕获时序如下:

使用硬件spi配置 分频配置为时时钟正常,也可以正常驱动屏幕,捕获时序如下:

配置为spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_4;时,SCK的时钟信号就不是很规律了,但是可以驱动屏,时序如下:

配置为spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_8;时序乱了,cs信号也跟着乱了,屏点不亮,捕获的时序如下:

如果我们使用图形配置工具,它是不能配置低于8倍分频的:

【讨论】
在使用spi中,图形化配置好的代码,不能用于spi屏的驱动,时序会乱。而如果配置为2倍频,spi只能跑到2MHz,而摸拟的却可以跑到5MHz。我看数据手册spi是可以跑到120MHz的。如果大佬们能给我指点一下,不胜感谢!

muyichuan2012 发表于 2023-11-7 13:05

SPI时钟源可以到150M,但SPI最高速度不能超过36M。如下图,423数据手册有SPI的最高速度为36M。你workbench的配置的主频是150M,APB也是150M。所以SPI要8除频才可以。
如果想SPI跑快一点,可以将主频配置为144M,APB为144M,SPI使用4除频,即36M。


lulugl 发表于 2023-11-7 14:30

muyichuan2012 发表于 2023-11-7 13:05
SPI时钟源可以到150M,但SPI最高速度不能超过36M。如下图,423数据手册有SPI的最高速度为36M。你workbench ...

但是事实上,我配置为8时他时序乱了,需要配置2-4才能正常工作。

muyichuan2012 发表于 2023-11-7 14:55

可以跑一下BSP里SPI example

lulugl 发表于 2023-11-7 20:18

muyichuan2012 发表于 2023-11-7 14:55
可以跑一下BSP里SPI example

我有两块开发板,有空跑一下互相通信,看看情况怎么样。

fxyc87 发表于 2023-11-8 09:06

你的逻辑分析仪采样率调的太低了,20M采样来读取3M时钟有点低,看样子波形不太好,估计上升沿,下降沿有些时间长,用示波器看一下。

lulugl 发表于 2023-11-8 09:39

fxyc87 发表于 2023-11-8 09:06
你的逻辑分析仪采样率调的太低了,20M采样来读取3M时钟有点低,看样子波形不太好,估计上升沿,下降沿有些 ...

好的,我回去试试用200M来采一下样看看。模拟的时钟5M的时序是非常好的。

xu@xupt 发表于 2023-11-8 18:54

学习,围观

Jon495323976 发表于 2023-11-9 17:40

那是因为你的逻辑分析仪分辨率不够,抓不到高频的波形,所以出现那种不规律的显示

lulugl 发表于 2023-11-10 08:02

Jon495323976 发表于 2023-11-9 17:40
那是因为你的逻辑分析仪分辨率不够,抓不到高频的波形,所以出现那种不规律的显示 ...

有道理,我回去再试试高频抓包,我的逻辑分析好象可以抓400M的,这个我没有注意到,多谢大佬的指点!

abotomson 发表于 2023-12-7 21:23

在硬件SPI中,时钟信号是由SPI控制器产生的。

pixhw 发表于 2023-12-7 21:59

硬件SPI可以实现更高的速度和稳定性,因为它依赖于精确的硬件组件来控制时钟信号 。

uytyu 发表于 2023-12-8 08:42

需要降低时钟信号的频率,以适应软件的处理速度。

adolphcocker 发表于 2023-12-8 09:10

MCU需要将内部系统时钟分频后,再通过外部时钟引脚发送给SPI设备。

timfordlare 发表于 2023-12-8 09:31

模拟SPI是一种通过软件模拟SPI协议的通信方式,通常用于在没有硬件SPI接口的情况下实现SPI通信。

tifmill 发表于 2023-12-8 10:00

硬件SPI通常具有较高的通信速度。

linfelix 发表于 2023-12-8 10:10

时钟信号的产生和传输都是硬件级别的操作,通常由专门的硬件电路来完成。

fengm 发表于 2023-12-8 15:52

不需要极高的传输速率,模拟SPI也可以满足需求。

timfordlare 发表于 2023-12-8 16:20

在SPI 通信中,时钟信号和分频都是非常重要的组成部分

chenjun89 发表于 2023-12-8 20:47

硬件和软件模拟肯定有区别啊
页: [1] 2 3
查看完整版本: 【AT-START-F423测评】 硬件SPI与模拟spi中时钟信号与分频之疑惑