AVR: usando ATmega328 Timer1 para crear un retraso [duplicado]

2

Estoy teniendo algunos problemas para comprender esto, y podría ser un pequeño error en algún lugar, que sigo perdiendo ... pero tal como está, estoy tratando de crear un "retraso" de hardware que puede ejecutarse en el Al mismo tiempo se ejecuta algún código.

Para propósitos de práctica, simplemente estoy tratando de hacer parpadear un LED en PD4 a un intervalo de 1 segundo.

He utilizado la siguiente fórmula para determinar el preescalador y el valor del Registro de comparación de salida A (OCR1A):

Alutilizarunvaloranteriora256,obtengounvalorparaOCR1Ade62499:

Mirando los registros TCCR1A y TCCR1B en la hoja de datos, configuro los bits del Modo de Generación de Forma de Onda (WGM) para usar CTC y los bits de Selección de Reloj para usar el prescaler 256.

Ahora, en mi función principal, estoy empezando por encender el LED y luego llamar a mi función que debería iniciar el temporizador. Luego estoy comprobando si el indicador de desbordamiento se ha establecido en TIFR1 y, si lo está, enciendo el LED y escribo un 1 lógico en TOV1 para restablecer el indicador de desbordamiento.

int main(void) {
   DDRD = 0xFF;
   PORTD = 0x00;

   while (1) {

      // Turn on LED at PD4
      PORTD |= (1 << PD4);

      oneSecondDelay();

      // Checking to see if the overflow flag has been set
      if (TOV1 == 1) {

         // Turn off LED at PD4
         PORTD &= ~(1 << PD4);

         // Set 1 in the Output Compare A Flag to reset the overflow flag
         TIFR1 = (1 << TOV1);
      }
   }

   return 0;
}

En mi función, comienzo configurando OCR1A en el valor que calculé anteriormente. Luego configuro los bits en el registro TCCR1B que deben configurarse para usar el preescalador específico y el modo CTC, y luego creo un bucle mientras espero que ocurra el evento de desbordamiento; que me imagino debería tomar un segundo.

void oneSecondDelay() {
   // Set the target value to 62499
   OCR1A = 0xF423;

   // Set prescaler to 256 and start the timer
   TCCR1B |= (1 << WGM12) | (1 << CS12);

   // Waiting for the overflow event
   while ((TIFR1 & (1 <<  OCF1A))) {

   }
}

TLDR: Ahora el problema es que no importa lo que pueda soñar, el LED se enciende constantemente y no estoy seguro de si estoy configurando los valores incorrectos en los registros, o si estoy ¿Sólo tienes un poco de cerebro?

    
pregunta Michael Nissen

1 respuesta

0
void oneSecondDelay() {

la construcción de esa función no es terriblemente óptima. fácilmente podría haber tomado un parámetro para determinar la duración de la demora, sin mencionar otros problemas.

Una solución rápida sería algo como esto: todavía tiene problemas pero al menos es viable.

//create a user-specified delay
//dly-duration in timer ticks
//timer1 presummed running, running at 256:1 prescaler
void myDelay(uint16_t dly) {
   // Set the target value to 62499
   OCR1A = TCNT1 + dly - 1;     //0xF423;

   // Set prescaler to 256 and start the timer
   //TCCR1B |= (1 << WGM12) | (1 << CS12);
   TCCR1B = (TCCR1B &~0x07) | (TMR1_PS256x & 0x07); //set timer1 prescaler to 256:1

   // Waiting for the overflow event
   while ((TIFR1 & (1 <<  OCF1A)) == 0) {

   }

   TIFR1 |= (1<<OCF1A);         //clear the flag

}

ese fragmento de código en acción cuando se alimenta TMR1_PS100ms como parámetro:

el objetivo de escribir cualquier fragmento de código es para que no tenga que escribirlo nuevamente. De esa manera, cualquier cosa que escriba es una inversión, no un gasto.

    
respondido por el dannyf

Lea otras preguntas en las etiquetas