cancel
Showing results for 
Search instead for 
Did you mean: 

SPI2 Slave bit shift problem

ivano
Associate II
Posted on July 03, 2013 at 15:27

Dear all I hope you can solve m problem. I need to configure the SPI2 on STM32F100V8 on pin PB12-14 in slave mode because I have a master board that communicates to other spi slaves. The SPI has the Clock normally High and the data of the master changes on falling edge of the clock (so I think the slave stm32 should be setted as CPOL High and CPHA = second edge, rising)

Here some little hardware

Master CLK -> Slave STM32 CLK

Master MISO <- Slave STM32 MISO (unconnected from Master for debug purposes)

Master MOSI -> Slave STM32 MOSI

Master CS -> dedicated line to Slave STM32 NSS

In this project i need to use UART3 but is used in asyncronous mode so this excludes some silicon bugs described in the ''errata''

The gpio are congigured as AF_PP, the RCC is enabled for SPI2, and the SPI is initialized in this way:

static void SPI2_Init (void){

 

  SPI_InitTypeDef SPI_InitStructure;

 

  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_Hard;      

 

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

 

  SPI_Init(SPI2, &SPI_InitStructure);

 

  SPI_Cmd(SPI2, ENABLE);

 

}

Here the task that is called in a while(1), no watchdog enabled no other tasks enabled for  the moment

void task_spi(vpoid){

 

  static unsigned char state;

 

   unsigned char read

 

  case 0:

 

      if(READ_CS_SPI2()==0){

 

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

 

        read = SPI_I2S_ReceiveData(SPI2);

 

        if(read==0x02){

 

          state = read;

 

          read = 0;

 

        }

 

      }

 

  case 2:

 

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

 

       SPI_I2S_SendData(SPI2, 0xFF); 

 

       TOGGLE_S4();

 

       state = 99;

 

  break;

 

  case 99:

 

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

 

       SPI_I2S_SendData(SPI2, 0x00); 

 

       state = 0;

 

  break;

 

  default:

 

      state = 0;

 

  break;

 

 

 

  }

 

}

With this code i have correct receive of the data in the slave stm32 but i have troubles in sending response data. For example if i try to send a reply 0xFF in my oscilloscope I see: 0xFE.

If I try to send 0xAA i only see glitches on the MISO line ( at the moment the miso line is disconnected from the master)

Hope someone can take me away from troubles. Regards, Ivano

Attached two Stamps of the scope for more clarification...

#spi2-problem-stm32f100v8
6 REPLIES 6
John F.
Senior
Posted on July 03, 2013 at 16:31

This may be nothing to do with your problem. I'm using an STM32F4 When sending SPI data, I wait on TXE and then on BSY.

DataToSend = (0x7000 | (pData->Channel_H << 4));
XDAC1_CS_LOW();
SPI_I2S_SendData(SPI1, DataToSend); //Send 16 bits through the SPI1 peripheral
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); //wait for TX buffer flag to set
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); //wait for BSY flag to clear
XDAC1_CS_HIGH();

I found a note from ST, ''During discontinuous communications, there is a 2 APB clock period delay between the write operation to SPI_DR and the BSY bit setting. As a consequence, in transmit-only mode, it is mandatory to wait first until TXE is set and then until BSY is cleared after writing the last data.''
ivano
Associate II
Posted on July 03, 2013 at 18:36

Dear Sir John F, thank you for your reply but I'm still in troubles.

Here attached a printscreen and the modified code (as you suggest); from images especially in the one to the right you can see that STM32

exits beforehand

from sending all data bits (second execution in case =2 of istruction TOGGLE_S4(), green line).

The code:

void task_spi(vpoid){

static unsigned char state; unsigned char read switch(state){ case 0: if(READ_CS_SPI2()==0){ while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE)==RESET);

while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY)==SET);

read = SPI_I2S_ReceiveData(SPI2); if(read==2){ state = 2; } } break; case 2:

TOGGLE_S4();

//FIRST TOGGLE OF GREEN LINE SPI_I2S_SendData(SPI2, 0xAA); while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)==RESET);

while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY)==SET);

TOGGLE_S4();

//SECOND TOGGLE OF GREEN LINE state = 99; break; case 99: SPI_I2S_SendData(SPI2, 0x00); while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)==RESET);

while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY)==SET);

state = 0; break; default: state = 0; break; }}

Attached new images

________________

Attachments :

3.jpg : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0vj&d=%2Fa%2F0X0000000bgG%2FWmwVXp2fODFLkP3x.8nruVVXbwm0cIZlrh5IAH4bnvE&asPdf=false
fernando
Associate II
Posted on July 04, 2013 at 07:53

Which library do you use for spi interface? Maybe trying to update libraries could solve ?
ivano
Associate II
Posted on July 04, 2013 at 08:19

My library version:

* Version            : V2.0.3

* Date               : 09/22/2008

Dear Sir lavega.fernando, honestly I would avoid in changing libraries without the security that this will solve the problem and, honestly,  I do not think that the problem is library related. Do you know if there have been problems like that with libraries?

ivano
Associate II
Posted on July 04, 2013 at 13:43

While I wait for an answer I'll try the same code on STM32 discovery board MB963 B but the mcu is different and I don't know if it is a valid test

John F.
Senior
Posted on July 04, 2013 at 14:43

If I have understood your requirements ...

In slave mode, the clock is provided by the external master. Data for transmission must be loaded into the TX buffer before the SPI clock starts (and only if TXE flag is set). If you are responding to received data, your response cannot be sent until the master sends more data.

Please have a look at the SPI section in RM0041 ''21.3.2 Configuring the SPI in slave mode'' where the Transmit and Receive sequences are described. Be aware that data already loaded into the TX buffer is transmitted only when the master is sending data you will receive - they happen at the same time - and consider if your task structure is suitable for what you want to do. The write to the DR must occur between SPI clock bursts. It looks like you should be writing new data to the DR with SPI_I2S_SendData() immediately after you have read received data. Straight after RXNE bit is set so it's ready to be sent next time the master clocks the SPI bus.

I didn't see an STM32 SPI slave code example. Maybe someone has this working?