I am using the STM32H725RE (68-pin package).
My goal is to have full duplex SPI communication with a 16 bit shift register using the stm32h7 as the SPI master (with no dma controller).
I am using the SPI3 with the following pin (12MHz)
PA15 (SPI3_nCS), PC10 (SPI3_SCK), PC11 (SPI3_MISO) and PC12 (SPI3_MOSI).
With the following code it is already possible to write the data successfully and the shift register also sends the data correctly to the MISO wire. (as you can see in the logic analyser screenshot)
But I have problems reading the receive buffer, the flags are set correctly (RXP is set correctly), but when I read the RXDR I only read the data 0xFFFF, although other data should be read as shown in the logic analyser screenshot?
#include <stm32h7xx.h>
#include "stm32h725xx.h"
#define pSpiSR SPI3
static void initSPI3() {
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // SPI1 Peripherie Enable (FLASH)
// PA15 (SPI3_nCS)
GPIOA->MODER &= ~(GPIO_MODER_MODE15);
GPIOA->MODER |= (GPIO_MODER_MODE15_1); // Alternate function mode
GPIOA->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED15_Pos); // very high speed
GPIOA->OTYPER &= ~GPIO_OTYPER_OT15; // Push-pull
GPIOA->AFR[1] |= ((6 & 0x000F) << ((15-8)*4)); // set Alternate function 6;
// PC10 (SPI3_SCK), PC11 (SPI3_MISO), PC12 (SPI3_MOSI)
GPIOC->MODER &= ~(GPIO_MODER_MODE10 | GPIO_MODER_MODE11 | GPIO_MODER_MODE12);
GPIOC->MODER |= (GPIO_MODER_MODE10_1 | GPIO_MODER_MODE11_1 | GPIO_MODER_MODE12_1); // Alternate function mode
GPIOC->OSPEEDR |= ((3 << GPIO_OSPEEDR_OSPEED10_Pos) | (3 << GPIO_OSPEEDR_OSPEED11_Pos) | (3 << GPIO_OSPEEDR_OSPEED12_Pos)); // very high speed
GPIOC->OTYPER &= ~(GPIO_OTYPER_OT10 | GPIO_OTYPER_OT11 | GPIO_OTYPER_OT12); // Push-pull
GPIOC->AFR[1] |= ((6 & 0x000F) << ((10-8)*4)); // set Alternate function 6;
GPIOC->AFR[1] |= ((6 & 0x000F) << ((11-8)*4)); // set Alternate function 6;
GPIOC->AFR[1] |= ((6 & 0x000F) << ((12-8)*4)); // set Alternate function 6;
// 1. deactivate the SPI
SPI3->CR1 = 0; // SPI deactivate
SPI3->CR2 = 0x0;
SPI3->I2SCFGR = 0; // I2S-mode deactivate
// 2. configuration of CFG1
SPI3->CFG1 = SPI_CFG1_MBR_1 | (0x0F << SPI_CFG1_DSIZE_Pos) //; //frame size 16bit
| (0x00 << SPI_CFG1_FTHLV_Pos);
// 3. configuration of CFG2
SPI3->CFG2 = SPI_CFG2_MASTER // master-mode
| SPI_CFG2_AFCNTR // automatic chip-select
| SPI_CFG2_SSOE; // SS-Pin activate
// 4. deactivate interupts
SPI3->IER = 0;
}
static void spiStart(SPI_TypeDef *pSpi)
{
pSpi->CR2 = 0x1;
pSpi->CR1 |= SPI_CR1_SPE; //Enable SPI
pSpi->CR1 |= SPI_CR1_SPE | SPI_CR1_CSTART; //Master transfer start
}
void static spiStop(SPI_TypeDef *pSpi)
{
pSpi->CR1 = 0; //master transfer stop
pSpi->IFCR = 0xFFFFFFFF;
}
static unsigned long spiTrns16(SPI_TypeDef *pSpi, uint16_t dataOut) {
uint16_t dataIn;
volatile uint16_t *pHw = (volatile uint16_t *)&pSpi->TXDR;
volatile uint16_t *pRxHw = (volatile uint16_t *)&pSpi->RXDR;
// clear Read Register
while (pSpi->SR & SPI_SR_RXP) {
(void)*pRxHw;
}
// send data
*pHw = dataOut;
// wait until data are received (RXP-Flag)
while (!(pSpi->SR & SPI_SR_RXP));
pSpi->IFCR = 0xFFFFFFFF; //reset interrupt flags
// read data
dataIn = *pRxHw;
return dataIn;
}
static uint16_t spiShiftRegister(uint16_t sendSR){
uint16_t readSR;
spiStart(pSpiSR);
readSR = spiTrns16(pSpiSR, sendSR);
spiStop(pSpiSR);
return(readSR);
}
// mainFunction
int main(void) {
// SPI3 init
initSPI3();
// Variablen für den SPI-Datenaustausch
uint16_t dataToSend = 0x0AAA;
uint16_t receivedData;
while (1) {
receivedData = spiShiftRegister(pSpiSR, dataToSend)
}
return 0;
}