El esclavo I2C no reconoce

3

Por lo tanto, la configuración que estoy usando es un K22FN512 (Arm Cortex M4) junto con un AGM01 (tarjeta de sensores 9DOF, gyro / accel / mag). La placa que contiene los sensores tiene una interfaz I2C para comunicarse con los dos chips montados en ella. Tengo el panel de arranque Vdd y Vdio conectados al pin de 3.3v del K22. La dirección del esclavo y los pines de restablecimiento de la placa del sensor están conectados al K22 a través de GPIO.

Ahora parece que no puedo lograr que el esclavo reconozca nada en absoluto. Hasta ahora he hecho lo siguiente:

  • Vdd y Vdio medidos, ambos bien
  • Tensiones bajas / altas SCL y SDA medidas, ambas finas
  • Se desaceleró el reloj de 90kHz a ~ 1.5kHz
  • Cambió la dirección del esclavo de 0x20 a 0x21, aún sin confirmar
  • Se movieron las sondas lógicas a los puntos de prueba soldados en la placa de ruptura del sensor, la señal aún es fuerte, no hay signos de problemas de cable / capacitancia

Estoy en una pérdida en qué intentar siguiente. A continuación se encuentra mi código, la salida del analizador lógico y los enlaces a la documentación del hardware. El código no está completo, tengo la intención de manejar también lecturas de múltiples bytes y otras cosas, pero en este momento ni siquiera puedo leer el registro de identificación del dispositivo.

Manualdereferenciapara K22 :

No puedo publicar más de dos enlaces ya que tengo menos de 10 representantes (al parecer, la imagen cuenta)

El giroscopio es el FXAS21002C

Breakout board es el BRKT-STBC-AGM01-QRC

Código:

    /*
    Sensor module header
    */
    #ifndef SENSORS_H
    #define SENSORS_H

    #include <cmsis_os.h>                       // CMSIS RTOS header file
    #include "MK22F51212.h"                     // CMSIS  Peripheral Access Layer for MK22F51212

    // I2C defs
    #define I2C_READ_BIT        0x01
    #define I2C_WRITE_BIT       0x00
    #define I2C_READ_BUFF         6u
    #define I2C_READ(add)       ((uint8_t)((((uint8_t)add) << 1) | I2C_READ_BIT));
    #define I2C_WRITE(add)      ((uint8_t)((((uint8_t)add) << 1) | I2C_WRITE_BIT));

     // Gyro address defs
     #define GYRO_ADD                   0x20
     #define GYRO_STATUS                0x00
     #define GYRO_X_MSB                 0x01
     #define GYRO_X_LSB                 0x02
     #define GYRO_Y_MSB                 0x03
     #define GYRO_Y_LSB                 0x04
     #define GYRO_Z_MSB                 0x05
     #define GYRO_Z_LSB                 0x06
     #define GYRO_DR_STATUS             0x07
     #define GYRO_F_STATUS              0x08
     #define GYRO_F_SETUP               0x09
     #define GYRO_F_EVENT               0x0A
     #define GYRO_INT_SRC_FLAG          0x0B
     #define GYRO_WHO_AM_I              0x0C
     #define GYRO_CTRL_REG0             0x0D
     #define GYRO_RT_CFG                0x0E
     #define GYRO_RT_SRC                0x0F
     #define GYRO_RT_THS                0x10
     #define GYRO_RT_COUNT              0x11
     #define GYRO_TEMP                  0x12
     #define GYRO_CTRL_REG1             0x13
     #define GYRO_CTRL_REG2             0x14
     #define GYRO_CTRL_REG3             0x15

     // RTX core 
     int Init_Thread_Sensors (void);
     void Thread_Sensors (void const *argument);

     // Sensor struct for sensors state
    typedef struct {
        int16_t gyro_x;
        int16_t gyro_y;
        int16_t gyro_z;
        int16_t accel_x;
        int16_t accel_y;
        int16_t accel_z;
        int16_t mag_x;
        int16_t mag_y;
        int16_t mag_z;
    }sensor;

    // Struct for I2C data
    typedef struct {
        uint8_t device;
        uint8_t reg;    
        uint8_t bytes;
        uint8_t data[I2C_READ_BUFF];
    }i2c_transfer;

    // Sensor model and mutex
    extern sensor sensorData;
    extern osMutexId sensor_mutex;

    // Functions
    void init_I2C(void);
    void init_IMU(void);
    void read_I2C(i2c_transfer*);
    void write_I2C(i2c_transfer*);

    #endif

.

    /*----------------------------------------------------------------------------
    *      Sensor thread, I2C0 used
    *---------------------------------------------------------------------------*/
    #include "Sensors.h"

    // RTX info
    osThreadId tid_Thread_Sensors;                          // thread id
    osThreadDef (Thread_Sensors, osPriorityNormal, 1, 0);   // thread object

    void init_I2C(void){

        // Enable module clock
        SIM_SCGC4 |= SIM_SCGC4_I2C0_MASK;   

        // Config pin mux for I2C bus
        SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;
        PORTB_PCR0 = PORT_PCR_MUX(0x02) | PORT_PCR_ODE_MASK | PORT_PCR_PE_MASK |PORT_PCR_PS_MASK;       // SCL
        PORTB_PCR1 = PORT_PCR_MUX(0x02) | PORT_PCR_ODE_MASK | PORT_PCR_PE_MASK |PORT_PCR_PS_MASK;       // SDA

        // Config gpio
        SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK;
        PORTC_PCR5 = PORT_PCR_MUX(0x01) | PORT_PCR_ODE_MASK;    // RST
        PORTC_PCR6 = PORT_PCR_MUX(0x01) | PORT_PCR_ODE_MASK;    // SA   

        GPIOC_PDDR |= (1<<5) | (1<<6);
        GPIOC_PSOR |= 1<<5; 
        GPIOC_PCOR |= 1<<6;

        // Config I2C0  
        I2C0_F = I2C_F_MULT(0x02) | I2C_F_ICR(0x3F);    
        I2C0_C1 = I2C_C1_IICEN_MASK;    
    }

    void init_IMU(void){

    }

    int Init_Thread_Sensors (void) {

        init_I2C();

        tid_Thread_Sensors = osThreadCreate (osThread(Thread_Sensors),       NULL);
        if(!tid_Thread_Sensors) return(-1);

        return(0);
    }

    void Thread_Sensors (void const *argument) {
        i2c_transfer packet;
        while (1) {
            packet.device = GYRO_ADD;
            packet.reg = GYRO_WHO_AM_I;     
            read_I2C(&packet);

            osThreadYield();                                            // suspend thread
        }
    } 

    void read_I2C(i2c_transfer* data){

        // Wait for bus ready
        while(I2C0_S & I2C_S_BUSY_MASK);

        // Trigger Start signal
        I2C0_C1 |= I2C_C1_TX_MASK | I2C_C1_MST_MASK;        

        // Send Write command
        I2C0_D = I2C_WRITE(data->device);

        // Wait for ACK     
        //while((I2C0_S & I2C_S_RXAK_MASK)==1){}; 
        while((I2C0_S & I2C_S_IICIF_MASK)==0){};   
        I2C0_S |= I2C_S_IICIF_MASK;

        // Write reg address
        I2C0_D = data->reg;

        // Wait for ACK
        //while((I2C0_S & I2C_S_RXAK_MASK)==1){};  
        while((I2C0_S & I2C_S_IICIF_MASK)==0){};   
        I2C0_S |= I2C_S_IICIF_MASK;

        // Repeat start to engage read
        I2C0_C1 |= I2C_C1_RSTA_MASK;    

        // Send Read device command
        I2C0_D = I2C_READ(data->device);

        // Wait for ACK     
        //while((I2C0_S & I2C_S_RXAK_MASK)==1){};  
        while((I2C0_S & I2C_S_IICIF_MASK)==0){};   
        I2C0_S |= I2C_S_IICIF_MASK;  

        // Switch to RX mode
        I2C0_C1 &= ~I2C_C1_TX_MASK;
        I2C0_C1 |= I2C_C1_TXAK_MASK;    

        // Trigger Read and wait for Data
        data->data[0] = I2C0_D;
        //while((I2C0_S & I2C_S_TCF_MASK)==0){};     
        while((I2C0_S & I2C_S_IICIF_MASK)==0){};   
        I2C0_S |= I2C_S_IICIF_MASK;  

        // Store Sata
        data->data[0] = I2C0_D;

        // Trigger Stop
        I2C0_C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK); 
    }

    void write_I2C(i2c_transfer* data){

    }

Solución encontrada

Resulta que necesito leer el documento más de cerca, el dispositivo se reinició y no puse SPI_CS_B alto como se suponía.

    
pregunta Dave851

2 respuestas

2

Cosas para verificar:

1) Verifique el pin 8 en el giro (I2C_B / SPI). Este pin selecciona entre los modos I2C y SPI. Necesitas que esté configurado para el modo I2C. Probablemente hay un puente para controlar esto. Desea que sea BAJO para el modo I2C.

2) Compruebe el pin 17 en el giro (SPI_CS_B). La hoja de datos dice que este pin debe estar atado alto si está utilizando el modo I2C.

3) Vuelva a comprobar el poder en la placa giroscópica. Asegúrate de que sea 3.3.

4) Si hay alguna forma de verificar de forma independiente el tablero de giroscopios de alguna manera, solo para ganar confianza de que es funcional, sería bueno hacerlo.

5) capture SCL y SDA con un osciloscopio en lugar de un analizador lógico para buscar problemas de integridad de la señal. Tal vez el giroscopio está tratando de bajar los datos durante un ack bajo, pero ¿algo más lo está tirando a lo alto?

¡Buena suerte!

    
respondido por el mkeith
0

¿Ha revisado los puentes en el tablero de ruptura? El tarjeta de referencia rápida muestra lo que parecen puentes para seleccionar la línea SDA / SCL y controlar las señales de reinicio. Intente verificar las señales de reinicio para cada sensor y asegúrese de que no se mantengan en reinicio.

    
respondido por el Adam Haun

Lea otras preguntas en las etiquetas