cancel
Showing results for 
Search instead for 
Did you mean: 

SPI Communication Issues

Posted on March 29, 2013 at 23:57

I am using the stm32l151RB microcontroller. It is running on an external clock source at 14.7456 MHz. I am communicating with a Micron M25P16 serial flash memory. This device states that it is compatible with CPOL/CPHA configurations of 0/0 and 1/1.

I am currently in the hardware validation phase writing simple blocks of code just to make sure the layout is correct. I was able to read the manufacturer id, memory type and memory capacity off of the device using a CPOL/CPHA set to 1/1.

The problem is that when CPOL/CPHA are set to 0/0 I am unable to read the previously listed items. Originally I was getting nothing but zeroes, but I have since updated to the latest SPI library files that I could find on the website. I now get 0xFF when I attempt to read. Also strangely enough when hooked up to the scope, we don't see any data coming out of the controller on the MOSI line in the 0/0 configuration. Any help that can be provided would be greatly appreciated. Please let me know that additional information I can provide.

Below you will find a snippet of the code that I am using detailing the SPI configuration.

Pin Configurations

void SPI_Flash_LowLevel_Init(void)

{

  GPIO_InitTypeDef  GPIO_InitStructure;

   

  RCC_AHBPeriphClockCmd(FLASH_SPI_CS_GPIO_CLK | FLASH_SPI_MOSI_GPIO_CLK | FLASH_SPI_MISO_GPIO_CLK |

                        FLASH_SPI_SCK_GPIO_CLK, ENABLE);

  RCC_APB2PeriphClockCmd(FLASH_SPI_CLK, ENABLE);

  GPIO_InitStructure.GPIO_Pin = FLASH_SPI_SCK_PIN;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;

  GPIO_Init(FLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);

 

  GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MISO_PIN;

  GPIO_Init(FLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MOSI_PIN;

  GPIO_Init(FLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);

 

  /*MKM - TODO - Clean this up and put this pin configuration in the right place*/

  GPIO_InitStructure.GPIO_Pin = FLASH_SPI_CS_PIN;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

  GPIO_Init(FLASH_SPI_CS_GPIO_PORT, &GPIO_InitStructure);

 

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

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

  GPIO_Init(FLASH_SPI_CS_GPIO_PORT, &GPIO_InitStructure);

 

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

  GPIO_Init(FLASH_SPI_CS_GPIO_PORT, &GPIO_InitStructure);

 

  GPIO_PinAFConfig(FLASH_SPI_SCK_GPIO_PORT, FLASH_SPI_SCK_SOURCE, FLASH_SPI_SCK_AF);

  GPIO_PinAFConfig(FLASH_SPI_MISO_GPIO_PORT, FLASH_SPI_MISO_SOURCE, FLASH_SPI_MISO_AF);

  GPIO_PinAFConfig(FLASH_SPI_MOSI_GPIO_PORT, FLASH_SPI_MOSI_SOURCE, FLASH_SPI_MOSI_AF);  

 

  SPI_Cmd(FLASH_SPI, ENABLE);

}

Usage

unsigned int i,mfg,memtype,capacity,address;

            

static portTASK_FUNCTION( vSPITask, pvParameters )

{

  /* The parameters are not used. */

  ( void ) pvParameters;

 

  SPI_InitTypeDef   SPI_InitStructure;

  SPI_InitTypeDef   *ptr_SPI_InitStructure;

  ptr_SPI_InitStructure = &SPI_InitStructure;

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

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

  SPI_InitStructure.SPI_CRCPolynomial = 7;

  SPI_Init(FLASH_SPI, &SPI_InitStructure);  

 

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

  SPI_Init(FLASH_SPI, ptr_SPI_InitStructure);

  SPI_Cmd(FLASH_SPI, ENABLE);

 

   for(;;){

    

     

    GPIO_ResetBits(GPIOA, GPIO_Pin_4); //Flash Chip Select

    //GPIO_ResetBits(GPIOA, GPIO_Pin_3); //FPGA Chip Select

    

    while(SPI_GetFlagStatus(FLASH_SPI, SPI_FLAG_TXE)==RESET){}

    

    SPI_SendData(FLASH_SPI,0x9F); //Read ID command

    while(SPI_I2S_GetFlagStatus(FLASH_SPI, SPI_I2S_FLAG_TXE)==RESET){}

    SPI_I2S_ReceiveData(FLASH_SPI); // Clear out any pending RX data

    SPI_I2S_SendData(FLASH_SPI,0x00); // Junk Byte        

    

    while(SPI_GetFlagStatus(FLASH_SPI, SPI_FLAG_RXNE)==RESET){}

   

    mfg = SPI_ReceiveData(FLASH_SPI); // Manufactuer ID 0x20

   

    while(SPI_GetFlagStatus(FLASH_SPI, SPI_FLAG_TXE)==RESET){}

    SPI_SendData(FLASH_SPI,0x00); // Junk Byte

    while(SPI_GetFlagStatus(FLASH_SPI, SPI_FLAG_RXNE)==RESET){}

   

    memtype = SPI_I2S_ReceiveData(FLASH_SPI);

    while(SPI_GetFlagStatus(FLASH_SPI, SPI_FLAG_TXE)==RESET){}

    SPI_SendData(FLASH_SPI,0x00); // Junk Byte

    while(SPI_GetFlagStatus(FLASH_SPI, SPI_FLAG_RXNE)==RESET){}

    capacity = SPI_ReceiveData(FLASH_SPI);

    GPIO_SetBits(GPIOA, GPIO_Pin_4);

    vTaskDelay( 2000/ portTICK_RATE_MS );

   }

}

 

#spi #spi-cpha #spi-st32l151rb
11 REPLIES 11
oversc0re
Associate II
Posted on July 08, 2015 at 14:58

Jack thank you for this post. My driver with SPI mode 0 worked for quite some time :) but now I found a couple of devices that have some problems and I think edge sampling might be the problem. 

If you are still active here on this forum I'd like to ask you, how did you handle the switch from mode 0 to mode 3. 

I asserted CS, sent command and address with mode 0, changed to mode 1 (waited until SPI is busy) and tried to read the data. Nothing useful comes out. Could you please comment on this?

Thanx,

Oversc0re 

jpeacock
Associate III
Posted on July 08, 2015 at 19:34

If an SPI peripheral reads and writes on different clock edges then I switch the SPI port on the fly, depending on if I'm reading or writing to the port.  Change the mode before asserting CS so any clock changes aren't seen by the peripheral.

  Jack Peacock