cancel
Showing results for 
Search instead for 
Did you mean: 

STM32f217IG SPI Master MISO question

rmpresto
Associate II
Posted on June 07, 2012 at 08:55

I have read through many posts about SPI problems and configuration questions.  I feel I have everything configured correctly, however I do not receive any data transferred across the MISO line.  Below shows the configuration code used:

/////////////////////////////////////////////////////////////// Begin Config////////////////////////////////////////////////////////////////////////////////

GPIO_InitTypeDef GPIO_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

SPI_InitTypeDef  SPI_InitStructure;

  /* Enable the SPI clock */

  SPIx_CLK_INIT(SPIx_CLK, ENABLE);

  /* Enable GPIO clocks */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOC  , ENABLE);

  /* Connect SPI pins to AF5 */  

  GPIO_PinAFConfig(GPIOI, GPIO_PinSource1, GPIO_AF_SPI2); // SPI SCLK

  GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_SPI2); // MOSI

  GPIO_PinAFConfig(GPIOC, GPIO_PinSource2, GPIO_AF_SPI2); // MISO

  GPIO_PinAFConfig(GPIOI, GPIO_PinSource2, GPIO_AF_SPI2); // CS

  

    /* SPI CS pin configuration */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init (GPIOI, &GPIO_InitStructure);

    

  

   /* SPI SCK pin configuration */

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

  GPIO_Init(GPIOI, &GPIO_InitStructure);

  /* SPI  MOSI pin configuration */

  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_3;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

  

    /* SPI  MISO pin configuration */

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;

  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_2;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

  

/* SPI configuration -------------------------------------------------------*/

  SPI_I2S_DeInit(SPI2);

  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;

  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;

  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

  SPI_InitStructure.SPI_CRCPolynomial = 7;

  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

  SPI_Init(SPI2, &SPI_InitStructure);

  

  /* Configure the Priority Group to 1 bit */                

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

  

  /* Configure the SPI interrupt priority */

  NVIC_InitStructure.NVIC_IRQChannel = SPIx_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

//////////////////////////////////////////////////////////////////END CONFIG /////////////////////////////////////////////////////////

ok so after this config (assuming its correct) I set the CS pin high and enable spi and interrupts :

GPIO_WriteBit(GPIOI,GPIO_Pin_2, Bit_SET);

SPI_Cmd(SPI2, ENABLE);

SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE);

SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);

Next I Transmit a 0x9F out to an EEPROM to read the device ID. ( CS is active low and is MSB first)

 GPIO_WriteBit(GPIOI,GPIO_Pin_2, Bit_RESET); // CS LOW

  SPI_I2S_SendData(SPI2, 0x9F);  // Send Data

Every time the TxE is empty it sends out the 9F.  The RXNE does go high and i read the first received 512 bytes in the DR as follows:

  if (SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_RXNE) == SET)

  {

      if (Rx_Idx < 512)

     {

        RxBuffer[Rx_Idx++] = SPI_I2S_ReceiveData(SPI2);

     }

    else

    {

               SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, DISABLE);

      GPIO_WriteBit(GPIOI,GPIO_Pin_2, Bit_SET);// CS HIGH

      int x = 0; 

    }

}

On the oscilloscope I do see data across the MISO line ( Device ID ) but I do not receive it in the micro rx buffer.

Any suggestions would be of great help; Maybe I overlooked something. 

Thanks in advanced for your help

#spi #stm32
9 REPLIES 9
Posted on June 07, 2012 at 11:47

The topic line is slightly misleading: you are trying to use the SPI module in I2S mode, and that makes a substantial difference.

Please read the user manual, chapter 25.2.2 I2S features, the very first line states: ''Simplex communication (only transmitter or receiver).

You would need to use two SPI modules, one as master transmitter and other as slave receiver (with appropriately connected clock pins) to achieve a 4/5-wire full-duplex ISP connection.

On the other hand, your remark:

> Next I Transmit a 0x9F out to an EEPROM to read the device ID.

 leads me to think that you simply misunderstood the purpose of I2S.

JW

rmpresto
Associate II
Posted on June 07, 2012 at 15:28

Where does it indicate that i am using I2S mode?  

I need to be using SPI where the MC is the master and EEPROM is the Slave.  I am a little confused by your response. Maybe your right but can you please explain a little more? 

Thanks

Posted on June 07, 2012 at 15:58

> Where does it indicate that i am using I2S mode?  

Nowhere, indeed. I must have been obsessed by I2S after having spent a day of hunting down errors in it... :) Sorry.

JW

rmpresto
Associate II
Posted on June 07, 2012 at 16:34

I noticed that the voltage level of EEPROM MISO message was below 2 volts... I decided to take off the MISO pin from the pad and wire a 3.3 volts directly to the pad.  Doing this would confirm that my setup is correct in which I expect to receive an 0xFF  since the line is being held high.  

I just tested this and did receive 512 0xFF.  Therefore on the micro there could be another peripheral driving the MISO pin low..  I am going to have to check what other peripherals use the SPI MISO line make sure they are inactive.  I did set the CS on all other peripherals to high, but maybe one of them is active high. 

I find it weird in the schematic of the micro that there is a pull up resistor on the MISO EEPROM and when configuring the pins it is held low.  When traffic crosses it is always below 2 volts.  There must be some sort of pin contention.

I will look more into this problem, but if there are any suggestions feel free to give your opinion.

Thanks.   

stenasc
Senior
Posted on December 06, 2012 at 16:29

Rob,

Did you find a solution? I'm seeing the same issue. I can see the data on MISO, but I can't capture it for whatever reason. Any help greatly appreciated.

Thanks

Bob

Posted on December 06, 2012 at 17:46

Did you find a solution? I'm seeing the same issue. I can see the data on MISO, but I can't capture it for whatever reason. Any help greatly appreciated.

With METOO issues it always helps to explain your specific situation, and provide code and connectivity details. There are thousands of reasons why things don't work, and they are not always identical.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stenasc
Senior
Posted on December 10, 2012 at 22:45

I'm trying to read and write data to the ST 95M02 EEProm, using SPI2 port on a stm32f051 processor. A simple test is to write to the status register and read back. I can see data from MOSI on the scope, but can't latch it in. The value returned is always 00h. Another issue is that the EEprom datasheet has some figures missing for flash read and flash write (even though they are referred to) which doesn't help matters.

If I could read the status register, then it would be a good start.

From Main calling function

....

  // SPI configuration ------------------------------------------------------

SPI_Config();

WriteEnable();

SPI_statusReg_Write(0x01, 0x06);

// Just a loop to monitor received data and view on scope

for (ee_add = 0; ee_add<1000; ee_add++)

  {    

    spi_rd_data = SPI_statusReg_Read(0x05);       

   printf(''\n\r Spi data = %d'',  spi_rd_data);

  }

// Rest of calling function

void SPI_Config(void)

{

  SPI_InitTypeDef SPI_InitStructure;

  GPIO_InitTypeDef GPIO_InitStructure;

  /* Enable the SPI peripheral */

//  RCC_APB1PeriphClockCmd(SPIx_CLK, ENABLE);

    /* Enable SPI clock, SPI2 */

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);    

    

  /* Enable SCK, MOSI, MISO and NSS GPIO clocks */

  RCC_AHBPeriphClockCmd(SPIx_SCK_GPIO_CLK | SPIx_MISO_GPIO_CLK | SPIx_MOSI_GPIO_CLK |

                        SPIx_NSS_GPIO_CLK , ENABLE);

    

  /* SPI pin mappings */

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;

  /* SPI SCK pin configuration */

  GPIO_InitStructure.GPIO_Pin = SPIx_SCK_PIN;

  GPIO_Init(GPIOB, &GPIO_InitStructure);

  /* SPI MOSI pin configuration */

  GPIO_InitStructure.GPIO_Pin = SPIx_MOSI_PIN;

  GPIO_Init(GPIOB, &GPIO_InitStructure);

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

  /* SPI MISO pin configuration */    

  GPIO_InitStructure.GPIO_Pin = SPIx_MISO_PIN;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;    // This needs to have a PULL-UP otherwise only driven to half the required level

  GPIO_Init(GPIOB, &GPIO_InitStructure);

 

  /* SPI NSS pin configuration */

 // GPIO_InitStructure.GPIO_Pin = SPIx_NSS_PIN;

 // GPIO_Init(GPIOB, &GPIO_InitStructure);

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

  /* Configure CS pin as output floating */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

  GPIO_Init(GPIOB, &GPIO_InitStructure);    

      

        

 

  /* SPI configuration -------------------------------------------------------*/

  SPI_I2S_DeInit(SPIx);

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

  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;

  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

 

  SPI_Init(SPIx, &SPI_InitStructure);

  SPI_SSOutputCmd(SPIx, ENABLE);

  SPI_Cmd(SPIx, ENABLE);

        

}

void WriteEnable(void)

{

    EEPROM_CS_LOW;

    SPI_SendData8(SPIx, 0x06);    

    // Wait for SPI Tx buffer empty

    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) != SET);

        // Clear receive buffer

    Clr_Rcv_Buf();    

    EEPROM_CS_HIGH;    

uint8_t SPI_statusReg_Write(uint8_t ins, uint8_t data)

{    

    EEPROM_CS_LOW;

    // Send SPI instruction         

    SPI_SendData8(SPIx, ins);

    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) != SET);

    Clr_Rcv_Buf();    

    

    SPI_SendData8(SPIx, data);

    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) != SET);

    Clr_Rcv_Buf();    

    EEPROM_CS_HIGH;        

     return (1);

}

uint8_t SPI_statusReg_Read(uint8_t ins)

{

// Delay between instruction and data read back    

uint8_t spi_rd_data;

        

      EEPROM_CS_LOW;

    // Send SPI instruction         

    SPI_SendData8(SPIx, ins);                

    // Wait for SPI Tx buffer empty

    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) != SET);

    Clr_Rcv_Buf();

      // Send Dummy Byte for Clocks

    SPI_SendData8(SPIx, 0xFF);

    // Wait for the data

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

            

        // read the received data from the register    

    spi_rd_data = SPI_ReceiveData8(SPIx);

            

    // wait for finish

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

    

    EEPROM_CS_HIGH;        

        

    return (spi_rd_data);

}

void Clr_Rcv_Buf(void)

{

uint8_t spi_rd_data;    

     /* Clears the receive buffer or we would get overrun errors */

    if (SPI_I2S_GetFlagStatus(SPIx,SPI_I2S_FLAG_RXNE) == SET)

       spi_rd_data = SPI_ReceiveData8(SPIx);

}

Posted on December 11, 2012 at 03:19

Bit of a mish-mash of styles there, absent the defines it's hard to clear up. You only need to enable a GPIO clock once, but it must occur prior to configuring the pins. You also need to route the SPI function to the pin's AF section using GPIO_PinAFConfig(GPIOx, GPIO_PinSourceX, GPIO_AF_X)

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stenasc
Senior
Posted on December 11, 2012 at 09:53

I had the following statements just after the GPIO pins configuration, but it made no difference so I removed them....The chip select wouldn't pulse so I had to drive it as an ordinary GPIO pin..hence the different styles.

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, SPIx_SCK_AF);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, SPIx_MISO_AF);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, SPIx_MOSI_AF);

        GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, SPIx_NSS_AF);

Definitions follow

#define EEPROM_CS_LOW            GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_RESET);

#define EEPROM_CS_HIGH        GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_SET);

#define SPI_DATASIZE                     SPI_DataSize_8b

#define SPI_DATAMASK                     (uint8_t)0xFF

#define SPIx                             SPI2

#define SPIx_CLK                         RCC_APB2Periph_SPI2

#define SPIx_SCK_PIN                     GPIO_Pin_13

#define SPIx_SCK_GPIO_PORT               GPIOB

#define SPIx_SCK_GPIO_CLK                RCC_AHBPeriph_GPIOB

#define SPIx_SCK_SOURCE                  GPIO_PinSource13

#define SPIx_SCK_AF                      GPIO_AF_0

#define SPIx_MISO_PIN                    GPIO_Pin_14

#define SPIx_MISO_GPIO_PORT              GPIOB

#define SPIx_MISO_GPIO_CLK               RCC_AHBPeriph_GPIOB

#define SPIx_MISO_SOURCE                 GPIO_PinSource14

#define SPIx_MISO_AF                     GPIO_AF_0

#define SPIx_MOSI_PIN                    GPIO_Pin_15

#define SPIx_MOSI_GPIO_PORT              GPIOB

#define SPIx_MOSI_GPIO_CLK               RCC_AHBPeriph_GPIOB

#define SPIx_MOSI_SOURCE                 GPIO_PinSource15

#define SPIx_MOSI_AF                     GPIO_AF_0

#define SPIx_NSS_PIN                     GPIO_Pin_12

#define SPIx_NSS_GPIO_PORT               GPIOB

#define SPIx_NSS_GPIO_CLK                RCC_AHBPeriph_GPIOB

#define SPIx_NSS_SOURCE                  GPIO_PinSource12

#define SPIx_NSS_AF                      GPIO_AF_0