2020-06-08 02:55 PM
Hello,
here is another bare metal question on STM32G071. I am trying to get the SPI to work. But it is not generating any clock signal or MOSI signal.
Here is my init code trying to get it to work on GPIOB 6 to 8:
void init_spi(SPI_TypeDef* SPI)
{
if(SPI == SPI2)
{
RCC->APBENR1 |= RCC_APBENR1_SPI2EN; // enable SPI2
RCC->IOPENR |= RCC_IOPENR_GPIOBEN; // enable GPIOB
GPIOB->MODER &= ~(GPIO_MODER_MODE6_Msk|GPIO_MODER_MODE7_Msk|GPIO_MODER_MODE8_Msk); // clear alternate functions PB6, PB7, PB8
GPIOB->MODER |= (GPIO_MODER_MODE6_1|GPIO_MODER_MODE7_1|GPIO_MODER_MODE8_1); // alternate functions PB6, PB7, PB8
GPIOB->OSPEEDR |= 0b111111<<14; // PB6, PB7, PB8 very high speed
GPIOB->AFRL |= (GPIO_AFRL_AFSEL6_2|GPIO_AFRL_AFSEL7_0); // PB6, PB7 SPI2
GPIOB->AFRH |= GPIO_AFRH_AFSEL8_0; // PB8 SPI2
}else{
return;
}
SPI->CR1 = (SPI_CR1_MSTR|SPI_CR1_SSM); // SPI master, enable, soft select
SPI->CR1 |= 0b111<<3; // 1 MHz baudrate
SPI->CR2 |= 0b111<<8; // SPI 8bit mode
SPI->CR1 |= SPI_CR1_SPE; // enable SPI
}
I can see in a logic analyzer that the pins shortly go low. So I guess my error is in the transmit code. I simply write to the SPI_DR to transmit.
void spi_wbyte(SPI_TypeDef* SPI, uint8_t val)
{
SPI->DR = val;
}
Also, how do I read a byte? I could not find any examples. Is there anything wrong in my init?
Thanks
Kind regards.
Solved! Go to Solution.
2020-06-09 01:10 AM
That's because you selected internal "soft" NSS, but you left its level as 0.
JW
2020-06-08 03:28 PM
> GPIOB->OSPEEDR |= 0b111111<<14; // PB6, PB7, PB8 very high speed
PB7, PB8 and PB9
Not that it matters much.
Also, "very high speed" is often a bad idea with SPI SCK, although maybe in 'G0 it is not that prominent.
Read out the registers and check/compare. My guess is, that you find that SPI is switched to slave.
JW
2020-06-08 03:52 PM
> Also, "very high speed" is often a bad idea with SPI SCK, although maybe in 'G0 it is not that prominent.
@Community member Why do you say that? Just because it creates a sharper edge which makes more noise?
2020-06-08 03:59 PM
> Also, how do I read a byte?
To read a byte from MISO, you just read from SPIx->DR. Check the RXNE flag first.
To write a bit to MOSI, you write to SPIx->DR. Check the TXE flag first.
The register serves a double purpose. Not sure if it matters for the G0 (I don't think it does), but the HAL and LL libraries perform these as byte instructions, as opposed to word instructions.
> __IO uint8_t *spidr = ((__IO uint8_t *)&SPIx->DR);
> *spidr = TxData;
2020-06-08 04:52 PM
Yes.
Moore Noyce in SPI SCK may mean false clock edges to be seen by the slave.
JW
2020-06-08 04:57 PM
> The register serves a double purpose.
Aren't there separate TDR/RDR in G0? I don't have the RM at hand now (or is it only in the newer UARTs?)
> Not sure if it matters for the G0 (I don't think it does
It probably does, all newer STM32 SPIs have so called data packing (see RM, can be a nasty surprise to the unaware).
JW
2020-06-09 01:03 AM
@Community member true, it is switched to slave. But why?
2020-06-09 01:04 AM
Thanks for the replies.
So I changed the speed to only high and inserted the code from TDK. It turns out it switched back to slave mode.
2020-06-09 01:10 AM
That's because you selected internal "soft" NSS, but you left its level as 0.
JW
2020-06-09 01:45 AM
Thanks, this was it.