2010-11-04 18 views
3

2 dernières semaines essaie d'apprendre la minuterie & interruption & a écrit un programme (avec ma compréhension) à clignoter LED sur ATmega2560 mais peu importe ce que je fais fonction TCNT0 incrémente jamais & ISR() ne sera jamais appelé. Où vais-je mal et comment puis-je le réparer? Voici mon code:Besoin d'aide avec minuterie

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

#define READ_ATMEGA(ADDR) *((P_CHAR)(BASE_ADDR + ((ADDR) * ADDR_MULTIPLIER))) 
#define WRITE_ATMEGA(ADDR, DATA) *((P_CHAR)(BASE_ADDR + ((ADDR) * ADDR_MULTIPLIER))) = DATA 

#define BASE_ADDR 0x20 

void init_timer0_ovf_interrupt(void); 
void timer0_interrupt_isr(void); 
void initialize_ports(void); 
void delay(unsigned int no_65_5ms_interrupts); 

void __attribute__((ISR)) timer0_interrupt_isr(void); 

//#pragma interrupt_handler timer0_interrupt_isr:24 

unsigned int delay_timer; 

int main(void) 
{ 
    initialize_ports(); 
init_timer0_ovf_interrupt(); 
delay(46); 
return 0; 
    } 

void initialize_ports(void) 
{ 
    READ_ATMEGA(4) = 0xff; 
    WRITE_ATMEGA(5, 0x00); 
} 

void delay(unsigned int no_65_5ms_interrupts) 
{ 
    TCNT0 = 0x00; 
    delay_timer = 0; 
    while(delay_timer <= no_65_5ms_interrupts) 
    { 
    ; 
    } 
} 

void init_timer0_ovf_interrupt(void) 
{ 
    TCCR0A = 0X00; 
    TCCR0B = 0x02; 
    TIMSK0 = 0x01; 
    TIFR0 = 1<<0; 
    OCR0A = 25; 
    sei(); 
} 

void timer0_interrupt_isr(void) 
{ 
    delay_timer++; 
    if(delay_timer >= OCR0A) 
    { 
    PORTB = ~(PORTB); 
    delay_timer = 0; 
    } 
} 
+0

FYI- Pour formater un bloc de code, sélectionnez-le et cliquez sur le bouton 'code'; celui qui ressemble à des chiffres binaires. – meagar

+0

Bien sûr, merci pour l'info. – sneezy

Répondre

1

3 -4 jours auparavant, j'ai écrit le même programme un peu différemment & eu clignotants LED mais toujours pas sûr si c'est la bonne façon d'utiliser minuterie & interruption. Quelqu'un peut-il s'il vous plaît voir ce & dites-moi si c'est le bon ou pas? J'ai réussi à écrire ce programme en lisant des programmes de minuteries, d'interruptions.

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

volatile uint8_t intrs; 

ISR(TIMER0_OVF_vect) { 
    /* this ISR is called when TIMER0 overflows */ 
    intrs++; 

    /* strobe PORTB.5 - the LED on arduino boards */ 
    if (intrs >= 61){ 
     PORTB = ~PORTB; 
     intrs = 0; 
    } 

} 


int main(void) { 

    TCCR0B = 0x02; 

    /* Enable Timer Overflow Interrupts */ 
    TIMSK0 = 0x01; 

    /* other set up */ 
    DDRB = 0xff; 
    TCNT0 = 0; 
    intrs = 0; 

    /* Enable Interrupts */ 
    sei(); 

    while (1) 
     ; /* empty loop */ 
} 

Si c'est la bonne façon, je peux commencer à travailler sur l'étape suivante.

Merci

+0

Je ne suis pas familier avec les produits Atmega/Arduino, donc je ne peux pas dire avec certitude, mais il semble que vous définissez la fréquence de la minuterie (TCCROB), en activant les interruptions de temporisation (TIMSK0), en réinitialisant le compteur (TCNT0) et en activant les interruptions du système (sei). Cela devrait être tout ce qui est généralement nécessaire pour faire fonctionner une minuterie. En ce qui concerne votre programme d'origine, je ne sais pas pourquoi cela ne fonctionnerait pas, puisque vous sembliez mettre tous les mêmes registres, plus quelques autres. Peut-être que dans votre programme d'origine, timer0_interrupt_isr n'était pas correctement associé à l'interruption de dépassement de temps du timer? –

0

Si pourrait être que votre boucle while dans la fonction de retard ne fait rien et n'incrémenter delay_timer si vous êtes coincé dans une boucle sans fin:

void delay(unsigned int no_65_5ms_interrupts) 
{ 
    TCNT0 = 0x00; 
    delay_timer = 0; 
    while(delay_timer <= no_65_5ms_interrupts) 
    { 
    ; //Nothing is happening here!! 
    } 
} 
1

Le la variable globale delay_timer est partagée entre le code d'interruption et le code de non-interruption. Il doit être déclaré comme volatile car la valeur peut changer en dehors de delay().

Si vous regardez le code généré pour delay(), vous verrez probablement que la valeur de delay_timer n'est pas relue pendant la rotation dans la boucle while. En outre, volatile ne suffit pas. Vous avez un code sans interruption et un code d'interruption qui écrit dans la même variable (delay_timer). Vous devez protéger les écritures de la variable dans le code sans interruption, il y a une condition de concurrence. Le moyen facile/paresseux est de désactiver les interruptions & les restaurer dans le code de non-interruption.

(En ce qui concerne la configuration de vos interruptions & à partir de votre minuterie, cette information devrait être dans la fiche technique de la puce. Habituellement, c'est la partie qui est plus facile d'obtenir le droit, il est la substance de données partagées qui mord les gens.)

+0

Je suis vraiment paniqué parce que je dois soumettre ce projet avant demain et je ne comprends toujours pas les minuteries et les interruptions parfaitement. (Ce n'est pas le projet de loi que je dois soumettre). Je dois lier des LEDs et des commutateurs, des LED de boucle et quand le commutateur est pressé ... allumé la LED appropriée en utilisant le temporisateur et l'interruption et sans employer les dossiers principaux d'avr. Dan .. ce que vous avez dit dans votre message, je réfléchis toujours dessus – sneezy