Timer AVR's

Saludos foro!
Bueno de antemano gracias y mi duda es acerca del Timer del ATmega8 el T1 no me funciona de la mejor manera no se si atienda de forma correcta la interrupcion por desbordamiento, quiero generar una base de tiempo precisa para un reloj, el circuito tiene un cristal de 12MHz lo que hago es inicializar el la cuenta del Timer en 0xFFFF-12000=0x0:LOL:11F para que cuando desborde halla contado los 12000 pulsos de 83.333nS es decir 1 mS.

Ahorita estoy solo visualizando las variables que estoy usando pero el problema es que la variable segundos cambia hasta que la de los ms llega a 65535 no 1000 como lo indica el if de la interrupcion :S ademas de que tampoco cambia la velocidad del reloj le cambio el divisor que tiene y se mantiene la misma, yo la ocupo sin dividir, pero no se si por que sea un cristal externo o sinceramente no se que pueda ser, un registro que me falte no lo se, por eso pido ayuda al for adjunto el codigo del programa, el circuito y el proyecto para AVR Studio.

La interrupcion si funciona sin ningun problema resetea como debe hacerlo.

Código:
/*
 * Timer.c
 *
 * Created: 21/11/2011 02:42:26 p.m.
 *  Author: Jaime
 */ 

#include <avr/io.h>
#include <avr/interrupt.h>

#include "retardo.h"
#include "LCD_4bits.h"

unsigned int ms;
unsigned char seg;

/************************************************************************/
/*               Interrupcion externa INT0                              */
/************************************************************************/
ISR (INT0_vect)
{ 
	//Limpia todas las variables
	seg=0;			
	ms=0;			
	TCNT1=0xD11F;
}
/************************************************************************/
/*               Interrupcion externa INT1                              */
/************************************************************************/
ISR (INT1_vect)
{ 
	//Por ahora no se ocupa
}
/************************************************************************/
/*         Interrupcion por desbordamiento del T1                       */
/************************************************************************/
ISR (TIMER1_OVF_vect)
{
	TCNT1=0xD11F;	//Inicializa el valor de la cuenta del T1 **En el main lo explica mejor
	ms++;			//Incrementa la variable que cuenta los milisegundos
	if (ms==1000)	//Si hay 1000 milisegundos
		{
			seg++;	//Incrementa la de los segundos
			ms==0;	//Limipia los milisegundos
		}
}

void main (void)
{ 
	unsigned char hold;
	
	DDRD=0x00;				//Puerto D Como entrada
	PORTD=0xFF;				//Pull up enable para todo el puerto D
	inicializacion_LCD();	//Inicializa el LCD a 4 bits
	display_off();			//Apagar el cursor
	
	/************************************************************************/
	/*                     Interruciones externas                           */
	/************************************************************************/
	
	sei();													//Hablitacion de las interrupciones globales
	MCUCR|=(1<<ISC11)|(0<<ISC10)|(1<<ISC01)|(0<<ISC00);		//Interrupcion por transicion de bajada 
	GICR|=(1<<INT1)|(1<<INT0);								//Hablitacion de las interrupciones externas
	
	/************************************************************************/
	/*                            Timer 1                                   */
	/************************************************************************/
	
	TCCR1B|=(0<<CS10)|(0<<CS10)|(1<<CS10);	//Reloj sin dividir
	TIMSK|=(1<<TOIE1);						//Hablitacion de interrupcion por desbordamiento del T1
	TCNT1=0xD11F;							//Inicializa cuenta del T1 para contar 12000 pulsos o sea 1mS debido al cristal de 12MHz
 	 										//0xFFFF-12000=0xD11F para generar la interrupcion por desbordamiento
											  
	/************************************************************************/
	/*               Ciclo principal repetitivo                             */
	/************************************************************************/
	while(1)
	{
		linea_inicial();				//Acomoda el cursor en la linea inicial del LCD
		print_var(ms,5,10,NO_DOT);		//Imprime el valor de ms en el LCD con 5 digitos, decimal, y sin punto
		salto_linea();					//A la segunda linea del LCD
		print_var(seg,3,10,NO_DOT);		//Imprime el valor de seg en el LCD con 3 digitos, decimal, y sin punto
		display_write(' ');				//Escribe un espacio
		print_var(TCNT1,4,16,NO_DOT);	//Imprime el valor de TCNT1 (cuenta del T1) en el LCD con 4 digitos, hexadecimal, y sin punto
		do 
		{
			hold=PIND&0x01;				//Para visualizar, le pone pausa al sistema
		} while (hold==0);
		 
		
	}		
			
	
}
PD
En resumen lo que hace bien es en lo que al timer respecta:
-De cierta forma entra a la interrupcion por que incremeta ambas variables
-La interrupcion externa funciona sin ningun problema.
-El timer si empieza la cuenta en FB4F hasta desbordar

Lo que no hace es:
-Cada 1000 cuantas de ms hacer que incremente seg, si no hasta que llega 65535 (FFFF el valor max de unsigned int)
-No cambia la frecuencia del timer aun seleccionando el divisor por 1024, solo si no se le selecciona fuente este se mantiene fijo eso si funciono de forma correcta (Lo explica mejor dentro del PDF)

Timer.png
 

Adjuntos

  • Capitulo 4 temporizador contador.pdf
    388.6 KB · Visitas: 4
  • Timer.rar
    47.4 KB · Visitas: 2
Última edición:
Eh saludos de nuevo para decirles que corregi los errores, fueron errores de software muy tontos y ovios una disculpa les digo que cambio

Estaba esto:
Código:
TCCR1B|=(0<<[B]CS10[/B])|(0<<[B]CS10[/B])|(1<<CS10);	//Reloj sin dividir
Esto es lo correcto:
Código:
TCCR1B|=(0<<[B]CS12[/B])|(0<<[B]CS11[/B])|(1<<CS10);	//Reloj sin dividir

Corrigio lo del divisor del reloj

Estaba esto:
Código:
ISR (TIMER1_OVF_vect)
{
	TCNT1=0xD11F;	//Inicializa el valor de la cuenta del T1 **En el main lo explica mejor
	ms++;			//Incrementa la variable que cuenta los milisegundos
	if (ms==1000)	//Si hay 1000 milisegundos
		{
			seg++;	//Incrementa la de los segundos
			[B]ms==0;[/B]	//Limipia los milisegundos
		}
}
Esto es lo correcto:
Código:
ISR (TIMER1_OVF_vect)
{
	TCNT1=0xD11F;	//Inicializa el valor de la cuenta del T1 **En el main lo explica mejor
	ms++;			//Incrementa la variable que cuenta los milisegundos
	if (ms==1000)	//Si hay 1000 milisegundos
		{
			seg++;	//Incrementa la de los segundos
			[B]ms=0;[/B]	//Limipia los milisegundos
		}
}

Con esto se corrigio lo que la variable llegara al maximo valor de su tipo 65535 por ser unsigned int ya que nunca se limpiaba la variable ms
 
Última edición:
Hola, amigos. Estoy programando en Codevision AVR un Atmega88, pero he tenido problemas con la lectura del temporizador Timer 1 (16 Bits)
He buscado información pero no encuentro ningún ejemplo claro.
Según la información que he encontrado debo leer el valor del timer 1 en TNCT1L y TNCT1H, pero solo consigo valores de entre 0-255 en TCNT1L, como si se tratara de un timer de 8 bits y 0 en TCNT1H.
Lo que necesito saber únicamente es como asignar el valor del Timer1 en una variante.

En este ejemplo la variable "a"
Les agradecería mucho si me pudieran orientar en este tema.
De ante mano, muchas gracias.
PHP:
#include <mega88>
#include <stdio.h>
#include <delay.h>

void main(void)
{
// Declare your local variables here
long a;
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif


// Port D initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (1<<DDD1) | (0<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);


// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 7.813 kHz
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer Period: 8.3886 s
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (1<<CS12) | (0<<CS11) | (1<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;


// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: Off
// USART Transmitter: On
// USART0 Mode: Asynchronous
// USART Baud Rate: 9600
UCSR0A=(0<<RXC0) | (0<<TXC0) | (0<<UDRE0) | (0<<FE0) | (0<<DOR0) | (0<<UPE0) | (0<<U2X0) | (0<<MPCM0);
UCSR0B=(0<<RXCIE0) | (0<<TXCIE0) | (0<<UDRIE0) | (0<<RXEN0) | (1<<TXEN0) | (0<<;UCSZ02) | (0<<RXB80) | (0<<TXB80);
UCSR0C=(0<<UMSEL01) | (0<<UMSEL00) | (0<<UPM01) | (0<<UPM00) | (0<<USBS0) | (1<<UCSZ01) | (1<<UCSZ00) | (0<<UCPOL0);
UBRR0H=0x00;
UBRR0L=0x33;


// TWI initialization
// TWI disabled
TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);

while (1)
{ 
      
      if(PIND.7==1)
        {
        a=TCNT1L; 
        printf("\r%d",a);
        while(PIND.7==1)
        {}
        }
        
        

      }
}
 
Hola, resulta que los registros TNCT1L y TNCT1H, son de 8 bits. Para asignarles valores deberás partir una variable de 16 bits (mayor peso =H, menor peso=L) luego asignar los valores a cada registro. Para obtener luego un valor de 16bits, pues lees cada registro y mediante corrimiento de bits, lo asignas a una variable de 16bits o tipo long.
Ejem:
variablelong=TNCT1H;
variablelong=(variablelong<<8)+TNCT1L;
 
Última edición:
Hola, resulta que los registros TNCT1L y TNCT1H, son de 8 bits. Para asignarles valores deberás partir una variable de 16 bits (mayor peso =H, menor peso=L) luego asignar los valores a cada registro. Para obtener luego un valor de 16bits, pues lees cada registro y mediante corrimiento de bits, lo asignas a una variable de 16bits o tipo long.
Ejem:
variablelong=TNCT1H;
variablelong=(variablelong<<8)+TNCT1L;

Amigo en verdad me haz ayudado inmensamente te lo agradezco mucho :apreton:
 
Porque accedés al registro en 8bit? O es que ese compilador solo lo hace de esa manera?
En el AVR-GCC ese registro se maneja a 16bit de un tiro, es decir.

a unsigned int;

a = TCNT1;
 
Atrás
Arriba