¿Por qué mi dispositivo I2C (VCNL4200) envía ceros cuando lo leo, independientemente del registro?

Cada vez que leo de mi VCNL4200 a través de I2C, la palabra de 16 bits que obtengo es siempre 0x0000. Esto es completamente independiente del registro que estoy leyendo, y aún sucede al leer el registro de ID del dispositivo que tiene un valor fijo distinto de cero. Esto sucedió en los dos chips sensores que probé.

Lo mejor que puedo decir es que el dispositivo lee los comandos I2C correctamente, ya que lo probé y verifiqué que el dispositivo está haciendo lo que mi función de configuración le indica que haga. También se comporta correctamente con los bits ACK/NACK (bajando para ACK durante la escritura, dejando que SDA flote para el micro a ACK durante la lectura).

Los rastros de alcance para SDA y SCL cuando intento leer el registro de ID del dispositivo se encuentran a continuación.

Rastreo de alcance de SDA y SCL durante la operación de lectura

Código que uso para leer/configurar el sensor:

//count is number of bits, stop is whether or not there is a stop condition at the end
int i2cWrite(int8 address, int8 *data, int8 count, int1 stop);
int i2cRead(int8 address, int8 *data, int8 count);

int16 VCNL4200_Read(void) {
    int8 data[2] = {0};
    int8 psDataRegister[1] = {0x0E}; //0x08 is the address of the data, 0x0E for device ID
    i2cWrite(VCNL4200_I2C_ADDRESS, psDataRegister, 1, 1);
    i2cRead(VCNL4200_I2C_ADDRESS, data, 2);
    return make16(data[1], data[0]);
}

void VCNL4200_Setup(void) {
    int8 configWords[5][2]  = {
        {0xF0, 0x00},   //PS_CONF1 , PS_CONF2
        {0x00, 0x20},   //PS_CONF3 , PS_MS
        {0x00, 0x00},   //PS_CANC_L, PS_CANC_H
        {0x00, 0x00},   //PS_THDL_L, PS_THDL_H
        {0x01, 0x00}    //PS_THDH_L, PS_THDH_H
    };
    int8 configWordCurrent[3];

    for(int8 i = 0; i < 5; i++){
        configWordCurrent[0] = i+3;                             //1st byte, register address. Sequential from 0x03 to 0x07
        configWordCurrent[1] = configWords[i][0];               //2nd byte, lower byte of config word
        configWordCurrent[2] = configWords[i][1];               //3rd byte, upper byte of config word
        i2cWrite(VCNL4200_I2C_ADDRESS, configWordCurrent, 3, 1);//Send over I2C
    }
}

Se ha verificado que las funciones i2cWritey i2cReadfuncionan en otros dispositivos. Estoy usando un compilador PIC16F1776 con CCS C.

¿Dónde haces tu configuración I2C? Como en la velocidad del reloj? ¿Es posible que esté utilizando una velocidad de reloj demasiado rápida para ese chip?
Mi velocidad de reloj es de 100 kHz, su configuración se usa #use i2c(master, sda=PIN_B5, scl=PIN_B4, force_hw, fast=100000)(consulte el manual de CCS para obtener más detalles). El VCNL4200 puede funcionar a 100 kHz

Respuestas (2)

Parece que el VCNL4200 espera un inicio repetido entre los dos comandos I2C, y tiene dos comandos separados con una parada entre ellos.

No es muy obvio en la hoja de datos, pero este controlador arduino no envía el mensaje de detención en WireEndTransmisson .

Sospecho que es el equivalente a i2cWrite(VCNL4200_I2C_ADDRESS, psDataRegister, 1, 1);convertirse i2cWrite(VCNL4200_I2C_ADDRESS, psDataRegister, 1, 0);en tu código.

¡Gracias! Este era el problema, lo he colgado y ahora funciona perfectamente.

i2c

En la interfaz digital puede ver, cuando está leyendo datos, que no puede enviar un mensaje de parada entre comandos. Cometí el mismo error, al igual que tú, porque otros dispositivos i2c envían el mensaje de detención