cancel
Showing results for 
Search instead for 
Did you mean: 

STMF103R8T6 SPI2 slave receive

youssef
Associate II
Posted on October 13, 2011 at 17:15

Hello,

We are trying to send a 44 byte report over SPI from one STM32F103 to another board.

 Our master sends this data out every 5ms, and our slave receives data based on an interrupt. 

We are experiencing an issue were our last byte from one report is received before the first byte of the second report (so we receive it 5ms later and with the wrong report).

Once the first byte comes in and triggers the interrupt, we loop for the rest of the values rather than having 44 interrupts happen. We also send some bytes during the receiving period, but this part has not been fully implemented/tested yet. Currently, we are using SPI2 with these master configurations:

/** Initializes SPI clock */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

SPI_InitTypeDef SPI_InitStructure;

/* SPI2 Config -------------------------------------------------------------*/

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;

SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

SPI_InitStructure.SPI_CRCPolynomial = 0;

SPI_Init(SPI2, &SPI_InitStructure);

SPI_CalculateCRC(SPI2, DISABLE);

/* Enable SPI2 */

SPI_Cmd(SPI2, ENABLE);

//GPIO

GPIO_InitTypeDef GPIO_InitStructure;

/* Configure SPI2 pins: SCK, MOSI, MISO -------------------------*/

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; //changed from 2Mhz

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOB, &GPIO_InitStructure);

/* Configure SPI2 pins: NSS ---------------------------------*/

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //was Mode_out_PP

GPIO_Init(GPIOB, &GPIO_InitStructure);

And our slave configurations:

/** Initializes SPI clock */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

SPI_InitTypeDef SPI_InitStructure;

/* SPI1 Config -------------------------------------------------------------*/

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;

SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;

SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

SPI_InitStructure.SPI_CRCPolynomial = 0;

SPI_Init(SPI2, &SPI_InitStructure);

SPI_CalculateCRC(SPI2, DISABLE);

/* Enable SPI2 */

SPI_Cmd(SPI2, ENABLE);

//GPIO

GPIO_InitTypeDef GPIO_InitStructure;

/* Configure SPI2 pins: MOSI, MISO -------------------------*/

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOB, &GPIO_InitStructure);

/* Configure SPI2 pins: NSS ------------------------------------*/

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;

GPIO_Init(GPIOB, &GPIO_InitStructure);

Here is out ISR configurations:

NVIC_InitTypeDef NVIC_InitStructure;

// Enable SPI IRQ IRQ Channel -----------------------------------------

NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQChannel;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 7;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);

We are running into a few odd problems.

1) Occasionally the receiver reads the data as if it was bit-shifted by some amount. When we check the data on the logic analyzer it is coming out correctly from the master. The only way we have seen to fix this is to restart both and try again.

2) This is the more serious problem we are experiencing. We receive the last byte of each report at the beginning of the next report. From our logic analyzer testing, we are sending out the data at the correct time though. so we send:

Master sends:

byte 41 -> byte 42 -> byte 43 -> byte 44 ---------------5ms-------------------- byte 1 -> byte 2

Receiver gets:

byte 41 -> byte42 -> byte 43 ------------------5ms-------------------- byte 44 -> byte 1 -> byte 2

Here is our receiving code:

void rx_only_spi2_isr(void)

{

SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, DISABLE);

int cnt=0;

for(;cnt<44;cnt++)

{

if(cnt>34 && cnt<43)

SPI_I2S_SendData( SPI2, cnt );

while( SPI_I2S_GetFlagStatus( SPI2, SPI_I2S_FLAG_RXNE ) == RESET );

spi_buf[cnt] = SPI_I2S_ReceiveData( SPI2 );

}

SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);

}

Any help would be greatly appreciated.
4 REPLIES 4
Posted on October 13, 2011 at 17:38

I'm not sure of the wisdom of disabling/enabling the interrupt in this fashion. Keep the interrupt brief, ie don't spin and poll stuff endlessly, use a state machine and account for each byte as it arrives, and forward the complete packet when done.

Also make sure that the RXNE is cleared before starting, otherwise it can flag with old/stale data.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
youssef
Associate II
Posted on October 14, 2011 at 17:38

Clive1,  are you saying to do a dummy read of the Receive buffer to clear RXNE?  If so, I have added in the code during the initialization and it doesn't change anything.

Also, as far as the state machine idea.  While it has merit and sounds good, I can't justify spending the time writing that up since we have SPI1 working with the current code and configurations (/8 to maintain the same speed, I think).  Let me know what you think about that, it would be really nice if we can get SPI2 to work properly also.

Posted on October 14, 2011 at 19:17

So what happens when your working SPI1 code blocks all further processing of SPI2?

You're interrupt processing methodology is broken, time spent fixing it will be time saved later.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
youssef
Associate II
Posted on October 14, 2011 at 22:40

Its not how the code runs really.  What I am saying is we have copied this code over to SPI1 instead, just to see if it would work.  and it does.  We will only have 1 SPI that is running interrupt based, but it would be nice if we could get the choice.

Can you explain what you mean by the interrupt processing methodology is broken?