Función de retardo usando el temporizador / contador 1

0

he creado una función llamada _MY_Delay () que utiliza el temporizador / contador1 de 16 bits en ATMEGA16 , y usé esta función para parpadear un LED. el problema es que no trabajé y no sé la razón, aquí está mi código:

 #define  F_CPU 1000000
 #include <avr/io.h>
 #include <avr/interrupt.h>

 void _MY_Delay(int delay){
 int n = (delay*F_CPU)/(1000*64) ; // number of counts required for the given delay 
 OCR1BL = n;                    // n =T(overflow time)*F_cpu / 64
 OCR1BH = n >> 8 ;
 while (!(TIFR & 1<<OCF1B));
 }


 int main(void)
 {
 DDRA = 0x00;
 DDRA |= 0x01;
 TCCR1B = (1<<CS10)|(1<<CS11); //divide by 64 (prescaler)
 sei();
 TIMSK |= 1<< OCIE1B ;
 WDTCR = 0x00; // disable watchdog timer 
 while(1)
 {
    PORTA |= 0x01 ;
    _MY_Delay(100);
    PORTA &= ~(0x01);
    _MY_Delay(100);
 }
 }
    

3 respuestas

2

El problema principal es con tu aritmética.

El argumento de _MY_Delay() se declara como int , y estás pasando el valor 100.

Lo primero que debes hacer es dividir el argumento por 1000. El resultado de esta división siempre será cero.

Obtendrás resultados más útiles si haces la multiplicación primero:

void _MY_Delay(int delay){
  int n = (delay*F_CPU)/1000; // number of counts required for the given delay 
  ...
}

... pero asegúrese de que el resultado intermedio no desbordará un número entero. Si es así, usa un long .

    
respondido por el Dave Tweed
1

El problema con su código actual es que habilita la interrupción de la salida B del temporizador1 mientras que no usa un controlador de interrupciones, esto lleva a un reinicio del mcu.

Elimina la siguiente línea de tu código y funcionará

TIMSK |= 1<< OCIE1B ; // enables timer1 output compare B interrupt

Con respecto a su función de demora, ya que no usa una interrupción y la ejecución espera a que finalice el temporizador, también puede usar la función _delay () de la biblioteca de demora con los mismos resultados (a menos que solo quiera experimentar con los temporizadores).

#include <util/delay.h>

void my_delay_ms(uint16_t n) {
 while(n--) {    // loop until 0
  _delay_ms(1);  // 1ms delay
 }
}

Utiliza una variable de 16 bits, por lo que puede usarla para retardos de hasta 65535 ms (65,5 segundos) (puede usar una variable de 8 bits para retrasos de hasta 255 ms si lo desea). Hay una pequeña sobrecarga en el retraso causado por el bucle, pero si estás interesado en los retrasos precisos, deberías usar una interrupción de temporizador de todos modos.

Como ejemplo, para una demora de 0.5 seg, lo llamas my_delay_ms(500)

    
respondido por el alexan_e
0

No estoy familiarizado con la CPU, por lo que no puedo hablar sobre el uso del registro. Sin embargo, esta línea: PORTA |= 0x00; no es la forma de desactivar un poco, en lugar de usar: PORTA &= ~(0x01);

Como nota al margen: El (los) compilador (es) de C añaden uno o dos guiones bajos a los nombres, por lo que puede haber confusión en el compilador con nombres que ya tienen un guión bajo.

the document at: <http://www.atmel.com/images/doc2466.pdf>
contains the details of the chip and the register names and bit
definitions and the details of how to access those registers in C

amongst other things, the section titled "accessing 16-bit registers"  it states
"To do a 16-bit write, the high byte must be written before the low byte."
however the posted code is performing the 16-bit write in the opposite order, I.E. junk is being written to the high byte of the 16-bit register
    
respondido por el user3629249

Lea otras preguntas en las etiquetas