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
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.