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

[复制链接]
6806|56
 楼主| lulugl 发表于 2023-11-7 12:27 | 显示全部楼层 |阅读模式
@21小跑堂

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

  1. //  作    者   : 刘建华
  2. //  生成日期   : 2023-11-7
  3. //  最近修改   :
  4. //  功能描述   :AT32F435 GC9306
  5. //              说明:
  6. //              ----------------------------------------------------------------
  7. //              GND   电源地
  8. //              VCC   3.3v电源
  9. //              SCL   PA13(SCLK)
  10. //              SDA   PA14(MOSI)
  11. //              RES   PA0
  12. //              DC    PA1
  13. //              CS    PA12
  14. //              BLK   PA3
  15. //              ----------------------------------------------------------------
  16. // 修改历史   :
  17. // 日    期   :
  18. //All rights reserved
  19. //******************************************************************************/


  20. #define SOFTWARE_SPI_ENABLE 0

  21. void LCD_GPIO_Init(void)
  22. {
  23.    gpio_init_type gpio_init_struct;

  24.    spi_init_type spi_init_struct;

  25.     /* 使能GPIOA GPIOB时钟 */

  26.                 crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
  27.                 crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

  28.         /* set default parameter */
  29.         gpio_default_para_init(&gpio_init_struct);

  30. #if SOFTWARE_SPI_ENABLE        

  31.         /* configure the led gpio */
  32.         gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  33.         gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
  34.         gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  35.         gpio_init_struct.gpio_pins = GPIO_PINS_4|GPIO_PINS_5|GPIO_PINS_7;
  36.         gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  37.         gpio_init(GPIOA, &gpio_init_struct);        
  38.         gpio_bits_set(GPIOA,GPIO_PINS_4|GPIO_PINS_5|GPIO_PINS_7);

  39. #else        

  40.         /*SPI1 :  
  41.                 PA4/CS  
  42.                 PA5/SCK   
  43.                 PA6/MISO   
  44.                 PA7/MOSI   
  45.         */   
  46.         gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  47.         gpio_init_struct.gpio_pull           = GPIO_PULL_UP;
  48.         gpio_init_struct.gpio_mode           = GPIO_MODE_OUTPUT;
  49.         gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  50.         gpio_init_struct.gpio_pins = GPIO_PINS_4;
  51.         gpio_init(GPIOA, &gpio_init_struct);
  52.         
  53.         gpio_bits_set(GPIOA,GPIO_PINS_4);

  54.         gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE5, GPIO_MUX_5);
  55.         gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE6, GPIO_MUX_5);
  56.         gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE7, GPIO_MUX_5);
  57.         gpio_default_para_init(&gpio_init_struct);

  58.         gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;

  59.         gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;
  60.         gpio_init_struct.gpio_mode           = GPIO_MODE_MUX;
  61.         gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  62.         gpio_init_struct.gpio_pins = GPIO_PINS_5  ;
  63.         gpio_init(GPIOA, &gpio_init_struct);


  64. //       gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  65. //       gpio_init_struct.gpio_pull           = GPIO_PULL_UP;
  66. //       gpio_init_struct.gpio_mode           = GPIO_MODE_MUX;
  67. //
  68. //       gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  69. //       gpio_init_struct.gpio_pins = GPIO_PINS_6;
  70. //       gpio_init(GPIOA, &gpio_init_struct);


  71.         gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  72.         gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;
  73.         gpio_init_struct.gpio_mode           = GPIO_MODE_MUX;
  74.         gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  75.         gpio_init_struct.gpio_pins = GPIO_PINS_7 | GPIO_PINS_6;
  76.         gpio_init(GPIOA, &gpio_init_struct);

  77.         crm_periph_clock_enable(CRM_SPI1_PERIPH_CLOCK, TRUE);
  78.   
  79.         spi_default_para_init(&spi_init_struct);
  80.         spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
  81.         spi_init_struct.master_slave_mode = SPI_MODE_MASTER;
  82.         spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_2;
  83.         spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
  84.         spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
  85.         spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;  //SPI_CLOCK_POLARITY_HIGH
  86.         spi_init_struct.clock_phase = SPI_CLOCK_PHASE_2EDGE;       //SPI_CLOCK_PHASE_2EDGE
  87.         spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
  88.         spi_init(SPI1, &spi_init_struct);

  89.         spi_enable(SPI1, TRUE);
  90.         
  91. #endif        
  92.         
  93.         gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  94.         gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
  95.         gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  96.         gpio_init_struct.gpio_pins = GPIO_PINS_0|GPIO_PINS_1|GPIO_PINS_2;
  97.         gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  98.         gpio_init(GPIOB, &gpio_init_struct);      
  99.         gpio_bits_set(GPIOB,GPIO_PINS_0|GPIO_PINS_1|GPIO_PINS_2);       
  100. }

  101. /******************************************************************************
  102.       函数说明:LCD串行数据写入函数
  103.       入口数据:dat  要写入的串行数据
  104.       返回值:  无
  105. ******************************************************************************/
  106. void LCD_Writ_Bus(uint8_t dat)
  107. {       
  108.         LCD_CS_Clr;
  109.   //gpio_bits_reset( GPIOA, GPIO_PINS_4 );
  110.         #if SOFTWARE_SPI_ENABLE        
  111.         u8 i;
  112.         for(i=0;i<8;i++)
  113.         {                          
  114.                 LCD_SCLK_LOW();
  115.                 if(dat&0x80)
  116.                 {
  117.                    LCD_MOSI_HIGH();
  118.                 }
  119.                 else
  120.                 {
  121.                    LCD_MOSI_LOW();
  122.                 }
  123.                 LCD_SCLK_HIGH();
  124.                 dat<<=1;
  125.                                 }
  126. #else
  127.   spi_i2s_data_transmit(SPI1, dat );
  128.         while(spi_i2s_flag_get(SPI1, SPI_I2S_TDBE_FLAG) == RESET) {};

  129. #endif

  130. }

测试结果:
使用软件摸的SPI,时钟可以达到5MHz显示图像正常,用逻辑分仪器捕获时序如下:
ff60debc984b63b92a687093c8c11025
使用硬件spi配置 分频配置为时时钟正常,也可以正常驱动屏幕,捕获时序如下:
ddc734364f35295dcf3d07f02b94b6f1
配置为spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_4;时,SCK的时钟信号就不是很规律了,但是可以驱动屏,时序如下:
0d3af70767ab22461d9c28618cbbd5ab
配置为spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_8;时序乱了,cs信号也跟着乱了,屏点不亮,捕获的时序如下:
091d9a08b4364887f07e3ab53f9056ac
如果我们使用图形配置工具,它是不能配置低于8倍分频的:
f116682f2760a2049160f8a44dade677
【讨论】
在使用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。
510516549c4e83142a.png

 楼主| 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 来自手机 | 显示全部楼层
硬件和软件模拟肯定有区别啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则

188

主题

844

帖子

12

粉丝
快速回复 在线客服 返回列表 返回顶部