Mein Interupt macht nicht das was ich will (atmega 328p @20 MHz)

Gast #3389157
Lesenswert?
• ▲
▼
Schönen guten Abend,

ich versuche seit 2 Stunden dieses Interrupt im ctc modus zum laufen zu 
bringen. Aber egal welche Zahl ich ins Register schreibe, die LED blinkt 
immer gleich schnell (bei dem geschriebenen Programm im Sekundentakt). 
Hat vielleicht jemand einen Tip für mich? Ich habe den verdacht dass 
mein Timer irgendwie nicht zurück gesetzt wird. Kann es sein dass der 
Timer nicht mit dem 20MHz quarz läuft?

Vielen Dank im Vorraus

Markus

#include <avr/io.h>
#include <asf.h>
#include <math.h>
#include <stdlib.h>
#ifndef F_CPU
#define F_CPU 20000000UL
#endif
#include <util/delay.h>
#include <avr/interrupt.h>


void servo_init(void);

#define SERVOPIN 1
#define SERVOPORT PORTD
#define DDRSERVO DDRD

long double t=0;


ISR(TIMER0_COMPA_vect)        //interrupt
{

  t++;

}

void servo_init(void)
{
  TIMSK0|=(1<<OCIE0A);          //interrupts
  TCCR0B |= (1<<CS00);          //Prescale=1,
  TCCR0A |= (1<<WGM01);          // CTC mode
  OCR0A = 200;      //alle 10µs ein IRQ 0,00001s
  DDRSERVO|=(1<<SERVOPIN);        //LED Pin als ausgang

}

int main (void)
{


  servo_init();
  sei ();        //interrups an

  while(1)
  {

    if (t<20000)SERVOPORT|=(1<<SERVOPIN);  //bis zum 20000. durchlaufen 
des Interrupts LED AN (200ms)
    else SERVOPORT &=(0<<SERVOPIN);    //ab dann LED AUS
    if (t>40000) t=0;      // bei 40000. interruptdurchlauf t 
zurücksetzen (insg. 400ms)

  }
}
#3389184
Lesenswert?
• ▲
▼
Sieht mir eigentlich alles gut aus, grad nochmal ins Datenblatt 
geschaut.
Das mit dem Volatile kann eigentlich deshalb nicht das Problem sein, 
weil man sonst im Main den Counter gar nicht erhöht bekäme.
Trotzdem sollte man lieber das Volatile verwenden.

Aber probier mal die Register mit = statt |= zu setzen um sicherzugehen, 
dass sie anderen Bits auch 0 sind.
#3389264
Lesenswert?
• ▲
▼
@ Markus (Gast)

>ich versuche seit 2 Stunden dieses Interrupt im ctc modus zum laufen zu
>bringen. Aber egal welche Zahl ich ins Register schreibe, die LED blinkt
>immer gleich schnell (bei dem geschriebenen Programm im Sekundentakt).
>long double t=0;

Willst du damit andeuten, den Allerlängsten zu haben? ;-)
long double, die es auf dem AVR sowieso nicht gibt, sind in den 
seltesten Fällen sinnvoll. Ein einfacher uint16_t tut es locker. Mal 
ganz abgesehen davon, dass man Servos anders ansteuert. Ausserdem fehlt 
ein volatile, siehe Interrupt.

>Danke für die schnelle Antwort aber die Kiste blinkt immer noch im
>sekundentakt. Eigentlich sollten es ja 200ms sein.

Möglicherweise ist die Arithmetik mit float so aufwändig und langsam, 
dass Interrupts verschluckt werden.
Gast #3389290
Lesenswert?
• ▲
▼
Hi

>Hehe Spess, bist du jetzt auch zu den C-Kryptographen übergelaufen, oder
>leistest du bloß mal Entwicklungshilfe ;-)

Letzteres. Hilft auch um C-Programme nach Assembler umzusetzen.

MfG Spess
#3389659
Lesenswert?
• ▲
▼
Markus schrieb:
> ich versuche seit 2 Stunden dieses Interrupt im ctc modus zum laufen zu
> bringen. Aber egal welche Zahl ich ins Register schreibe, die LED blinkt
> immer gleich schnell (bei dem geschriebenen Programm im Sekundentakt).

Du benutzt AVR Studio 6.x? Versuch mal mit Device Programming -> Memory 
dein Programm auf den Atmega328 zu laden. Der Upload aus der 
Entwicklungsumgebung geht in AVR Studio 6.x manchmal schief, 
insbesonders wenn man mal den Zielprozessor geändert hat.

Markus schrieb:
> if (t<20000)SERVOPORT|=(1<<SERVOPIN);
> else SERVOPORT &=(0<<SERVOPIN);
> if (t>40000) t=0;

Du darfst in main() nicht einfach so auf t zugreifen. Da t größer als 
ein Byte ist, besteht der Zugriff aus mehreren Assemblerbefehlen. Der 
TIMER0_COMPA_vect kann dann zwischen diesen Befehlen stattfinden, so 
dass du unter Umständen sehr seltsame Werte in t beobachten wirst. Um 
jeden Zugriff auf t herum muss darum der Interrupt ausgeschaltet sein. 
volatile allein hilft da nicht.

LG, Sebastian

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren