PIC interrupt delay_ms

0

Estoy usando MikroC Pro, PIC16F1824 con XTAL 4Mhz.

Básicamente tengo 2 modos de LEDs. Utilizo un cable serie para enviar el modo para jugar.

  • Modo 1 = Encendido durante 3 segundos y Apagado durante 3 segundos.
  • Modo 2 = Encendido durante 1 segundo y Apagado durante 1 segundo.

Todo funciona bien y uso una interrupción. Pero cuando envío un nuevo modo de jugar, espera hasta que se complete el modo de ejecución actual. No detiene el modo actual inmediatamente.

Preguntas:

  • ¿Cómo uso la interrupción para detener el modo actual inmediatamente (delay_ms) y reproducir el nuevo modo?
  • Me dijeron que debía usar el contador de bucles. ¿Cómo funciona?

Código:

 void OnLed(short nMode){
if (nMode == 1)
{
    PWM1_Set_Duty(100);
    delay_ms(3000);
    PWM1_Set_Duty(0);
    delay_ms(3000);
}
else
{
    PWM1_Set_Duty(100);
    delay_ms(1000);
    PWM1_Set_Duty(0);
    delay_ms(1000);
} 
}
void interrupt()
{
    cnt++ ;             // Interrupt causes cnt to be incremented by 1
    PIR1.TMR1IF = 0;    // Reset bit TMR1IF
    TMR1H = 0xFC;       // TMR1H and TMR1L timer registers are returnesd
    TMR1L = 0x18;       // their initial values
}

'void main()
{

...

T1CON = 1;          // Turn on timer TMR1
PIR1.TMR1IF = 0;    // Reset the TMR1IF bit
TMR1H = 0xFC;       // TMR1H and TMR1L timer registers are returned
TMR1L = 0x18;       // their initial values
PIE1.TMR1IE = 1;    // Enable an interrupt on overflow
INTCON = 0xC0;      // Enable interrupt (bits GIE and PEIE)

...

UART1_Init(9600);

...

while(1)
{
    if (UART1_Data_Ready())
      {
        sByte = UART1_Read();
        if (sByte = '1')
            OnLed(1);
        else 
            OnLed(2);
    }
}
    
pregunta mlam

3 respuestas

2

En lugar de usar delay_ms () para hacer la sincronización de tu LED, debes usar la interrupción del temporizador para eso. No conozco a MikroC en absoluto, pero asegúrate de tener las interrupciones de tiempo correctas primero. Luego, calcula la duración entre dos interrupciones de temporizador sucesivas. Usando este valor, puede agregar una variable global (estática) para mantener su límite superior para su contador (supongo que en su caso, cnt). Calcularía estos dos valores de límite superior manualmente: uno para el modo uno, otro para el modo dos (es decir, su contador debería contar y restablecerse a 0 una vez que alcance el valor respectivo). Estos valores determinarán su retraso de 3 segundos o 1 segundo. Podría tener otra variable global para determinar si el LED debería estar encendido o apagado, pero podría hacerlo sin él.

Ahora, en el código principal, solo necesitas cambiar los límites de tu contador dentro de tu declaración if-else.

    
respondido por el dhsieh2
0

Sospecho que lo que alguien estaba sugiriendo es mover su lógica OnLed () a la otra condición en su bucle en main (). Use el conteo incremental para hacer un seguimiento del tiempo para hacer que la lógica cambie. Puedes restablecer el tiempo de cambio fácilmente al recibir un personaje.

    
respondido por el kenny
0

Muestra de código manual

Interrupt calibrated to one second{
   timeCount++;
}

main{
  mode = readState;
  if mode = 1{
    if timeCount >= 1{
      LEDSTATE = !LEDSTATE;
      timeCont = 0
    }
  }
  if mode = 2{
    if timeCount >= 3{
      LEDSTATE = !LEDSTATE;
      timeCont = 0
    }
  }

}
    
respondido por el André Müller Pereira

Lea otras preguntas en las etiquetas