Elección de la declaración condicional apropiada

0

Estoy midiendo el ancho de un impulso PWM con la interrupción externa:

void interrupt ISR() {

if (INTCON3bits.INT1IF) {                   // INT0 interrupt
    if(INTCON2bits.INTEDG1) {               // Rising edge detected
        T1CONbits.TMR1ON = 1;               // Start TMR1
        INTCON2bits.INTEDG1 = 0;            // Swap edge
    } else if (!INTCON2bits.INTEDG1) {      // Falling edge detected
        T1CONbits.TMR1ON = 0;               // Stop TMR1
        INTCON2bits.INTEDG1 = 1;            // Swap edge
    }
 INTCON3bits.INT1IF = 0;                    // Clear flag
    }
}

Quiero almacenar el ancho del pulso actual y el ancho del siguiente pulso. Por ancho me refiero al valor TMR1 [hexadecimal], no a un valor de tiempo [s]. ¿Cómo y dónde debo hacer esto?

Algo más: si estos dos valores de pulso son los mismos, quiero hacer 'algo1', si no lo son, quiero hacer 'algo2': se parece a esto:

if (current_value == previous_value) {
     Do something1; // if entered here, I will start UART communication and keep reading incomming data constantly, so I suppose this is a dead end.
 } else {
     Do something2; // if entered here, there is no need of pulse measurment anymore
 }

Pero mientras esté en esto, si la rutina quiero verificar constantemente el ancho del pulso, ¿cómo puedo hacer eso? Pensé en una rutina de "hacer mientras", pero no estoy seguro de ello también.

Estoy trabajando con pic18f25k80, usando MPLAB X si esto es importante

    
pregunta PlatonInc.

2 respuestas

4

Esto no está respondiendo directamente a sus preguntas, sino que aborda el problema de nivel superior de medir el ancho de un pulso usando un PIC típico 16.

Primero, no tiene sentido iniciar y detener un contador. Todo lo que necesita hacer es tomar una instantánea del contador de cada borde, luego hacer una resta entera del nuevo valor menos el valor anterior. Eso le dará los conteos transcurridos entre los dos eventos hasta los conteos máximos que el contador puede expresar. No importa si el valor del recuento se redujo durante el intervalo, siempre que el número de recuentos esté dentro del rango del contador. La resta siempre produce el número de cuentas como un número sin signo.

Por ejemplo, digamos que está utilizando un temporizador de 16 bits, como el temporizador 1 en un PIC 16. Por lo tanto, el valor del temporizador siempre es de 0 a 65535. Siempre que el intervalo que esté tratando de medir sea de 65535 tics o menos En longitud, una simple resta de nuevo menos anterior siempre dará como resultado la respuesta deseada. Digamos que el intervalo es de 100 tics de largo. Obviamente, esto funciona si los conteos anterior y nuevo son 1234 y 1334, 5000 y 5100, etc.

Sin embargo, todavía funciona incluso si el contador se ajustó durante el intervalo. Por ejemplo, considere qué sucede si el valor anterior era 65500, que es FFDCh. Sumando 100 (64h) a los rendimientos 10040h. Sin embargo, el hardware simplemente descarta el mantenimiento del último bit, por lo que el valor del contador de 16 bits será 0040h (64). Entonces, para determinar la longitud del intervalo, realice la resta de 64 - 65500, o 0040h - FFDCh, o 0000000001000000b - 1111111110111100b, manteniendo solo los 16 bits bajos del resultado. Resuelva esto de la manera que desee, y verá que el resultado es 100, 0064h o 0000000001100100b.

El segundo punto es que la mayoría de estos PIC tienen hardware para realizar la operación de captura que está haciendo actualmente en el firmware. Lea nuevamente el capítulo de la hoja de datos en el módulo CCP, esta vez prestando especial atención al modo de captura. Verá que el hardware de CCP toma el valor del temporizador de ejecución libre 1 en el momento de un flanco de entrada. Solo hace esto en una polaridad de borde, por lo que aún tiene que tomar la interrupción y cambiar a la otra polaridad de borde para configurar el próximo evento de captura. O, si tiene dos módulos CCP disponibles, configúrelos para capturar en bordes opuestos. En cualquier caso, el valor del temporizador 1 se captura en los registros de CCP por el hardware en el momento del límite. Todo lo que tiene que hacer es agarrarlo antes del siguiente borde y hacer la resta para encontrar el número de tics del temporizador 1 desde el último evento de captura. Timer 1 funciona gratis todo el tiempo. Iniciarlo y detenerlo solo desperdiciará ciclos y, posiblemente, provocará la pérdida de eventos y agregar jitter.

    
respondido por el Olin Lathrop
0

Si desea guardar los valores de una llamada de función a la siguiente, puede declarar una variable estática:

void interrupt ISR()
{
  static int last_width = 0;
  int new_width;

  //Get the new width
  new_width = ...

  //After some processing, save the new width
  last_width = new_width;
}

last_width se inicializa una vez cuando se inicia el programa, al igual que una variable global. Luego retiene su valor entre las llamadas a ISR ().

Tenga en cuenta que su medición no será muy precisa si el tiempo que tarda en llegar a la interrupción varía. Esto puede suceder si otras interrupciones están atando la CPU.

    
respondido por el Adam Haun

Lea otras preguntas en las etiquetas