¿Cómo implementar una señal de sincronización con AVR (attiny45)?

2

En pseudocódigo quiero hacer lo siguiente:

i = 0
state = 0

while (1):

  compareState = readDigitalIn()
  if state == compareState:
    i = i+1
  else:
    i = 0
    state = compareState

  writeDigitalOut(dataVector[i])

En inglés, quiero restablecer el contador i cada vez que cambio el estado de digitalIn -pin.

¿Lo anterior es una buena manera de hacer esto? ¿Attiny tiene oyentes de eventos o similares?

El objetivo final es sincronizar varios controladores pwm en diferentes chips (writeDigitalOut se cambia a AdjustPwmFrequency ...)

Editar: ¿Puedo usar interrupciones para esto? ¿Cómo? ¿Se puede crear una interrupción que se activa cuando se cambia el pin digitalIn?

    
pregunta Juha

1 respuesta

2

Sí, esta es una aplicación bastante buena para usar interrupciones.

Lo que le interesa es la interrupción externa, pero primero analicemos la estructura general de una interrupción.

Si ha habilitado una interrupción particular en su sistema, cuando ocurra ese tipo de interrupción, el procesador buscará en una tabla para encontrar la función o rutina de servicio para saltar a fin de atender esa evento particular.

Esta función se llama una rutina de servicio de interrupción, o ISR para abreviar. Este es un método que debes escribir.

Identifiquemos qué interrupción quieres y qué ISR quieres escribir. Para ello, necesitamos consultar la ficha técnica. El tipo de interrupción en el que está interesado está en la familia de interrupciones llamadas interrupciones externas . Un extracto de la hoja de datos de ATiny45 :

  

9.2 Interrupciones externas

     

Las interrupciones externas son activadas por el pin INT0 o cualquiera de los pines PCINT [5: 0]. Observar   eso, si está habilitado, las interrupciones se dispararán incluso si los pines INT0 o PCINT [5: 0] están configurados como   salidas Esta característica proporciona una forma de generar una interrupción de software. Pin cambia las interrupciones   PCI se activará si se activa cualquier pin PCINT [5: 0] habilitado. El registro PCMSK controla qué pines   Contribuir a las interrupciones de cambio de pin. Las interrupciones de cambio de pin en PCINT [5: 0] se detectan de forma asíncrona. Esto implica que estas interrupciones se pueden usar para despertar la parte también del sueño   modos distintos del modo inactivo.

     

Las interrupciones INT0 pueden ser activadas por un flanco descendente o ascendente o por un nivel bajo. Esto se configura como   indicado en la especificación para el registro de control de MCU - MCUCR. Cuando la interrupción INT0 es   habilitado y se configura como nivel disparado, la interrupción se disparará mientras se mantenga apretado el pin   bajo. Tenga en cuenta que el reconocimiento de interrupciones de flanco descendente o ascendente en INT0 requiere la presencia de un   Reloj de E / S, descrito en "Sistemas de reloj y su distribución" en la página 23.

Así que han mencionado algunos registros de interés aquí: PCMSK y MCUCR

PCMSK controla qué los pines pueden activar la interrupción, por lo que desea conectar su señal de conmutación a cualquiera de los pines que especifique aquí, y MCUCR define cómo los pines deben cambiar para activar la interrupción. En este caso, probablemente estaría interesado en configurar su interrupción para Any logical change on INT0 generates an interrupt request. como se describe en la tabla 9-2 en el documento. Continúe leyendo lo que hacen los registros en la sección de interrupción externa, son los siguientes: MCUCR , GIMSK , GIFR , PCMSK . La información que desea obtener de esto es

  1. Cómo configurar la interrupción ( PCMSK y MCUCR )
  2. Cómo habilitar o deshabilitar la interrupción ( GIMSK )
  3. Cómo verificar su estado actual ( GIFR )

Ahora en la codificación real. La estructura tendrá un aspecto similar a este (pseudo código):

volatile int i; // volatile because this gets changed in the ISR, so the compiler will know to NOT optimize this when used in loops

int main(void)
{
     /* set-up your registers here ... */
     /* enable global interrupts */

     i = 0;
     while (1) {
          boundsSafeVectorPrinter(i);
          i++;
     }
}

ISR(PCINT0_ISR)
{
     i = 0;
}

Ahora, siempre que se produzca un cambio de pin en uno de los pines que especificó (dado que ha configurado todos los registros correctamente), se ejecutará la rutina ISR(PCINT0_ISR) .

Entonces, ¿cómo supe usar ISR(PCINT0_ISR) ? Deberá buscar en el archivo de definiciones que esté utilizando para ver si le han proporcionado la asignación PCINT0_ISR . Si no, consulte la hoja de datos nuevamente y consulte la sección 9.1 Interrupt Vectors in ATtiny25/45/8 y definelo usted mismo. Si está utilizando avr-gcc, la macro ISR() está definida aquí .

Creo que esto cubre lo básico sin revelar demasiado código. ¡Buena suerte y diviértete!

    
respondido por el Jon L

Lea otras preguntas en las etiquetas