2020-02-22 12:01 PM
I am learning bare-metal programming on STM32F411RE (Nucleo board). I am trying to implement a SPI driver.
Even though I have set the Data Frame Format to 8-bit, My SCK consists of 16 clock cycles. Sending 8 bit data on this has weird behavior(I am trying to send 0x9D below):
Here's my code:
#include "stm32f4xx.h" // Device header
void SPI1_init(void);
void SPI_write(uint8_t data);
int main()
{
SPI1_init();
GPIOA->BSRR = 1<<4;
while(1)
{
GPIOA->BSRR = 1<<20; //assert ~CS
SPI_write(0x9D);
//SPI_write(0xA2);
GPIOA->BSRR = 1<<4; //de-assert ~CS
}
}
void SPI1_init(void)
{
RCC->AHB1ENR |= 1; //enable clock to PortA
RCC->APB2ENR |= 1<<12; //enable clock to SPI1
GPIOA->MODER &= ~(3<<14 | 3<<10 | 3<<12 | 3<<8); //clear SPI bits
GPIOA->MODER |= (2<<10 | 2<<14 | 2<<12 | 1<<8 ); //set MOSI,MISO,SCK bits for AF and NSS as GPO
GPIOA->AFR[0] &= ~(0xF<<20 | 0xF<<24 | 0xF<<28); //clear AF
GPIOA->AFR[0] |= (5<<20 | 5<<24 | 5<<28); //setting AF05 for MOSI,MISO and SCK
//SPI1->CR1 &= ~(1<<6);
SPI1->CR1 = 0x31C; //disable SPI, 8 bit, Master, Mode0 SPI
//SPI1->CR1 &=~(1<<11);
SPI1->CR2 |= 0; //Motorola Frame format
SPI1->CR1 |= 0x40; //SPI enable
}
void SPI_write(uint8_t data)
{
while(!(SPI1->SR & 0x2)); //till transmit buffer is NOT empty, do nothing.
SPI1->DR = data;
while(SPI1->SR & 0X80); //while BSY flag is 1 do nothing. ie wait till transmission is complete
}
Sending 16 bit data, of-course, works perfectly (sending 0x9D and 0xA2 here):
My application requires me to send 24 bit data in a single ~CS cycle. So I can't use the 16-bit frame format. I need 8 bit frame format. Going through forum answers I found this answer trying to force the data register as:
*(__IO uint8_t *)&SPI->DR = data;
But even this doesn't work for me. I am still getting the 16 clock cycles on SCK. Any tips?
Solved! Go to Solution.
2020-02-23 12:39 AM
Note that the BSY bit is not set immediately when DR is written. Wait for TXE=1 first, then for BSY=0, and only then disable CS.
Casting to *(volatile uint8_t *)&SPI->DR might not even be necessary on the F4 series.
2020-02-23 12:39 AM
Note that the BSY bit is not set immediately when DR is written. Wait for TXE=1 first, then for BSY=0, and only then disable CS.
Casting to *(volatile uint8_t *)&SPI->DR might not even be necessary on the F4 series.
2020-02-23 12:40 AM
Check in the reference manual if your SPI has FIFO built-in for 8 or 16 bit write queuing. If not, the SPI is Gen1 and the cast is only needed for futureproofing your code.
Well, take an example SPI code (STM32Cube for the F411 nucleo, spi example, LL if available), run the example in 8 bit mode, and use debugger to look at the SPI registers. Then compare with your own.
2020-02-23 12:51 AM
F4 SPI has no FIFO.
2020-02-23 01:39 AM
Thanks a ton! That simple change in code actually worked like a charm. :)
Should have read the instructions in RM carefully,my bad.