¿Cómo se establece la frecuencia de reloj entre el maestro y el esclavo en el protocolo I2C?

7

Esta es una pregunta de seguimiento para ¿Qué sucede si omito las resistencias pullup en las líneas I2C?

En un reloj de pared digital que diseñé (usando el DS1307 RTC y el ATmega328 MCU), accidentalmente omití las resistencias de pull-up que deben estar conectadas a ambas líneas I2C. Al final tuve la suerte de que los pull-ups internos en las líneas ATmega I2C fueron suficientes para (apenas) permitir la comunicación entre los dispositivos. El resultado fueron largos tiempos de subida en las líneas I2C y reducción de velocidad a 32kHz como se ve en las tomas de alcance a continuación.

Editar: En realidad, la frecuencia es exactamente de 100 kHz, hay 2 picos por cada 20us en la línea verde. Inicialmente pensé que había una reducción a 32 kHz porque mi alcance calculó la frecuencia en la traza amarilla.

Lo que me desconcierta ahora es que los dispositivos decidieron que 32 kHz era suficiente para que se produjera la comunicación. El La hoja de datos de DS1307 dice que el dispositivo admite una frecuencia de 100 kHz en el bus I2C. ¿Cómo es que terminó usando 32kHz? ¿Hay algún tipo de fase de apretón de manos en la que se establezca la frecuencia?

Al final, mi pregunta realmente es esta: ¿Cómo se establece la frecuencia de reloj entre maestro y esclavo en el protocolo I2C?

No pude encontrar esa información buscando en la Red.

En caso de que esto importe, estoy usando Arduino IDE 1.03 y mi firmware maneja el RTC usando el DS1307RTC Arduino lib (a través de sus funciones RTC.read() y RTC.write() ). Esa lib a su vez usa Wire.h para hablar con el RTC.

    
pregunta Ricardo

3 respuestas

4

Siguiendo los comentarios:

Sí, la frecuencia está codificada en algunos registros específicos relacionados con I2C. En tiempo de ejecución.

Dicho esto, su biblioteca Arduino podría realizar algunas mediciones de tiempo de levantamiento y sondeo en el bus para determinar una velocidad de reloj viable. A ver.

Después de hacer un poco de búsqueda de fuentes, la respuesta está en twi.h

#ifndef TWI_FREQ
#define TWI_FREQ 100000L
#endif

Otra pieza de ese mismo archivo:

TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2;

Donde TWBR significa Two Wire Baudrate Register , sospecho.

Llamaría a eso evidencia suficiente y definitivamente diría, sí, tu frecuencia de I2C la establece directamente tu biblioteca sin ninguna negociación. Si desea cambiarlo, le sugiero que # defina TWI_FREQ antes de incluir # twi.h (o indirectamente a través de Wire.h)

    
respondido por el Dzarda
5

Para que se produzca un flanco ascendente del reloj en I2C, el maestro debe hacer valer el reloj, lo que puede hacer que algunos esclavos se unan para afirmarlo también, y luego el maestro y todos los esclavos deben coincidir en liberar el reloj. Hasta que todos los dispositivos liberen el reloj, permanecerá activado y todos los dispositivos verán que está activado.

Una vez que todos los dispositivos hayan soltado el reloj, cada dispositivo esclavo "volverá a armar" el circuito de retención del reloj a menos que esté listo para el siguiente flanco ascendente [algunos dispositivos siempre están "preparados" para los flancos ascendentes como tan rápido como el maestro puede enviarlos, y por lo tanto no necesita un circuito de retención de reloj; otras veces, es posible que otros sepan que no estarán interesados en los flancos ascendentes hasta que aparezca la siguiente condición de inicio, y no volver a armar su circuito de retención de reloj hasta entonces]. Cuando el maestro ve que se libera el reloj, espera un tiempo mínimo para asegurarse de que cualquier persona que necesite volver a armar un circuito de retención de bus tenga la oportunidad de hacerlo, y luego volver a hacer valer el reloj y asegurarse de que está sostenido el tiempo suficiente para permitir que cualquier circuito armado de autobuses se unan para sujetarlo. El ciclo se puede repetir.

Los dispositivos esclavos generalmente no tienen una velocidad de operación mínima, pero tendrán un máximo. Algunos dispositivos sincronizan toda su lógica I2C con un reloj interno y, por lo tanto, pueden requerir uno o dos ciclos para activar o activar su circuito de retención de reloj. Además, I2C requiere que los dispositivos deben determinar al 100% de manera confiable si los bordes en el cable del reloj suceden antes o después de los bordes en el cable de datos; ya que los cambios en la línea de datos a menudo ocurren casi inmediatamente después de la caída de los bordes del reloj, los dispositivos pueden agregar algo de retraso cuando perciben cambios en la línea de datos. Esto requiere agregar un retraso entre cualquier momento en que el maestro cambie su salida de datos y la hora en que levante su reloj. Siempre que todos los dispositivos cumplan con el requisito de retraso mínimo, el maestro puede demorar todo el tiempo que quiera; sin embargo, cuanto más se demore el maestro, más tardará en enviar los datos.

    
respondido por el supercat
3

De la sitio web de Arduino - Referencia detallada de la biblioteca electrónica :

  

La llamada twi.init () es interna a la biblioteca de Wire. Realiza las siguientes tareas: establece la frecuencia de reloj que usará el hardware TWI si / cuando es el maestro en el bus I2C. Se establece en el código fuente a 100 kHz, pero en teoría al menos puede restablecer esta frecuencia al redefinir TWBR antes de llamar a Wire.begin (), por ejemplo: TWBR = 400000L debería configurarlo a 400kHz.

La biblioteca RTC que utiliza no cambia TWBR. Algo más que estás usando podría haberlo cambiado. O el largo y lento tiempo de pull-up de los súper débiles internos ha hecho que el motor i2c de ATMega se ralentice. El motor comprueba si la línea es alta o baja antes de cambiarla.

Dicho esto, la frecuencia del reloj i2c es arbitraria , hasta la frecuencia máxima admitida más baja de cualquier dispositivo en el bus (y quizás unas decenas de Hz más). Más rápido y empiezas a tener problemas de lectura y escritura. Algunos dispositivos tienen frecuencias mínimas antes de que se agote el tiempo de espera, pero he visto que los dispositivos de 400 kHz funcionan a 10 kHz. La velocidad del reloj es decidida únicamente por el maestro (es decir, usted, el codificador).

Hay una opción para alargar el reloj en la parte del esclavo (mantiene la línea del reloj baja hasta que esté lista, y la especificación i2c requiere que el maestro verifique esto), pero las imágenes de alcance no parecen indicar que esto está sucediendo aquí.

Si tuviera que agregar algunos pullups externos adecuados, sin cambiar ningún código, debería ver el aumento de frecuencia más cercano a 100kHz como la biblioteca de Wire define como estándar

    
respondido por el Passerby

Lea otras preguntas en las etiquetas