gpt4 book ai didi

c - SPI从机将数据读入stm32上的缓冲区?

转载 作者:行者123 更新时间:2023-11-30 16:11:06 24 4
gpt4 key购买 nike

我正在尝试通过 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 读取字节的 native 方法。

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 循环直到最后一个字节的传输完成

最佳答案

我认为下面的代码不正确(但我不知道函数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中应该非常相似)。

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

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

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

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

关于c - SPI从机将数据读入stm32上的缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58706757/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com