STM32F4在半双工/单工模式下停用SPI的正确方法

Posted

技术标签:

【中文标题】STM32F4在半双工/单工模式下停用SPI的正确方法【英文标题】:Correct way to deactivate SPI in half-duplex/simplex mode STM32F4 【发布时间】:2021-07-17 05:03:39 【问题描述】:

我正在尝试在一定时间后将 STM32F4 从从机更改为主机,以主机身份发送消息,然后返回从机。我发现将 SPI 配置为 slave_rxonly 并启用 SPI 将导致时钟在我将设备配置回主机后立即意外发送时钟。没有我发送任何数据。我假设它是因为我要么错误地初始化外围设备,要么错误地取消初始化它

这是我的主循环。

  while (1)
  
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
      MX_SPI1_Init(); /* This configures master */
      HAL_Delay(10);
 
      sendHelloWorld();
      configSlave(); /* Configures slave mode */
      __HAL_SPI_ENABLE(&hspi1); /* Enabling the device in this mode generates a continous clock during master init */
 
      HAL_Delay(100);
 
      HAL_SPI_DeInit(&hspi1);   /* Disables SPI and de-initializes the peripheral */
  

我的主配置:

  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  
    Error_Handler();
  

我的奴隶配置:

if(HAL_SPI_DeInit(&hspi1) != HAL_ERROR)

       /* SPI1 parameter configuration*/
    hspi1.Instance = SPI1;
    hspi1.Init.Mode = SPI_MODE_SLAVE;
    hspi1.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
    hspi1.Init.NSS = SPI_NSS_SOFT;
    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
    hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi1.Init.CRCPolynomial = 10;
 
    if (HAL_SPI_Init(&hspi1) != HAL_OK)
    
        Error_Handler();
    
 

这是我的逻辑分析仪的波形。一旦我在启用 SPI 作为从设备后运行函数 MX_SPI1_Init() ,就会生成时钟。橙色是时钟,如您所见 - 从 10 毫秒延迟开始 - 它在初始化为主机后立即启用。

有什么想法吗?我一直在与这个问题作斗争一个多星期,并尝试了很多方法

【问题讨论】:

【参考方案1】:

可能是垃圾 HAL 功能意外临时更改为 master rx-only。各种 HAL 函数按照它们写入寄存器的顺序是幼稚的,并且会产生这样的故障。在重新配置之前尝试调用HAL_SPI_DeInit。或者干脆完全放弃 HAL。

Master RX-only 总是必须盲目地输出时钟。如果您想控制何时发送时钟,请使用主 tx 和 rx 模式,然后写入您想要读取的相同数量的虚拟数据。如果您希望 MOSI 保持三态而不发送虚拟数据,那么您可以在执行此操作时将引脚更改为 GPIO 模式。

【讨论】:

是的。 HAL 一直很痛苦,我很可能不得不创建自己的实现,但是,我认为事先试验 HAL 会更容易。 ST社区有人告诉我永远不要禁用SPI(SPE reg),只需更改主/从配置。这解决了它,但我认为这不应该是正确的方法。 如果这解决了您的问题,您能否接受左侧带有绿色勾号的答案?谢谢。

以上是关于STM32F4在半双工/单工模式下停用SPI的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

如何将 STM32f4 编程为 SPI 从设备

如何在stm32f2xx or stm32f4xx中使用spi dma来完成全双攻通信

带有 STM32F7 的 SPI 从模式和循环 DMA

STM32F4 SPI1 工作,SPI5 不工作?

STM32F4 SPI接收中断不起作用

stm32f407IG SPI通信