I'm trying to set communication between esp32 (master) and stm32 (slave) over SPI. esp32 is running under micropython and sends four bytes, for example spi.write_readinto(b'\x31\x32\x33\x34', buf)
stm32' code is here (instead of this i use 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");
}
}
But when I send four bytes 0x31 0x32 0x33 0x34
(analyzer confirms bytes were sent) and my stm gets only 0x31 0x32 0x31 0x32
UPD I use std periph library and SPI_I2S_ReceiveData is a native method to read byte from 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.
But maybe I exit out from IRQ before all data are read. I found to run the while loop until the transmission of the last byte is complete
I think the following code is not correct (but I don't know what the function SPI_I2S_ReceiveData
is doing):
while(!SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE));
for (u8 i=0; i<4; i++) {
printf("0x%02x ", SPI_I2S_ReceiveData(SPI1));
}
You exit from the while
as soon as one byte is ready to be read. I assume SPI_I2S_ReceiveData
is only reading the SPI FIFO. in that case you try to read 4 bytes when possibly only one or two has been received.
You didn't precise the kind of STM32 you're using so I am describing the SPI of STM32H7 (as far as I know it should be pretty similar in other STM32).
To setup a reception in slave mode you should define in particular these 3 parameters:
In your case I think you should setup a transfer size of 4 (4 bytes) and wait for EOT flag to be set. When it is set you only have to read 4 bytes from SPI Receive Register (you can read all 4 bytes at once by the way).
I suggest you do not use the HAL but write your own SPI reception / transmission routines by reading / writing registers. It is not a very complex peripheral (so it will not cost you a lot of time) and you will understand precisely how it works (instead of digging into the HAL).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.