SPI slave считывает данные в буфер на stm32? - PullRequest
0 голосов
/ 05 ноября 2019

Я пытаюсь установить связь между esp32 (master) и stm32 (slave) через SPI. 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,:  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, пока не будет завершена передача последнего байта

1 Ответ

0 голосов
/ 05 ноября 2019

Я думаю, что следующий код неправильный (но я не знаю, что делает функция 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, поэтому я описываю SPI STM32H7 (насколько я знаю, он должен быть очень похож на другой STM32).

ДляЧтобы настроить прием в подчиненном режиме, вы должны определить, в частности, эти 3 параметра:

  • длина так называемого «кадра» (количество байтов, которые должны быть прочитаны / записаны одновременно). Это поле SPI_DataSize` в структуре данных HAL, здесь 8 бит.
  • номер передачи (TSIZE), который указывает, когда генерируется событие «Конец передачи». Выражается в количестве «кадров». Этот параметр должен быть установлен через регистр SPI.CR2 перед каждым приемом (при условии, что вы, конечно, знаете количество байтов, которые должны быть получены).
  • «Порог FIFO». Он указывает, с какой частотой генерируется событие RXP или TXP. Вы можете изменить этот параметр, чтобы уменьшить нагрузку на программное обеспечение, но на получение только 4 байтов это не влияет.

В вашем случае, я думаю, вам следует установить размер передачи 4 (4 байта) идождитесь установки флага EOT. Когда он установлен, вам нужно только прочитать 4 байта из регистра получения SPI (вы можете прочитать все 4 байта одновременно).

Я предлагаю вам не использовать HAL, а написать свои собственные процедуры приема / передачи SPI, читая / записывая регистры. Это не очень сложное периферийное устройство (поэтому оно не будет стоить вам много времени), и вы точно поймете, как оно работает (вместо того, чтобы копаться в HAL).

...