cancel
Showing results for 
Search instead for 
Did you mean: 

Hello, i try to use the SPI interface on STM32f3 DISCOVERYBOARD. My problem is that my clock toggles, even though the data transfer is complete. The busy flag is not yet reset either. What can that be? Ther is an Osziplot wich shows the Problem

BKopp.1
Associate II

This is my source code for the SPI configuration:

static void SPI1_init(){

   //GPIOs konfigurieren

   //PA4 Chip select

   //PA5 clk

   //PA6 MISO

   //PA7 MOSI

   uint8_t ch;

   while(SPI1->SR & SPI_SR_FTLVL); // Wait until no more data to transmit

   while(SPI1->SR & SPI_SR_BSY); // Wait until SPI is not busy

   SPI1->CR1 &= ~SPI_CR1_SPE; // Disable SPI1 peripheral

      while(SPI1->SR & SPI_SR_FRLVL) // Read all data deceived   

      {      

      if(SPI1->SR & SPI_SR_RXNE)

      {      

      ch = SPI1->DR;   

      }   

      }

   // Enable SPI1 Clock

   RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;

   //Config GPIO Ports

   GPIOA ->MODER &= ~(GPIO_MODER_MODER5 | GPIO_MODER_MODER6 | GPIO_MODER_MODER7);

   GPIOA ->MODER |= GPIO_MODER_MODER5_1 | GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1;

   GPIOA ->OTYPER &= ~(GPIO_OTYPER_OT_5 | GPIO_OTYPER_OT_6 |GPIO_OTYPER_OT_7);

   //BUS speed

   GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR5 | GPIO_OSPEEDER_OSPEEDR6 | GPIO_OSPEEDER_OSPEEDR7;

   GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR5_1 | GPIO_OSPEEDER_OSPEEDR6_1 | GPIO_OSPEEDER_OSPEEDR7_1;

   // No pull up or pull down for CLK, MOSI. Pull up for MISO

   GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR5 | GPIO_PUPDR_PUPDR6 | GPIO_PUPDR_PUPDR7);

   GPIOA->PUPDR |= GPIO_PUPDR_PUPDR6_0;

   // Set alternative function to AF5 (SPI Mode)

   GPIOA->AFR[0] &= ~(GPIO_AFRL_AFRL5 | GPIO_AFRL_AFRL6 | GPIO_AFRL_AFRL7);   

   GPIOA->AFR[0] |= ( (5U << 20) | (5U << 24) | (5U << 28));

   // Now configure SPI settings:

   SPI1->CR1 = 0x00; // Reset SPI CR1

   SPI1->CR2 = 0x0700; // Reset SPI CR2: Default settings for CR2 okay for use

   SPI1->CR1 &= ~SPI_CR1_BR_0;

   SPI1->CR1 |= SPI_CR1_BR_1; // Spi Clock is 8 MHz / 4 = 2 MHz

   SPI1->CR1 |= SPI_CR1_CPHA;

   SPI1->CR1 &= ~(SPI_CR1_CPOL);

   SPI1->CR1 &= ~SPI_CR1_RXONLY; // Full duplex mode

   SPI1->CR1 &= ~SPI_CR1_BIDIMODE; // 2-line unidirectional data

   SPI1->CR1 |= SPI_CR1_BIDIOE; // Output enabled MOSI pin

   SPI1->CR1 &= ~SPI_CR1_CRCEN; // CRC calculation disabled

   SPI1->CR1 &= ~SPI_CR1_LSBFIRST; // MSB First

   //SPI1->CR1 |= SPI_CR1_LSBFIRST; // LSB first

   SPI1->CR1 |= SPI_CR1_SSM; // Enable software slave management

   SPI1->CR1 |= SPI_CR1_MSTR; // Master Configuration

   SPI1->CR1 |= SPI_CR1_SSI; // Set SSI High

   SPI1->CR2 |= SPI_CR2_FRXTH; // Reception threshold >= 8-bits

   SPI1 ->CR2 = SPI_CR2_DS_0 | SPI_CR2_DS_1 | SPI_CR2_DS_2 ;

   SPI1 ->CR2 &= ~ SPI_CR2_DS_3 ;

   SPI1 ->CR2 &= ~ (SPI_CR2_ERRIE_Msk);

   SPI1 ->CR2 &= ~(SPI_CR2_RXDMAEN);

   SPI1 ->CR2 &= ~(SPI_CR2_TXDMAEN);

   SPI1 ->CR2 &= ~(SPI_CR2_SSOE);

   SPI1 ->CR2 &= ~(SPI_CR2_NSSP);

   SPI1->CR2 |= SPI_CR2_FRF;

   SPI1->CR2 |= SPI_CR2_FRXTH;

   SPI1 ->CR2 &= ~(SPI_CR2_LDMATX);

}

With this function I write in the DB register, this is called periodically. For tests, i send always the number "176" in dec.

void SPI1_sendByte(uint8_t data)

{

while(!(SPI_SR_BSY)); // Wait until bus is not busy

SPI1->DR = data; // write data

while(!(SPI_SR_BSY)); // Wait until bus is not busy

}

4 REPLIES 4
BKopp.1
Associate II

Short update:

I think that the automatic data packing becomes active. As described in the manual on page 965.

Does anyone know why this becomes active? I only transfer 8 bits. That's why it shouldn't actually be active.

Or does anyone know how to disable it?

Manuel page 965:

"Data packing

When the data frame size fits into one byte (less than or equal to 8 bits), data packing is

used automatically when any read or write 16-bit access is performed on the SPIx_DR

register. The double data frame pattern is handled in parallel in this case. At first, the SPI

operates using the pattern stored in the LSB of the accessed word, then with the other half

stored in the MSB. Figure 357 provides an example of data packing mode sequence

handling. Two data frames are sent after the single 16-bit access the SPIx_DR register of

the transmitter. This sequence can generate just one RXNE event in the receiver if theRXFIFO threshold is set to 16 bits (FRXTH=0). The receiver then has to access both data

frames by a single 16-bit read of SPIx_DR as a response to this single RXNE event. The

RxFIFO threshold setting and the following read access must be always kept aligned at the

receiver side, as data can be lost if it is not in line.

A specific problem appears if an odd number of such “fit into one byte�? data frames must be

handled. On the transmitter side, writing the last data frame of any odd sequence with an 8-

bit access to SPIx_DR is enough. The receiver has to change the Rx_FIFO threshold level

for the last data frame received in the odd sequence of frames in order to generate the

RXNE event."

BKopp.1
Associate II

If someone has the same problem, here is the solution:

wrong: SPI1->DR = data; // write data

Right:*(volatile uint8_t*)&SPI1->DR = data;

Otherwise you have a 16 bit access to the DB register. Then the stm will automatically transfer 16 bits.

S.Ma
Principal

Yes it is the unfortunate side effect of the FIFOs. 8 bit or 16 bit data register access now matters...

Excellent!

Thanks for the solution. I've been trying to solve the problem for 2 days.