Electronics > Microcontrollers
STM32F4 SPI read problem
Ulfberth:
Hi :)
I got problem with receiving data from nrf24l01+
First I thought that this is hardware issue, and slave device doesn't send right data, so I plugged logic analyzer which showed me that hardware is ok.
After that I launched debugger and found out that this is software issue, but I still didn't managed to find the mistake :scared:
So what I'm trying to do is:
1) Write register of slave.
2) Read that register.
so steps to write address are:
1) Select NRF 2) Send register address + write cmd 3) Send register value 4) Release device
And for read:
1) Select NRF 2) Send register address + read cmd 3) Send 5 dummy bytes 4) save data to array 5) Release device
The problem is, 1st byte in array always wrong, the rest is right, but they are shifted by 1. And after 1 cycle 1st data in array is actually the one which should be last :-//
It's on screenshot below, instead of rxBuf[0]=0x51 I get 1C then after cycle its 0x55...
I assume mistake is in read function, but I can't figure it out :-[
Code and screenshots is below
SPI settings
--- Code: ---void spi1_init(void)
{
// Enable clock for SPI2
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
// Configure SPI2
SPI1->CR1 = 0; // Reset CR1 register
SPI1->CR1 |= SPI_CR1_BR_0; // Baud rate prescaler = 4 => 16/4=4mhz
SPI1->CR1 |= SPI_CR1_MSTR; // Master mode
SPI1->CR1 |= SPI_CR1_SSM | SPI_CR1_SSI; // Software slave management
SPI1->CR1 |= SPI_CR1_SPE; // Enable SPI2
}
void spi1_gpio_init(void) // PA4 - SPI1_NSS | PA5-SPI1_SCK | PA6-SPI1_MISO| PA7-SPI1_MOSI
{
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; //Enable GPIOA Clock
GPIOA->MODER |= GPIO_MODER_MODER4_0; //PA4 GPIO OUT mode
GPIOA->MODER |= GPIO_MODER_MODER5_1; //Enable Alternate function mode for GPIOA PA5
GPIOA->MODER |= GPIO_MODER_MODER6_1; //Enable Alternate function mode for GPIOA PA6
GPIOA->MODER |= GPIO_MODER_MODER7_1; //Enable Alternate function mode for GPIOA PA7
GPIOA->AFR[0] |= 0x5UL<<GPIO_AFRL_AFSEL5_Pos; //GPIO alternate function set 0101 AF5 SPI PA5
GPIOA->AFR[0] |= 0x5UL<<GPIO_AFRL_AFSEL6_Pos; //GPIO alternate function set 0101 AF5 SPI PA6
GPIOA->AFR[0] |= 0x5UL<<GPIO_AFRL_AFSEL7_Pos; //GPIO alternate function set 0101 AF5 SPI PA7
}
--- End code ---
code for read and write functions
--- Code: ---void test_read(void)
{
uint8_t rxBuf[5]={0};
GPIOA->BSRR = GPIO_BSRR_BR4;
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = NRF24_REG_TX_ADDR | NRF24_CMD_R_REGISTER;
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = 0xFF;
while (!(SPI1->SR & SPI_SR_RXNE));
rxBuf[0]=SPI1->DR;
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = 0xFF;
while (!(SPI1->SR & SPI_SR_RXNE));
rxBuf[1]=SPI1->DR;
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = 0xFF;
while (!(SPI1->SR & SPI_SR_RXNE));
rxBuf[2]=SPI1->DR;
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = 0xFF;
while (!(SPI1->SR & SPI_SR_RXNE));
rxBuf[3]=SPI1->DR;
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = 0xFF;
while (!(SPI1->SR & SPI_SR_RXNE));
rxBuf[4]=SPI1->DR;
while (!(SPI1->SR & SPI_SR_TXE));
while (SPI1->SR & SPI_SR_BSY);
GPIOA->BSRR = GPIO_BSRR_BS4;
}
void test_write(void)
{
GPIOA->BSRR = GPIO_BSRR_BR4;
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = NRF24_REG_TX_ADDR | NRF24_CMD_W_REGISTER;
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = 0x51;
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = 0x52;
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = 0x53;
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = 0x54;
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = 0x55;
while (!(SPI1->SR & SPI_SR_TXE));
while (SPI1->SR & SPI_SR_BSY);
GPIOA->BSRR = GPIO_BSRR_BS4;
}
--- End code ---
wek:
Basically, after *each* Tx you should wait for RXNE and read out the received byte.
JW
Ulfberth:
Is my sequence wrong?
My steps when I read from spi:
1) I wait for TXE ( transmit buffer empty)
2) I put data into tx DR
3) I wait for RXE (Receive buffer not empty)
4) I take data from rx DR and put it into array
langwadt:
--- Quote from: Ulfberth on February 02, 2023, 01:28:35 pm ---Is my sequence wrong?
My steps when I read from spi:
1) I wait for TXE ( transmit buffer empty)
2) I put data into tx DR
3) I wait for RXE (Receive buffer not empty)
4) I take data from rx DR and put it into array
--- End quote ---
remember that every transmit is also a receive
try waiting for RXE and doing a dummy read of DR after sending the read command
Sherlock Holmes:
--- Quote from: Ulfberth on February 02, 2023, 01:28:35 pm ---Is my sequence wrong?
My steps when I read from spi:
1) I wait for TXE ( transmit buffer empty)
2) I put data into tx DR
3) I wait for RXE (Receive buffer not empty)
4) I take data from rx DR and put it into array
--- End quote ---
I wrote this last year, the SPI to NRF code works correctly.
https://github.com/Steadsoft/embedded/tree/main/NucleoF446RE/NRF24
These are just apps, using the API I created, this is for testing RX functionality, all STM32
https://github.com/Steadsoft/embedded/blob/main/NucleoF446RE/NRF24/Receiver/nrf_hal_rx_project.c
So focus on the API libraries I created, that's where the real effort went.
Navigation
[0] Message Index
[#] Next page
Go to full version