SPI从设备将数据读入stm32的缓冲区中?

我正在尝试通过SPI设置esp32(主设备)和stm32(从设备)之间的通信。 esp32在micropython下运行,并发送四个字节,例如 spi.write_readinto(b'\x31\x32\x33\x34',buf)

stm32'代码在这里(而不是我使用SPI_InitDef.SPI_NSS = SPI_NSS_Soft;

void SPI_Init(void) {
    ...

    //  initialize SPI slave
    // for slave,no need to define SPI_BaudRatePrescaler
    SPI_InitDef.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitDef.SPI_Mode = SPI_Mode_Slave;
    SPI_InitDef.SPI_DataSize = SPI_DataSize_8b; // 8-bit transactions
    SPI_InitDef.SPI_FirstBit = SPI_FirstBit_MSB; // MSB first
    SPI_InitDef.SPI_CPOL = SPI_CPOL_Low; // CPOL = 0,clock idle low
    SPI_InitDef.SPI_CPHA = SPI_CPHA_2Edge; // CPHA = 1
    SPI_InitDef.SPI_NSS = SPI_NSS_Hard; // use hardware SS
    SPI_InitDef.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; // APB2 72/64 = 1.125 MHz

    SPI_InitDef.SPI_CRCPolynomial = 7;
    SPI_Init(SPI1,&SPI_InitDef);

    SPI_Cmd(SPI1,ENABLE);

    NVIC_EnableIRQ(SPI1_IRQn);
    //Тут мы разрешаем прерывание по приему
    SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_RXNE,ENABLE);
}

void main() {
    /* Setup SysTick Timer for 10ms interrupts  */
    if (SysTick_Config(SystemCoreclock / 100))
    {
    /* Capture error */
    while (1);
    }
    /* Configure the SysTick handler priority */
    NVIC_SetPriority(SysTick_IRQn,0x0);

    SPI_Init();

    while(1) {
        while(!SPI_I2S_GetflagStatus(SPI1,SPI_I2S_flaG_RXNE));
        for (u8 i=0; i<4; i++) {
            printf("0x%02x ",SPI_I2S_ReceiveData(SPI1));
        }
        printf("\r\n");
    }
}

但是当我发送四个字节0x31 0x32 0x33 0x34(分析器确认已发送字节)并且我的stm仅获得0x31 0x32 0x31 0x32

UPD  我使用std周线库,而SPI_I2S_ReceiveData是从SPI读取字节的本地方法。

uint16_t SPI_I2S_ReceiveData    (   SPI_TypeDef *   SPIx     )  
Returns the most recent received data by the SPIx/I2Sx peripheral.

Parameters:
SPIx,:  To select the SPIx/I2Sx peripheral,where x can be: 1,2 or 3 in SPI mode or 2 or 3 in I2S mode or I2Sxext for I2S full duplex mode.
Return values:
The     value of the received data.

uint16_t SPI_I2S_ReceiveData    (   SPI_TypeDef *   SPIx     )  
Returns the most recent received data by the SPIx/I2Sx peripheral.

Parameters:
SPIx,2 or 3 in SPI mode or 2 or 3 in I2S mode or I2Sxext for I2S full duplex mode.
Return values:
The     value of the received data.

但是也许我在读取所有数据之前退出了IRQ。我发现运行while循环,直到最后一个字节的传输完成为止

zhao_xunze 回答:SPI从设备将数据读入stm32的缓冲区中?

我认为以下代码不正确(但我不知道函数SPI_I2S_ReceiveData在做什么):

while(!SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE));
for (u8 i=0; i<4; i++) {
  printf("0x%02x ",SPI_I2S_ReceiveData(SPI1));
}

一旦准备好读取一个字节,您就从while退出。我假设SPI_I2S_ReceiveData仅在读取SPI FIFO。在这种情况下,如果可能只接收到一两个字节,则尝试读取4个字节。

您没有精确说明所用STM32的种类,所以我描述的是STM32H7的SPI(据我所知,它应该与其他STM32非常相似)。

要在从属模式下设置接收,您应该特别定义以下三个参数:

  • 所谓的“帧”的长度(一次读取/写入的字节数)。这是HAL数据结构中的SPI_DataSize`字段,此处为8位。
  • 传输次数(TSIZE),它指定何时生成“传输结束”事件。用“帧”数表示。必须在每次接收之前通过寄存器SPI.CR2设置此参数(前提是您当然知道要接收的字节数)。
  • “ FIFO阈值”。它指定事件RXP或TXP生成的频率。您可以更改此参数以减少软件的工作量,但仅接收4个字节就没有影响。

在您的情况下,我认为您应该将传输大小设置为4(4个字节),并等待EOT标志被设置。设置该位后,您仅需从SPI接收寄存器读取4个字节(您便可以一次读取所有4个字节)。

我建议您不要使用HAL,而是通过读/写寄存器来编写自己的SPI接收/发送例程。它不是一个非常复杂的外围设备(因此不会花费您大量时间),并且您将准确地了解它的工作原理(而不是深入研究HAL)。

本文链接:https://www.f2er.com/3161427.html

大家都在问