【问题标题】:STM32 SPI slave mode doesn't transmit properlySTM32 SPI 从机模式无法正常传输
【发布时间】:2021-12-24 17:07:35
【问题描述】:

我使用 STM32G030C8T6 作为 SPI(从设备)接收来自 Raspberry pi(主设备)的字符,接收效果很好!那里没有问题,但是当我尝试将数据从 STM32 发送到 Pi 时,似乎 STM32 卡住了一段时间,并且 Pi rx 缓冲区重复填充只有一位,例如,如果我发送 char buf[6] = { 0,1,2,3,4,5}; Pi 接收 (111111) 或 (333333) 取决于我发送的字符数。

我真正想做什么?

我想将 ADC 数据从 STM32(从模式)传输到 Pi(主模式),到目前为止它只接收我重复的一位。

有人可以帮我实现吗?

这是我的 SPI 配置:

void MX_SPI1_Init(void)
{

  /* USER CODE BEGIN SPI1_Init 0 */

  /* USER CODE END SPI1_Init 0 */

  /* USER CODE BEGIN SPI1_Init 1 */

  /* USER CODE END SPI1_Init 1 */
  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_SLAVE;
  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.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */

}

然后是读取字符、发送数据和字符串的函数

char SPI_read(void)
{
    // SPI1->SR is the STATUS REGISTER on SPI1 Bus
    // SPI1->DR is the DATA REGISTER on SPI1 Bus

    char data;
    while(!(SPI1->SR & SPI_SR_RXNE));


    while(SPI1->SR & SPI_SR_BSY);

    data = SPI1->DR;

    printmsg("%c",data);

    return data;
}


void spi_Send(char caracSend)
{
    while(!(SPI1->SR & SPI_SR_TXE));

    SPI1->DR = caracSend;
}


void spi_send_string(char* stringSend)
{
    int i=0;
    unsigned int sizeChar = 0;

    sizeChar = strlen(stringSend);

    __NOP();

    for(i=0;i<sizeChar;i++)
    {
        spi_Send(stringSend[i]);
    }
}

这是我从 Pi 接收数据的函数,我在主 while 循环中调用它。

void SPI_Receive_Commands(void)
{

    while(HAL_GPIO_ReadPin(SPI_SS_GPIO_Port, SPI_SS_Pin) == GPIO_PIN_RESET);
  {
        HAL_SPI_Receive(&hspi1, (uint8_t *)spi_buf, 10, 100);

    if(spi_buf[0] == 'v')
    {
      memset(spi_buf,'*',10);

      printmsg("Character V received\r\n");

      Battery_Voltage();
      spi_send_string(batteryVoltage);
      spi_Send('v');

      printmsg("Sending battery voltage\r\n");
    }
}
}

非常感谢您提前帮助我。

【问题讨论】:

  • 这个 nop 有什么用?
  • while(SPI1->SR & SPI_SR_BSY);根本不需要在接收中
  • nop 是一个无操作功能,我认为可以添加延迟?
  • 不,不是。在这里什么都不做
  • 好的,我会删除 NOP 函数和 while(SPI1->SR & SPI_SR_BSY);

标签: stm32 spi master-slave stm32f4discovery stm32cubeide


【解决方案1】:
  1. 初始化。在读取和写入字节时,您需要将 RX FIFO 阈值设置为 1/4。我不知道如何在 HAL 中做到这一点。寄存器级别只需在CR2 寄存器中设置FRXTH

  2. DR 寄存器必须以 8 位操作访问。

  3. 您不需要在轮询模式下使用 BSY 位,除非您想禁用 SPI 外设。

void spi_Send(char caracSend)
{
    while(!(SPI1->SR & SPI_SR_TXE));

    *(volatile uint8_t *)&SPI1->DR = caracSend;
}

void spi_send_string(char* str)
{
     if(str) while(*str) spi_Send(*str++);
}


char SPI_read(void)
{
    char data;
    while(!(SPI1->SR & SPI_SR_RXNE));

    data = *(volatile uint8_t *)&SPI1->DR;
    return data;
}

记住树莓派必须发送虚拟数据以允许从站发送信息。从站生成时钟信号,时钟必须由主站提供

【讨论】:

    猜你喜欢
    • 2023-03-16
    • 2020-12-05
    • 2019-02-21
    • 2017-04-14
    • 2019-04-06
    • 2019-06-14
    • 1970-01-01
    • 2020-03-01
    • 2021-11-22
    相关资源
    最近更新 更多