I2C bit banging

3

Tengo que implementar I2C usando bit banging ya que el controlador no es compatible con los controladores I2C. Por lo tanto, para generar el reloj SCL, debe haber demoras para generar los períodos de alta y baja del reloj. ¿Cuál es el mejor método para generar el retraso, A) usando nops / para bucles, o B) los retrasos generados usando un temporizador de propósito general?

    
pregunta xyz101

5 respuestas

5

Realmente depende de si necesitas hacer otra cosa al mismo tiempo, y también la velocidad de tu procesador. Si puede bloquear completamente su aplicación (bucle principal) mientras se ejecuta I²C, usar los retrasos de software es mucho más fácil. Pero con un procesador rápido, estás desperdiciando cientos de instrucciones que podrían usarse para otra cosa.

Sin embargo, si necesita manejar otras E / S y / o hacer cálculos en el bucle principal al mismo tiempo, entonces las interrupciones serían el camino a seguir. Pero puede ser capaz de ejecutar suficientes instrucciones entre bits para que valga la pena, ya que las interrupciones, por su naturaleza, agregan una sobrecarga adicional. Con cualquiera de los dos enfoques, necesitarías implementar algún tipo de máquina de estado para hacer un seguimiento de qué hacer a continuación.

Una interfaz I²C normalmente se ejecuta a 100 kHz o 400 kHz. Entonces, esto significaría una interrupción cada 10 µs o 2.5 µs, respectivamente. Para un procesador razonablemente rápido, digamos un PIC32 que se ejecuta a 80 MHz, esto representa 800 ó 200 instrucciones de un ciclo entre bits, por lo que no hay problema.

Pero para un procesador que funciona a 8 MHz e I²C a 400 kHz, solo hay 20 instrucciones por bit, por lo que no es posible utilizar interrupciones, ya que tiene que reparar la interrupción (guardar registros y confirmar el indicador de interrupción), genere el pulso de reloj (SCL), obtenga el bit de datos que se enviará y envíelo (SDA) 1/2 bit después del borde del reloj, actualice un contador de bits y quizás el estado, restaure los registros y devuelva. Probablemente no sucederá en 20 instrucciones, incluso en lenguaje ensamblador.

El motivo de la temporización de 1/2 bit, es que está generando los pulsos de reloj (SCL) y de datos (SDA). El reloj cae en el medio del bit de datos, por lo que el esclavo puede usar el borde para registrar los datos en su registro (ver más abajo).

Por lo tanto, con procesadores más lentos, probablemente necesitará utilizar retrasos de software. Podría crear una función (o macro) para retrasar el tiempo de 1/2 bit para generar los pulsos SCL y SDA, pero eso no permite la sobrecarga de obtener el siguiente bit y actualizar el contador de bits. Agregar esa sobrecarga significaría que su bus correría un poco más lento que 400 kHz (pero debería funcionar bien). Al incluir la sobrecarga en su cálculo de tiempo (por lo tanto, demorar solo un tiempo de menos de 1/2 bit para hacer que el tiempo general salga bien), podrá correr a toda velocidad. Esto requerirá un conteo cuidadoso de los ciclos de la máquina para maximizar la velocidad.

    
respondido por el tcrosley
1

Aquí hay un punto de vista más para que usted considere. Primero debe considerar qué problema necesita resolver: es que la conectividad I2C genérica o simplemente se conecta a uno o dos chips específicos.

Si necesita crear un host I2C genérico que pueda comunicarse con cualquier chip I2C, debe implementar los retrasos correctamente, incluido el alargamiento del reloj. Pero si solo necesita comunicarse con un IC específico, revise la hoja de datos de ese IC para conocer los requisitos de tiempo y haga algunas pruebas también. Probablemente no haya circuitos dentro de un IC específicamente diseñado para requerir algún tiempo determinado, los requisitos de tiempo del bus provienen de la necesidad de satisfacer las condiciones para corrientes de pull-up, capacitancias, longitudes del cableado, máxima ventilación. Out, esto y aquello. El chip en sí mismo probablemente solo requiera SDA, SCL bordes y niveles reconocibles y puede funcionar en los límites del proceso, lo que significa megaherts (a menos que ese chip también esté usando software para muestrear las líneas y emular I2C).

Si su bus I2C solo se ejecuta en su PCB entre solo un par de chips, haga lo mismo con las resistencias pull-up. Sus requisitos eléctricos para el bus pueden ser considerablemente más fáciles que los requisitos para un bus I2C genérico. Por ejemplo, lo más probable es que pueda utilizar la conducción normal push-pull de los pines SDA y SCL cuando conduce el autobús en lugar de confiar en la resistencia de pull-up y tal vez incluso sobrescribir los ACK.

Tenga en cuenta que si está utilizando pines del microcontrolador para implementar I2C, es muy difícil hacerlo de acuerdo con la especificación de todos modos , porque la especificación I2C requiere que los pines son colectores abiertos, no debe haber ninguna fuga en el lado superior, para permitir que cualquier chip en el bus se encienda o se apague de forma independiente. Ningún pin genérico de microcontrolador puede satisfacer esto , ya que invariablemente tienen estructuras de protección lateral altas. Nuevamente, esto no es un problema si tiene el control total del bus para que sea el único maestro y así pueda controlar la alimentación de las líneas de bus, por ejemplo. puede tirar alto al voltaje de alimentación digital de su microcontrolador. Pero es un problema si está diseñando un IC esclavo que debe apagarse mientras el resto del sistema está encendido. Si necesita respetar este aspecto del bus I2C, necesita circuitos externos.

Entonces, en resumen, mi punto de vista es que probablemente no debería resolver un problema mayor que el que necesita resolver; es muy posible que se salga con la suya con el chip específico que necesita para admitir. . Pero haga eso tan bien como pueda, con márgenes de error suficientes. Y si no es demasiado costoso, tenga en cuenta también algunos aspectos de la capacidad de ampliación, la capacidad de actualización y la reutilización del diseño.

Vea también: Aislamiento I2C usando el interruptor

    
respondido por el PkP
0

Totalmente dependiente de tu circuito. Tenga en cuenta que los dispositivos I2C tienden a tener una velocidad máxima y un tiempo mínimo entre los pulsos del reloj, pero tienden a ser completamente liberales a velocidades más bajas . Usted puede golpear I2C a velocidades muy bajas si lo desea o lo necesita. He usado expansores de puertos generales a velocidades de hasta 25 kHz y los IC no tendrían un solo problema con él.

Sus retrasos entre los tiempos de SCL alto y bajo solo deben ser lo suficientemente lentos para cumplir con el tiempo mínimo, lo que se puede hacer con algunos NOP.

    
respondido por el Passerby
0

Expresaré una opinión diferente a las respuestas anteriores.

generar retrasos usando "ciclos de temporización" (con NOP y bucles FOR o DO) es simple y confiable, pero no reingresante . es decir, es lo que puede hacer si no tiene otras tareas que molesten al microcontrolador en el momento de la comunicación I²C. por lo que no se puede utilizar en un contexto de subprocesos múltiples activo.

Si su I²C de bit bit se está realizando cuando también se deben atender otras tareas, entonces debe usar el temporizador y escribir el código de reingreso para hacer esto. debe recorrer cada uno de los hilos de cada tarea de una manera rápida y eficiente. cada subproceso debe comprobar rápidamente si su tarea necesita atención o no, y salir rápido si no.

y si la tarea de algún hilo necesita necesita atención, debes prestarle la atención que necesita y salir rápido. Si la atención que necesita cualquier tarea en particular no es una acción rápida, entonces ese hilo debe ser golpeado en prioridad de manera que el bit² banger I²C no se estropee.

además, debido a que no está seguro de la cantidad de MIPS o el tiempo que utilizan los otros subprocesos, debe reducir la velocidad de reloj de la línea I²C SCL para que el jitter que pueda resultar de las acciones de los otros subprocesos sea pequeño en comparación con el período de reloj.

estoy trabajando en una aplicación ADI SHArC (que sí tiene un I²C o "TWI" incorporado pero no lo estoy usando) y convertí el intercambio de bits de reingresantes con un simple no -incremento de bit entrante utilizando bucles de temporización. redujo en gran medida el tamaño del código y, dado que las comunicaciones I²C se realizaban únicamente para inicializar los registros de control de los chips periféricos al reiniciarse, no había interrupciones activas ni subprocesos de la competencia. así que el código de reingreso simplemente no era necesario.

    
respondido por el robert bristow-johnson
-3

La espera ocupada (NOP) suele ser la peor opción pero la más fácil de implementar.

    
respondido por el Tom L.

Lea otras preguntas en las etiquetas