La lectura de I2C de múltiples bytes no funciona mientras que el Arduino "equivalente" funciona

3

Entiendo que la gente probablemente ha preguntado esto antes, pero he mirado durante horas y no puedo encontrar lo que estoy haciendo mal.

Estoy intentando que se produzca una transferencia de múltiples bytes entre un dispositivo i2c, el DS3231 y mi microcontrolador, un AT89S51 (8051).

Puedo sacar toda la información usando múltiples métodos de escritura / solicitud, pero me gustaría aprender a hacer lecturas / escrituras de múltiples bytes para simplificar mi código y entender mejor cómo funciona i2c.

Intenté dibujar en la imagen lo que hace cada parte de la señal pero, como resultado, un ratón no es lo mejor para esto.

La primera imagen es la forma de onda equivalente de Arduino y la segunda es mi implementación.

SicomparaslasformasdeondadelArduinoydemi8051,sonbastantesimilares,exceptoporelhechodequeelArduinodevuelvelos7bytescompletosdedatos,mientrasquelosmíossolodevuelven1.

Enestepunto,loúnicoquecreoquepodríaestarmalesquetalvezmi8051micronotiradelalíneaSDAlosuficientecuandonecesitaenviarlaseñalACKy,porlotanto,eldispositivoi2cnolaregistra..Siesteeselcaso,¿hayalgunasolución?

Graciasportutiempo.

edite: Eliminé la imagen antigua y la reemplacé con una con un ciclo de trabajo mejor.

    
pregunta Noixo

1 respuesta

1

Mi conjetura sería que de alguna manera no se genera correctamente el bit ACK (SDA bajo) después de cada byte. Como eres el maestro, puedes controlar el tiempo. Estudie esta función que se usa para obtener múltiples bytes del bus i2c. Son las tres líneas después del bucle for las que necesita corregir.

int I2cGetOctetAndAck(){
    register int result = 0;
    register int i;
    I2C_RELEASE_SDA(); //SDA to Z state, pull-up via resistor
    for (i=0; i<8; i++){ //clock in 8 bits
        I2C_CLOCK_HIGH();
        result <<= 1;
        result |= SDA_PIN;
        I2C_CLOCK_LOW();
    }
    I2C_DRIVE_SDA(); // SDA from Z state to LOW state for generating ACK
    I2C_CLOCK_HIGH(); // SCL HIGH, macro includes delay
    I2C_CLOCK_LOW(); // SCL LOW, macro includes delay
    return result;
}
    
respondido por el PkP

Lea otras preguntas en las etiquetas