2019-12-23 07:43 AM
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
}
2019-12-23 04:28 PM
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."
2019-12-25 10:02 AM
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.
2019-12-25 10:34 AM
Yes it is the unfortunate side effect of the FIFOs. 8 bit or 16 bit data register access now matters...
2021-01-20 12:29 AM
Excellent!
Thanks for the solution. I've been trying to solve the problem for 2 days.