STM32 UART转SPI变长数据传输

问题描述 投票:0回答:1

您好,我正在尝试与 STM32 IoT 开发套件中的 ES-WIFI 模块进行通信。 wifi模块默认通过SPI2连接(要使用UART,我必须使用SPI刷新模块的固件)。我想将 AT 命令从 UART 串行监视器传输到 wifi 模块,并接收返回到 PC 串行监视器的响应。所以,我想接收来自USART1(pc-uart)的消息并将数据传输到SPI2。同样,应从 SPI2 读取响应并将其传输到 USART1。还有一点是,数据传输应该是可变长度的。

当我运行程序时,调试器在 SPI 状态寄存器 TXE 不为空时停止。并且 FIFO 传输级别已满(FTLVM:11)。谁能告诉我我做错了什么。

    void USART1_IRQHandler(void)
{
  while (!((USART1->ISR) & USART_ISR_TXE));

  char temp1 = USART1->RDR;

  SPI2->DR = temp1;

  while (!(USART1->ISR & USART_ISR_TC)); // Checking transfer complete bit from UART status register

  while (!((SPI2->SR)& SPI_SR_TXE)); //Checking Transmit buffer empty from SPI status register

  while (((SPI2->SR)& SPI_SR_BSY)); //Checking SPI busy flag from status register

  uint8_t temp2 = SPI2->DR; // To clear Data and status register
          temp2 = SPI2->SR;
}

我的SPI2初始化函数是

void MX_SPI2_Init(void)
{

  /* USER CODE BEGIN SPI2_Init 0 */

  /* USER CODE END SPI2_Init 0 */

  /* USER CODE BEGIN SPI2_Init 1 */

  /* USER CODE END SPI2_Init 1 */
  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_MASTER;
  hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi2.Init.NSS = SPI_NSS_SOFT;
  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 7;
  hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  if (HAL_SPI_Init(&hspi2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI2_Init 2 */

  /* USER CODE END SPI2_Init 2 */

}

我的UART初始化函数是

void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_8;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */

  /* USER CODE END USART1_Init 2 */

}
c embedded stm32 uart spi
1个回答
1
投票

从根本上来说,我们需要处理两种情况:

  1. 将数据传入 UART。通过 SPI 发送。
  2. 传入 SPI 的数据。通过 UART 发送。

我认为你已经理解了这部分内容。

当您进行连续传输而不是单个字节时,问题就会出现。除非传输时序完全相等(这在现实世界中是不可能的),否则一个外设将比另一个外设更快地发送/接收数据。考虑夸张的例子以使其更直观:

设 SPI 为 1Mbit/s。
让 UART 为 9600b/s。

您可以看到,如果您接收到多于一个字节的 SPI 数据并连接到 UART,UART 将无法处理它,它根本无法足够快地移出数据。它正在移出第一个字节,但已经有更多字节通过 SPI 传入。如果您通过慢速 UART 接收,但通过更快的 SPI 发送,您可以看到,当输入一个完整字节的 UART 数据时,SPI 可以轻松地将其移出并休息一下,同时 UART 数据的第二个字节仍在输入. 当速度接近时,仍然会存在不匹配,并且无论是从 UART 到 SPI 还是从 SPI 到 UART,输入都会比输出快。


让我们考虑一下,SPI 比 UART 更快,就像我上面编写的示例一样。如果您的情况相反也没关系,这与概念有关。

当快速 SPI 上的字节传入时,可能有两种情况:

  1. UART 空闲。开始传输。够简单的。
  2. UART 已经在转移一些东西了。现在我们遇到了问题。我相信这就是您想要解决的问题,并且您的代码挂起,您错误地处理了这种情况。

因此,我相信您需要退一步,也许拿起笔和纸,考虑您的应用程序中可能出现的不同场景。您必须选择哪个方向更快,因此不需要任何缓冲区,而另一个方向则必须使用预定长度的 FIFO 缓冲区数组。 MCU 确实几乎立即处理传入的数据(与物理通信速度相比),但将数据移出另一个外设的物理过程需要时间,没有办法绕过它。

考虑到您的 MCU 移动数字的速度非常快(可能比数据物理移出至少快一个数量级),并且您可以简单地以这样的方式实现它,即始终发送传入的 SPI 缓冲区 SPI_RX_BUFFER[0]通过 UART 输出并立即将所有其他元素下移一个元素。您只需要一个 FIFO“满度”计数器即可知道何时停止。例如,将其称为 SPI_RX_BUFFER_LAST_ELEMENT,每次通过 UART 发送内容时,都会将其递减(以便在发送 FIFO 中的最后一个元素时它为 -1)。每次 SPI 数据进入时,SPI_RX_BUFFER_LAST_ELEMENT 都会增加 1,并且新数据存储在该位置。

即使您的 ST-Link 及其 USB-UART 桥接器也具有有限的 FIFO。如果你用 USB 数据淹没它,它就会溢出,并且会发生某种错误事件。例如,基于STM32F103的ST-Link的UART最大速度为4.5Mbps,而其USB接口最高支持12Mbps。

在这里,我花了一点时间画了一些插图,因为用图来谈论这些事情更容易。


底线是,您需要退一步重新考虑您的算法,决定缓冲区的深度并逐步实现它。在一个方向上,你的算法将是“我收到了数据,只需将其放入另一个接口的 TX 中”,因为那里肯定已经完成了先前的数据(尽管“if”语句不会造成伤害)。从另一个方向来说,它必须是“我将数据放入下一个空闲的 FIFO 位置。如果 FIFO 为空,则开始传输”,并且“我已经发送了一个字节并且传输数据寄存器为空,我需要检查 FIFO 是否有任何内容”否则将被发送。如果是,则将其加载到发送寄存器中,并将 FIFO 中的所有数据和指针移至最后一个元素”。

© www.soinside.com 2019 - 2024. All rights reserved.