LusoRobótica - Robótica em Português

Sistemas específicos => Arduino / AVR => Tópico iniciado por: zepedro em 21 de Junho de 2012, 22:30

Título: Timer no ATMega88
Enviado por: zepedro em 21 de Junho de 2012, 22:30
Olá,

estou a usar um ATMega88 e estou a tentar implementar um timer. Apesar de ter preenchido os registos todos conforme o datasheet, obtenho um erro que me faz com que o programa comece sempre de novo cada vez que a interrupção é chamada!
Sei isto porque tenho uma variavel incializada a 0 que é mostrada num LCD, e quando carrego no botão de incrementar, esta volta-me sempre a 0!

Tá aqui o código dos registos:


Código: [Seleccione]
OCR0A=250;  //*Escreve 250 no OCR0A    -   0.0321 segundos
TCCR0A=2;  //*Configuracao do TC0 para modo CTC*
TCCR0B=0b00000101;    //*Prescaler para 1024    -    1/(8*10^6/(1024*(250+1))
TIMSK0|=2;            //*Saida do TC0 compara as interrupçoes activas*
SREG|=0b10000000;


E a rotina de interrupção:

ISR(TIMER0_COMPA_vect)
{
count--;
if (count==0)
{
conv=1;

count=156;
}
}

Já aconteceu isto a alguém? Abraço.
Título: Re: Timer no ATMega88
Enviado por: senso em 21 de Junho de 2012, 22:35
Podes mostrar o resto do código.
A variavel count está definida como volatile?
Já apanhei este tópico em mais 2 fóruns, se responderes tens mais ajuda do que espalhares a pergunta por todo o lado e mais algum  ;)
Título: Re: Timer no ATMega88
Enviado por: zepedro em 21 de Junho de 2012, 23:42
O código é um bocado extenso e por isso é que não colei aqui tudo! A variável count não está como volatile, mas não é essa que está a ser passada para o LCD. Aliás, se eu nem puser nada na rotina obtenho o mesmo erro!
Título: Re: Timer no ATMega88
Enviado por: senso em 21 de Junho de 2012, 23:57
Qualquer variavel usada numa ISR tem de ser declarada como volatile, sem o código completo não há muito mais a fazer.
E não deves mexer no SREG, usa antes o sei() para ligar interrupções e o cli() para as desligar, é muito mais seguro.
Título: Re: Timer no ATMega88
Enviado por: zepedro em 22 de Junho de 2012, 00:26
Basta escrever "sei()" para as interrupts ficarem activas?


Cá vai código inteiro então:


Código: [Seleccione]
#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>

#include "lcd.h"
#include "ds1307.h"
#include "I2C.h"
#include "therm_ds18b20.h"


unsigned int count=156, conv=0;   //count 156*0.032s para fazermos 5 segundos

int main(void)
{
unsigned int c=10, inc=0, flag1=0;
char buffer [33];
char x[20] = {0};
uint8_t temperature[2];
int8_t digit;
uint16_t decimal;

DDRD=0b00000010; //so TX é que é saida (para ja)


OCR0A=200;  //*Escreve 250 no OCR0A    -   0.0321 segundos
TCCR0A=2;  //*Configuracao do TC0 para modo CTC*
TCCR0B=0b00000101;    //*Prescaler para 1024    -    1/(8*10^6/(1024*(250+1))
TIMSK0|=2;            //*Saida do TC0 compara as interrupçoes activas*
SREG|=0b10000000;



// Initialize my LCD display.  Uses the Fleury LCD code
lcd_init(LCD_DISP_ON);

// Clear the LCD screen
lcd_clrscr();         


  while(1)
{


inc=(PIND & 0b00100000); //conta o numero de impulsos no botao
  if (inc==0b00100000)
    flag1=0;
   if(inc==0 && flag1==0) //flag para evitar que conte mais do que um impulso no caso do botao estar activo bastante tempo activo
  {
    flag1=1;
    c++;
    }



//----------Termometro-----------------

if(conv==1)
{
therm_read_temperature2(&digit, &decimal);
conv=0;
}

//----------Apresentar-------------------

lcd_command(0b00001100); //desliga o cursor
lcd_home(); //volta com o cursor ao inicio

sprintf(buffer, "%d.%d C", digit, decimal);

lcd_puts(buffer);
 

sprintf(buffer, "\n%d",c);

lcd_puts(buffer);




}
 
return 0;
 
 }   



//*******************FIM DA MAIN********************

ISR(TIMER0_COMPA_vect)
{
count--;
if (count==0)
{
conv=1;

count=156;
}
}
Título: Re: Timer no ATMega88
Enviado por: zepedro em 22 de Junho de 2012, 15:47
Já resolvi. Burrice minha... Tinha-me esquecido de por a biblioteca <interrupts.h> :|