Warum sendet mein I2C-Gerät (VCNL4200) unabhängig vom Register nur Nullen, wenn ich daraus lese?

Immer wenn ich von meinem VCNL4200 über I2C lese, ist das 16-Bit-Wort, das ich zurückbekomme, immer 0x0000. Dies ist völlig unabhängig von dem Register, das ich lese, und passiert immer noch beim Lesen des Geräte-ID-Registers, das einen festen Wert ungleich Null hat. Dies ist bei beiden Sensorchips passiert, die ich ausprobiert habe.

Soweit ich sagen kann, liest das Gerät I2C-Befehle korrekt, da ich es sondiert und überprüft habe, dass das Gerät das tut, was meine Setup-Funktion ihm sagt. Es verhält sich auch korrekt mit ACK/NACK-Bits (für ACK während des Schreibens auf Low ziehen, SDA für das Mikro zum ACK während des Lesens floaten lassen).

Die Scope-Traces für SDA und SCL, wenn ich versuche, das Geräte-ID-Register zu lesen, sind unten.

Scope-Trace von SDA und SCL während des Lesevorgangs

Code, den ich zum Lesen/Einrichten des Sensors verwende:

//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
    }
}

Die Funktionen i2cWriteund i2cReadwurden auf anderen Geräten als funktionsfähig verifiziert. Ich verwende einen PIC16F1776 mit CCS C-Compiler.

Wo machst du dein I2C-Setup? Wie in der Taktrate? Ist es möglich, dass Sie eine zu schnelle Taktrate für diesen Chip verwenden?
Meine Taktfrequenz beträgt 100 kHz, die Einrichtung erfolgt über #use i2c(master, sda=PIN_B5, scl=PIN_B4, force_hw, fast=100000)(siehe CCS-Handbuch für Details). Der VCNL4200 kann mit 100 kHz betrieben werden

Antworten (2)

Es sieht so aus, als ob der VCNL4200 einen Wiederholungsstart zwischen den beiden I2C-Befehlen erwartet , und Sie haben zwei separate Befehle mit einem Stopp dazwischen.

Aus dem Datenblatt ist es nicht sehr offensichtlich, aber dieser Arduino-Treiber sendet die Stoppnachricht nicht auf WireEndTransmisson .

Ich vermute, das ist das Äquivalent zum i2cWrite(VCNL4200_I2C_ADDRESS, psDataRegister, 1, 1);Werden i2cWrite(VCNL4200_I2C_ADDRESS, psDataRegister, 1, 0);in Ihrem Code.

Danke! Das war das Problem, ich habe es aufgehängt und es funktioniert jetzt perfekt

i2c

Auf der digitalen Schnittstelle können Sie beim Lesen von Daten sehen, dass Sie zwischen den Befehlen keine Stoppnachricht senden können. Ich habe den gleichen Fehler gemacht, genau wie Sie, weil andere i2c-Geräte die Stoppnachricht senden