/var/www/restricted/ssh/stm32/www/stm32circle/ STM CircleOS forum / connecting to the MEMS motion sensor over SPI

Username:     
Password:     
             

Forum
  • Index
  •  » circleOS
  •  » connecting to the MEMS motion sensor over SPI

# 1   2009-02-21 06:40:16 connecting to the MEMS motion sensor over SPI

Andrew
New member
Registered: 2009-02-20
Posts: 6

connecting to the MEMS motion sensor over SPI

Hello,
Sorry for the offtopic. I am trying to connect LIS302DL motion sensor to the STM32F103 on our custom board over SPI bus. I was advised that Primer communicates to the motion sensors via SPI bus as well.

I didn't use additional schematics and directly connected CS, SCL, SDx, SDO of LIS302DL to the NSS, SCK, MOSI, MISO respectively (similarly as it is done in Primer).

With oscilloscope I can see perfectly shaped square signal on SCL and SDx. But SDO pin (that has to be sensor's output signal) produces saw-like signal where each period looks like triangle.

I have looked at Circle OS sources, that are available here:
http://www.stm32circle.com/projects/project.php?id=49
and found that very interesting process is used there that is called 'SPI resynchronization'  In general it tries to reinitialize SPI pins until it is possible to read Identification from motion sensor chip. (excerpt from MEMS_Init() is attached below)

So I wonder  if there is anybody who could shed some light upon the concept behind SPI resynchronization or on possible reason of incorrect form of the SDO signal in my case.

A smallest comment will be hugely appreciated.
Andrew.

Code:

    /* Enable SPI  */
    SPI_Cmd( SPIX_MEMS, ENABLE );

    if( MEMS_ReadID() != 0x3A )
        {
        int i;

        // Try to resynchronize
        for( i = 0 ; i < 17 ; i++ )
            {
            /* Configure SPI2 pins: SCK, MISO and MOSI */
            GPIO_InitStructure.GPIO_Pin   = GPIO_PIN_MEMS_SCK | GPIO_PIN_MEMS_MOSI;
            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
            GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;

            GPIO_Init( GPIOX_MEMS_CTRL, &GPIO_InitStructure );
            GPIO_WriteBit( GPIOX_MEMS_CTRL, GPIO_PIN_MEMS_MOSI, HIGH );
            MEMS_ChipSelect( LOW );

            GPIO_WriteBit( GPIOX_MEMS_CTRL, GPIO_PIN_MEMS_SCK, LOW );
            GPIO_WriteBit( GPIOX_MEMS_CTRL, GPIO_PIN_MEMS_SCK, HIGH );
            MEMS_ChipSelect( HIGH );

            /* Configure again PB. SCK as SPI2 pin */
            GPIO_InitStructure.GPIO_Pin   = GPIO_PIN_MEMS_SCK | GPIO_PIN_MEMS_MOSI;
            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
            GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;

            GPIO_Init( GPIOX_MEMS_CTRL, &GPIO_InitStructure );
            if ( MEMS_ReadID() == 0x3A )
                {
                break;
                }
            }

        if( i == 17 )
            {
            DRAW_DisplayString( 1, 50, "Test MEM ID Failed", 18 );
            }

Offline

 

# 2   2009-02-21 08:47:38 connecting to the MEMS motion sensor over SPI

sjoerd
Member
From: Stad aan het Haringvliet
Registered: 2008-09-04
Posts: 65

Re: connecting to the MEMS motion sensor over SPI

Do you configure the MOSI pin?  (i can't find it in your code)


You can check the code from this project: http://www.stm32circle.com/projects/project.php?id=54
I've used the SPI bus to communicate with a RF module.

Offline

 

# 3   2009-02-21 09:59:47 connecting to the MEMS motion sensor over SPI

Francis
Administrator
From: France-Grenoble
Registered: 2007-07-09
Posts: 890

Re: connecting to the MEMS motion sensor over SPI

We introduced this resynchronization because there is no 'RESET' pin on this device. When you debug, you often stop a session randomly, and you always have the risk to interrupt a SPI communication within a byte transmission. A transmission is made of a certain number of clock (I don't remember but let say N). If after reading the IdCode, we don't find it, we assume that we are desymchronized and we send one clock more with the hope that the desymchronization was just one clock. If it does not work, we try again. With N tries, we are sure that must have encountered a synchronized situation. It works.

Offline

 

# 4   2009-02-22 00:09:45 connecting to the MEMS motion sensor over SPI

Andrew
New member
Registered: 2009-02-20
Posts: 6

Re: connecting to the MEMS motion sensor over SPI

sjoerd :

Do you configure the MOSI pin?  (i can't find it in your code)


You can check the code from this project: http://www.stm32circle.com/projects/project.php?id=54
I've used the SPI bus to communicate with a RF module.

Hello, thanks for the link
Yes, I configured MOSI pin as:

Code:

    GPIO_InitStructure.GPIO_Pin   = GPIO_PIN_MEMS_SCK | GPIO_PIN_MEMS_MISO | GPIO_PIN_MEMS_MOSI;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;

Offline

 

# 5   2009-02-22 00:12:42 connecting to the MEMS motion sensor over SPI

Andrew
New member
Registered: 2009-02-20
Posts: 6

Re: connecting to the MEMS motion sensor over SPI

Francis :

We introduced this resynchronization because there is no 'RESET' pin on this device. When you debug, you often stop a session randomly, and you always have the risk to interrupt a SPI communication within a byte transmission. A transmission is made of a certain number of clock (I don't remember but let say N). If after reading the IdCode, we don't find it, we assume that we are desymchronized and we send one clock more with the hope that the desymchronization was just one clock. If it does not work, we try again. With N tries, we are sure that must have encountered a synchronized situation. It works.

Hello Francis,
Thanks for the information. This makes sense.
But unfortunately it doesn't solve my problem with the triangular signal as I hoped.
Will investigate furhter.

Thanks.

Offline

 

# 6   2009-02-23 10:41:46 connecting to the MEMS motion sensor over SPI

Francis
Administrator
From: France-Grenoble
Registered: 2007-07-09
Posts: 890

Re: connecting to the MEMS motion sensor over SPI

Did you try with a lower bit rate ?

Offline

 

# 7   2009-02-24 07:13:25 connecting to the MEMS motion sensor over SPI

Andrew
New member
Registered: 2009-02-20
Posts: 6

Re: connecting to the MEMS motion sensor over SPI

Hello Francis,
yes, I set lowest possible bit-rate:
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;

I am attaching my code below. In the main function I am trying to read identification register of the sensors.
The code is relatively big, sorry for this. If you could tell me what I am doing wrong, I was in much debt to you.

Great thanks in advance

Code:

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"

/* Local includes ------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;

/* Private define ------------------------------------------------------------*/
#define BufferSize 32

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
SPI_InitTypeDef   SPI_InitStructure;


/* Private functions ---------------------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);

void RCC_Configuration(void)
{
  /* RCC system reset(for debug purpose) */
  RCC_DeInit();

  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  ErrorStatus HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if (HSEStartUpStatus == SUCCESS)
  {
    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1);

    /* PCLK2 = HCLK/2 */
    RCC_PCLK2Config(RCC_HCLK_Div2);

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2);


    
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);


    /* PLLCLK = 8MHz * 9 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
    

    /* Enable PLL */
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {}

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while (RCC_GetSYSCLKSource() != 0x08)
    {}
  }

  /* Enable peripheral clocks --------------------------------------------------*/
  /* GPIOA, GPIOB and SPI1 clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC |
                         RCC_APB2Periph_SPI1, ENABLE);
  /* SPI2 Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
}

void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* Configure SPI1 pins: SCK, MOSI ---------------------------------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7; //GPIO_Pin_6 | 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;//GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//GPIO_Mode_Out_PP;//GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);


  /* Configure SPI1 pins: MISO  ---------------------------------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//GPIO_Mode_Out_PP;//GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  
  /* Configure SPI1 pins: SS ---------------------------------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

 }

void NVIC_Configuration(void)
{
#ifdef  VECT_TAB_RAM
  /* Set the Vector Table base location at 0x20000000 */
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else  /* VECT_TAB_FLASH  */
  /* Set the Vector Table base location at 0x08000000 */
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
}

/*******************************************************************************
* Function Name  : main
* Description    : Main program
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
int main(void)
{

  /* System clocks configuration ---------------------------------------------*/
  RCC_Configuration();

  /* NVIC configuration ------------------------------------------------------*/
  NVIC_Configuration();

  /* GPIO configuration ------------------------------------------------------*/
  GPIO_Configuration();

  

  /* 1st phase: SPI1 Master and SPI2 Slave */
  /* SPI1 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_CPOL_Low;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//SPI_NSS_Soft; //SPI_NSS_Hard;//
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;//SPI_BaudRatePrescaler_4;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//SPI_FirstBit_LSB;
  SPI_InitStructure.SPI_CRCPolynomial = 0;
  SPI_Init(SPI1, &SPI_InitStructure);

  /* Enable SPI1 */
  SPI_Cmd(SPI1, ENABLE);

    u16 request = 0x0F;//0x0F;//0x29;  // OutX register
    request |= 0x80;   // RW bit =1 for reading    
   // request |= 0x40;   // MS bit = 1 for address increment
   // request <<= 8;
    
    int i = 0;
    int j = 0;
    u16 buf[100]={0};

    GPIO_ResetBits(GPIOA, GPIO_Pin_4);

 //   SPI_I2S_SendData(SPI1, request);
 //   SPI_I2S_SendData(SPI1, 0);

    while(1)
        {
        //set low
        GPIO_ResetBits(GPIOA, GPIO_Pin_4);

        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
           SPI_I2S_SendData(SPI1, request);
           while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
        SPI_I2S_SendData(SPI1, 0);
        

            
            //set high
            GPIO_SetBits(GPIOA, GPIO_Pin_4);
            
            while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
            
            {
                buf[i++] = SPI_I2S_ReceiveData(SPI1);
                i%=100;                
            }

            j++;
        }


  while (1)
  {}
}

Offline

 

# 8   2009-02-24 07:48:55 connecting to the MEMS motion sensor over SPI

Francis
Administrator
From: France-Grenoble
Registered: 2007-07-09
Posts: 890

Re: connecting to the MEMS motion sensor over SPI

A few ideas:
1. Check the crystal  frequency (here 8MHz, 12Mz for Primers).
2. In the CircleOS code. I see:

Code:

    GPIO_InitStructure.GPIO_Pin   = GPIO_PIN_MEMS_SCK | GPIO_PIN_MEMS_MISO | GPIO_PIN_MEMS_MOSI;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;

In your code, MISO is configured as IN_FLOATING. It could be your problem.

3. Check the state of the CS pin (should be 0 I believe) to switch between I2C and SPI.

4. In CircleOS, I see:
    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_16;
    SPI_InitStructure.SPI_FirstBit            = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial       = 7;

I assume that CRC is not used, but I see some differences (CPHA)

Offline

 

# 9   2009-02-25 08:15:59 connecting to the MEMS motion sensor over SPI

Andrew
New member
Registered: 2009-02-20
Posts: 6

Re: connecting to the MEMS motion sensor over SPI

Hello Francis,
Thanks for the comment.
I have changed  clock polarity and clock phase.
I also experimented with CPU frequency
by changing mulitpliers in:
RCC_PLLConfig(RCC_PLLSource_HSE_Div2, RCC_PLLMul_2);
CPU frequency doesn't have any effect.

But changing the SPI baud prescaler
SPI_InitStructure.SPI_BaudRatePrescaler   = SPI_BaudRatePrescaler_16;
affects the shape of the output impulse from MEMS sensor.  But it can't help make SDO pulses square.

I also have experimented with vdd_IO. This line is intended to power the inpu/output lines. I am not sure if this line is needed at all because sensor is working over I2C without this line connected.


It seems that from software point of view I have tried all variants.

Offline

 

# 10   2009-02-25 08:51:34 connecting to the MEMS motion sensor over SPI

sjoerd
Member
From: Stad aan het Haringvliet
Registered: 2008-09-04
Posts: 65

Re: connecting to the MEMS motion sensor over SPI

Have you tried a 10K resistor on the SDO line?

Offline

 

# 11   2009-02-25 08:55:14 connecting to the MEMS motion sensor over SPI

Francis
Administrator
From: France-Grenoble
Registered: 2007-07-09
Posts: 890

Re: connecting to the MEMS motion sensor over SPI

It looks like a hardware issue... Did you try on two different boards?
I guess you checked the CS pin (to switch between I2C and SPI).
If you have a Primer (either Primer1 or Primer2), you can test your software running on the primer, then you could port it to your target board.

Offline

 

# 12   2009-02-26 01:12:04 connecting to the MEMS motion sensor over SPI

Andrew
New member
Registered: 2009-02-20
Posts: 6

Re: connecting to the MEMS motion sensor over SPI

Fantastic !!!
I have solved the problem by soldering 22K (I didn't have 10K) resistor between CS line and the ground, instead of setting Chip Select signal in software.
It might look simple but for me it is real break-through.
Dear sjoerd, Francis   thank you so much for your help!
It was really important to feel that you are not alone with your problems..
Thanks guys!

Offline

 

  • Index
  •  » circleOS
  •  » connecting to the MEMS motion sensor over SPI

Board footer