cancel
Showing results for 
Search instead for 
Did you mean: 

SPI in slave mode doesn't work correctly (STM32F100RB)

Harry Hamper
Associate II

The SPI does not work correctly in the slave mode when CPOL=0 and CPHA=0 or CPOL=1 and CPHA=1.

When transmitting some bytes, the slave SPI distorts the data and terminates the processing of the frame prematurely (during the seventh pulse of the clock signal).

Other bytes are transmitted correctly.

Test code (0x03 raises an error, 0xFF does not):

/*
MCU: STM32F100RB
 
SPI1:
	PA4 - NSS;
	PA5 - SCK;
	PA6 - MISO;
	PA7 - MOSI.
 
SPI2:
	PB12 - NSS;
	PB13 - SCK;
	PB14 - MISO;
	PB15 - MOSI.
 
Connections: PA4-PB12; PA5-PB13; PA6-PB14; PA7-PB15.
*/
 
#include "stm32f10x.h"
 
const uint32_t CPOL=SPI_CR1_CPOL*0;
const uint32_t CPHA=SPI_CR1_CPHA*0;
 
uint8_t a1=0x5A;	// Byte to transfer through the SPI1.
uint8_t a2=0x03;	// Byte to transfer through the SPI2.
//uint8_t a2=0xFF;
//uint8_t a2=0x3C;
uint8_t b1=0;		// The byte received by the SPI1.
uint8_t b2=0;		// The byte received by the SPI2.
 
int main(void)
{
	RCC->APB2ENR|=
			RCC_APB2ENR_SPI1EN|
			RCC_APB2ENR_IOPAEN|
			RCC_APB2ENR_IOPBEN;
 
	RCC->APB1ENR|=RCC_APB1ENR_SPI2EN;
 
	// PA4 (SPI1_NSS): alt. out, push-pull, high speed
	// PA5 (SPI1_SCK): alt. out, push-pull, high speed
	// PA6 (SPI1_MISO): float input
	// PA7 (SPI1_MOSI): alt. out, push-pull, high speed
	GPIOA->CRL=
			GPIOA->CRL&~0xFFFF0000|
						0xB4BB0000;
 
	// PB12 (SPI2_NSS): input
	// PB13 (SPI2_SCK): input
	// PB14 (SPI2_MISO): alt. out, push-pull, high speed
	// PB15 (SPI2_MOSI): input
	GPIOB->CRH=
			GPIOB->CRH&~0xFFFF0000|
						0x4B440000;
 
	SPI1->CR1=				// Clear all bits except...
			SPI_CR1_MSTR|	// master
			SPI_CR1_BR|		// the lowest speed
			CPOL|
			CPHA;
 
	SPI1->CR2=
			SPI1->CR2&~0xE7|	// Clear all unreserved bits.
			SPI_CR2_SSOE;	// NSS is output.
 
 
	SPI2->CR1=				// Clear all bits except...
			CPHA|
			CPOL;
	SPI2->CR2&=~0xE7;		// Clear all unreserved bits.
 
	SPI1->CR1|=SPI_CR1_SPE;
	SPI2->CR1|=SPI_CR1_SPE;
 
	while(!(SPI2->SR&SPI_SR_TXE)) {}
	SPI2->DR=a2;
 
	while(!(SPI1->SR&SPI_SR_TXE)) {}
	SPI1->DR=a1;
 
	while(!(SPI1->SR&SPI_SR_RXNE)) {}
	b1=SPI1->DR;
 
	while(!(SPI2->SR&SPI_SR_RXNE)) {}
	b2=SPI2->DR;
 
	if(b1!=a2||b2!=a1)
	{
		// ERROR!!!
	}
 
	while(true) {}
}

4 REPLIES 4

What exactly are the received values and where is the mismatch?

Observe the pins using oscilloscope.

Try to set OSPEEDR to higher setting.

JW

Harry Hamper
Associate II
  1. In the model example above, the master (SPI1 here) sends 0x5A, the slave (SPI2) has to send 0x03. But really the slave sends 0x02 and receives 0x5B instead of 0x5A. It refers to the mode with CPOL=0, CPHA=0 (or CPOL=1, CPHA=1). There are no problems if CPOL=0, CPHA=1.
  2. The oscilloscope shows ideal edges. The logical state of the pins and flags of the SPI2 during transmission:0693W000005AEjFQAW.png
  3. There is no OSPEEDR in STM32F100xx. There is GPIOx->CRL, GPIOx->CRH (bits CNF, MODE). The maximum speed of GPIO is used in the example.

Yes I don't use the 'F1, am aware that GPIO is different but don't really know the exact implementation. I see you know what I am talking about nevertheless :)

Very nice diagram. Care to tell us how did yo produce it?

The upper 3 signals, they are from master or slave? Can you try to produce the same for the other SPI?

Is there any other hardware connected, or are the lines only plainly looped back to themselves?

Try perhaps lowering the "OSPEEDR" setting, especially for clock.

JW

Harry Hamper
Associate II

> Very nice diagram. Care to tell us how did yo produce it?

This is my logic self analyzer technique. The DMA, on a timer signal, reads SPIx->SR and the state of the pins (GPIOx->IR) and stores it in a memory buffer. Then we transfer the accumulated data to a PC for processing.

> The upper 3 signals, they are from master or slave? Can you try to produce the same for the other SPI?

Those are from slave. It is for master:0693W000005AFd8QAG.png> Is there any other hardware connected, or are the lines only plainly looped back to themselves?

They are only looped back to themselves.

> Try perhaps lowering the "OSPEEDR" setting, especially for clock.

And yes! The device operates normally in all modes after decreasing the speed of outputs. I should think.

Thanks a lot for your help!