No hay respuesta de la tarjeta de ruptura IMU ST LSM6DS3 utilizando SPI

4

Estoy conectando un STM32F4 (descubrimiento) a una IMU LSM6DS3 (o, más bien, a la placa de arranque de sparkfun) a través de SPI y no obtengo una respuesta. Tengo un analizador lógico conectado a la IMU y veo esto:

Loúnicoquepudeveresunerrorenestaimagenesquelalíneadelrelojcomienzademasiadotardedespuésdeliniciodemisdatos.Peronotengoideadecómosolucionarlo.

Mifrecuenciaestápordebajodellímitede10MHzymiVddiotambiénestápordebajodelaespecificaciónmáxima.Tengodosfichasconlamismaconfiguración,porloqueelerroresprobablementeelmío.

Aquíestámicódigo.Deacuerdoconla hoja de datos 0xf es el indicador de who_am_I.

#include "imu_control.h"
#include <spi.h>

void init_SPI1();
uint8_t SPI1_send(uint8_t data);

void imu_task(void* pvParameters){
  uint8_t rec = 0;
  init_SPI1();
  while(1){     
    GPIOE->BSRRH |= GPIO_Pin_7; // set PE7 (CS) low
    SPI1_send(0x0f);  // transmit data
    rec = SPI1_send(0x00); // transmit dummy byte and receive data
    GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 (CS) high
    printf("%d\n", rec);
    vTaskDelay(1000);

  }
}

void init_SPI1(){

  GPIO_InitTypeDef GPIO_InitStruct;
  SPI_InitTypeDef SPI_InitStruct;

  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStruct);

  // connect SPI1 pins to SPI alternate function
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);


  // enable clock for used IO pins
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);

  /* Configure the chip select pin
     in this case we will use PE7 */
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(GPIOE, &GPIO_InitStruct);

  GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 high

  // enable peripheral clock
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

  /* configure SPI1 in Mode 0 
   * CPOL = 0 --> clock is low when idle
   * CPHA = 0 --> data is sampled at the first edge
   */
  SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines
  SPI_InitStruct.SPI_Mode = SPI_Mode_Master;     // transmit in master mode, NSS pin has to be always high
  SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; // one packet of data is 8 bits wide
  SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;        // clock is high when idle
  SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;      // data sampled at first edge
  SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set; // set the NSS management to internal and pull internal NSS high
  SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; // SPI frequency is APB2 frequency / 4
  SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first
  SPI_Init(SPI1, &SPI_InitStruct); 

  SPI_Cmd(SPI1, ENABLE); // enable SPI1
}

/* This funtion is used to transmit and receive data 
 * with SPI1
 *          data --> data to be transmitted
 *          returns received value
 */
uint8_t SPI1_send(uint8_t data){

    SPI1->DR = data; // write data to be transmitted to the SPI data register
    while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete
    while( !(SPI1->SR & SPI_I2S_FLAG_RXNE) ); // wait until receive complete
    while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore
    return SPI1->DR; // return received data from SPI data register
}
    
pregunta Brandon Solis

3 respuestas

2

[Dado que esto se confirmó como la solución de mi comentario, aquí está como respuesta:]

El SparkFun LSM6DS3 breakout permite utilizar la interfaz SPI o I2C del dispositivo. Sin embargo, la PCB de ruptura se suministra de forma predeterminada con un puente soldado en el lugar, etiquetado "ADDR", que selecciona la dirección I2C de una opción de dos. Sin embargo, ese puente soldado evita la comunicación SPI en la conexión MISO, y debe eliminarse si el módulo de ruptura se utiliza con la interfaz SPI.

Este requisito se menciona brevemente en la SparkFun LSM6DS3 Breakout Hookup Guide :

    
respondido por el SamGibson
1

Usted establece que el bit 0 es bajo = operación de escritura, durante la operación de escritura no se espera que el dispositivo de respuesta responda nada. Para obtener una respuesta de datos, configure el bit 0 a 1 para iniciar la operación de lectura.

    
respondido por el Anonymous
0

Sin haber comprobado su inicialización SPI: De acuerdo con la hoja de datos, los datos del LSM6DS3 se muestrean en el flanco ascendente y los cambios en el flanco descendente. Tanto CPOL como CPHA tienen que ser 1, para tener Reloj alto cuando están inactivos y datos de muestra en el borde ascendente (consulte aquí ).
Por lo tanto, si el Reloj está inactivo en Alta, y los datos deben muestrearse en el flanco ascendente, este flanco ascendente es, por supuesto, el borde segundo de la señal del reloj.
Debes verificar tu configuración de CPOL y CPHA.

EDITAR:
Otro punto: para leer un registro, el primer bit transmitido debe ser 1 (consulte el capítulo 6.2.1 lectura SPI). No está en tu captura de pantalla. Por favor, compruebe esto también.

    
respondido por el mic

Lea otras preguntas en las etiquetas