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
-
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:
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.
-
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 ;)
-
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!
-
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.
-
Basta escrever "sei()" para as interrupts ficarem activas?
Cá vai código inteiro então:
#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;
}
}
-
Já resolvi. Burrice minha... Tinha-me esquecido de por a biblioteca <interrupts.h> :|