首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SPI从读入数据到stm32上的缓冲区?

SPI从读入数据到stm32上的缓冲区?
EN

Stack Overflow用户
提问于 2019-11-05 07:51:46
回答 1查看 4.1K关注 0票数 0

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

Stm32的代码在这里(我使用的不是这个,而是SPI_InitDef.SPI_NSS = SPI_NSS_Soft;)

代码语言:javascript
复制
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 i使用std循环库,SPI_I2S_ReceiveData是从读取字节的原生方法。

代码语言:javascript
复制
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,:  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.

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-11-05 09:17:17

我认为下面的代码是不正确的(但我不知道SPI_I2S_ReceiveData正在做什么):

代码语言:javascript
复制
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。在这种情况下,当可能只接收到一个或两个字节时,您尝试读取4个字节。

您没有精确地说明您正在使用的STM32类型,所以我描述的是STM32H7的SPI (据我所知,它在其他STM32中应该非常类似)。

若要设置从模式下的接收,应特别定义以下3个参数:

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

在您的情况下,我认为您应该设置一个4(4个字节)的传输大小,并等待设置EOT标志。设置它时,您只需从SPI接收寄存器读取4个字节(顺便说一下,您可以同时读取所有4个字节)。

我建议您不要使用HAL,而是通过读/写寄存器来编写自己的SPI接收/传输例程。它不是一个非常复杂的外围设备(所以它不会花费大量时间),并且您将准确地了解它是如何工作的(而不是深入到HAL中)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58706757

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档