Forum: Compiler & IDEs ATmega16 Problem


von Tobias Neumann (Gast)


Lesenswert?

Hallo zusammen,
habe folgendes Problem:
Ich habe an PORTA sowie PORTD jeweils 8 LEDs angeschlossen und habe 
bisher mit einem manuel Programmierten Timer diese zum leuchten 
gebracht.
Nun will ich die Timer/Counter möglichkeiten die der ATmega16 mitbringt 
nutzen und habe dafuer folgendes Programm geschrieben welches lediglich 
den ersten PIN des PORTAs im Sekundentakt blinken lassen soll.
Es blinkt jedoch nichts.. sondern die LED blinkt konstant weil die 
Variable "stop" anscheinend in "ISR nicht auf 0 gesetzt wird. Ich kann 
in ISR auch keinen Port schalten von daher habe ich das Gefühl das er 
garnicht erst ISR ausführt..

Hat jemand ne Idee woran es liegen könnte?..
danke im Voraus,
Tobias.

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


volatile uint8_t z;
volatile char stop = 1;

void timer1_init()
{
        z=0;
  //Schaltet zunächst alle Kontroll Register in TCCR1x aus
  TCCR1A=0;
  TCCR1B=0;

  //Schaltet das Zaehlregister zunaechst auf null, wobei es spaeter in 
abhaengigkeit von der internen Taktzahl, dem Prescaler und OCR1A
  // neu gesetzt wird. (Taktzahl/Prescaler_Takt/OCR1x = 
11059000Hz/1024/250
  //Ist letztendlich die Anzahl der Aufrufe des Interupts pro Sekunde, 
also: 43. Deshalb wird die Lampe alle 43 Aufrufe an und aus geschaltet.
        TCNT1=0;

  //Manipuliert den letztendlichen Takt
        OCR1A=250;
        //OCR1B=250;

  //Der Prescaler wird auf 1024 gesetzt und der Timer wird in den 
CTC-Mode gesetzt(WGM12)
  TCCR1B=(1<<CS10)|(1<<CS12)|(1<<WGM12);


  // aktiviere IRQ cnt1
        TIMSK=(1<<OCIE1B)|(1<<OCIE1A);
        sei();
};

// 
//////////////////////////////////////////////////////////////////////
// Wartet etwa t*10 ms.
// timer_10ms wird alle 10ms in der Timer1-ISR erniedrigt.
// Weil es bis zum nächsten IRQ nicht länger als 10ms dauert,
// wartet diese Funktion zwischen (t-1)*10 ms und t*10 ms.
void xwait_10ms ()
{
int i=0;
   for(i=0;i<2000;i++);
}

// 
//////////////////////////////////////////////////////////////////////
// Die Interrupt Service Routine (ISR).
// In interrupt_num_10ms werden die IRQs gezählt.
ISR(TIMER1_COMPA_vect)
{
#if 1
  //PORTA ^= (1<<5);
  z++;
  if(z>=43)
  {
    stop ^= 1;
    z=0;
  }
#endif

}
// 
//////////////////////////////////////////////////////////////////////
// Das Hauptprogramm: Startpunkt
int main()
{
  wdt_disable();

  DDRA = 255;
  DDRD = 255;

  PORTA = 255;
  PORTD = 254;

  // Timer1 initialisieren
      timer1_init();

#if 1
  while(1)
  {
    if ( stop == 1 )
    {
      PORTA &= ~(1<<0);
    }
    else
    {
      PORTA |= (1<<0);
    }
  }

#endif

  PORTD = 0;
}

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Dein Programm stürzt laufend ab, weil in TIMSK = 
(1<<OCIE1B)|(1<<OCIE1A); der Interrupt OCIE1B ohne die passende 
ISR(TIMER1_COMPB_vect) angeschaltet wird.

von Hc Z. (mizch)


Lesenswert?

Zwei Dinge fallen zunächst auf:
1
        TIMSK=(1<<OCIE1B)|(1<<OCIE1A);
Wenn Du beide Interrupts freigibst, müssen auch beide 
Interruptroutinen vorhanden sein, sonst hast Du einen garantierten 
Aufhänger gebaut.  Es existiert in Deinem Code aber nur eine.
1
void xwait_10ms ()
2
{
3
int i=0;
4
   for(i=0;i<2000;i++);
5
}
Die Schleife wird wegoptimiert, da i nicht volatile ist.  Es ergibt sich 
keine Verzögerung von 10 ms, sondern von 0.  Nimm die Delay-Routinen der 
avr-libc.

Weiter habe ich nicht geschaut.

von Tobias Neumann (Gast)


Lesenswert?

ja aber die funktion xwait wird nicht benutzt und ist daher nicht zu 
beachten..

von Tobias Neumann (Gast)


Lesenswert?

Ok ich hab den Teil nun geaendert:
TIMSK=(1<<OCIE1A);

Habe nicht gewusst das ich ihm damit sage Welche ISR Routine er starten 
soll.. aber es funktioniert leider trozdem noch nicht.. danke aber 
trozdem für die Info!

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Die LED an PA0 soll also alle 1 s blinken. Das wäre wenn der Atmega16 
mit 11059000Hz läuft.

Wenn der AVR allerdings nur mit 1 MHz läuft (Werkseinstellung) ist die 
Blinkzeit ca. 11 s.

Hast du mal nach der Codekorrektur so lange die laufende Schaltung 
beobachtet? Funktioniert die Ansteuerung der LED im statischen Fall (um 
Fehler im Aufbau auszuschliessen)?

von Tobias Neumann (Gast)


Lesenswert?

ja also ich habe einen 11,059 Mhz Quarz laufen der den Takt angibt.. 
also ich habe die Schaltung konstant an und die LED geht wirklich nie an 
und aus sie leuchtet zu 100% konstant.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Tobias Neumann schrieb:

> ja also ich habe einen 11,059 Mhz Quarz laufen der den Takt angibt..

Quarz allein in die Schaltung bauen reicht nicht. Schau dir den Artikel 
AVR Fuses an.

> also ich habe die Schaltung konstant an und die LED geht wirklich nie an
> und aus sie leuchtet zu 100% konstant.

Wie lange beobachtet?

LED von Anfang an vermeintlich dauerleuchtend passt zu einer /active 
high/ angeschlossenen LED und obigem Code inkl. Taktratenproblem. Ist 
deine LED active high angeschlossen?

von Tobias Neumann (Gast)


Lesenswert?

Also ich hab den Quartz an XTAL1 und XTAL2 angeschlossen und der Quartz 
hat einen Takt von 11,059 Mhz, heißt das nicht das der Atmega16 dann mit 
dieser Taktung läuft? Entschuldige.. beschäftige mich erst seit einer 
Woche mit Microcontrollern :)

Also ich habe es mind. 2 Min Beobachtet und an ist es seit Stunden.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Tobias Neumann schrieb:
> Also ich hab den Quartz an XTAL1 und XTAL2 angeschlossen und der Quartz
> hat einen Takt von 11,059 Mhz, heißt das nicht das der Atmega16 dann mit
> dieser Taktung läuft? Entschuldige.. beschäftige mich erst seit einer
> Woche mit Microcontrollern :)

Reicht nicht siehe oben.

> Also ich habe es mind. 2 Min Beobachtet und an ist es seit Stunden.

Der Hinweis auf die notwendige Codeänderung kam doch erst vor ein paar 
Minuten. Hast du den Atmega16 noch nicht neu programmiert? Dann stürzt 
er weiterhin laufend ab.

von Karl H. (kbuchegg)


Lesenswert?

Dann überprüf als erstes, ob die ISR überhaupt aufgerufen wird.

Leg die Lampenmanipulation im Hauptprogramm still und schalte in der ISR 
einfach nur eine Lampe ein (oder als Gegentest aus). Lass dein Programm 
laufen und sieh nach, ob das tatsächlich passiert. Dann weißt du schon 
mal, ob die ISR überhaupt aufgerufen wird oder nicht.

von Karl H. (kbuchegg)


Lesenswert?

Zum Thema Quarz

Dieses Testprogramm
1
#define F_CPU 11059000
2
3
#include <avr/io.h>
4
#include <utils/delay.h>
5
6
int main()
7
{
8
  DDRA = 0xFF;
9
10
  while( 1 ) {
11
    PORTA = 0xFF;
12
    _delay_ms( 1000 );
13
    PORTA = 0x00;
14
    _delay_ms( 1000 );
15
  }
16
}

lässt deine Lampe blinken. Die Frage ist nur wie schnell?
Ist die LED 1 Sekunde an / 1 Sekunde aus, dann läuft dein µC mit 11Mhz 
und der Quarz ist aktiv.
Ist die LED 11 Sekunden an / 11 Sekunden aus, dann läuft dein µC mit 
1Mhz und der QUarz ist nicht aktiv.

von Tobias Neumann (Gast)


Lesenswert?

@ Stefan
Die einzige Codeaenderung die ich bisher gemacht habe ist das ich
TIMSK=(1<<OCIE1B)|(1<<OCIE1A);
in
TIMSK=(1<<OCIE1A);
umgeschrieben habe.
Danach habe ich das Program neu auf den MC gebrannt, ohne irgendwelche 
auswirkungen. Die LED an Port PA0 leuchtet weiterhin konstant.

@Karl Heinz
Ich habe versucht in der ISR Ports zu schalten. Ohne Erfolg, mir scheint 
es als ob die ISR garnicht aufgerufen wird!

von Tobias Neumann (Gast)


Lesenswert?

@ Karl Heinz

Habe das Test Programm aufgespielt und die LEDs gehen etwa alle 11 
sekunden aus bzw an! Was soll ich nun tun? :)

von Karl H. (kbuchegg)


Lesenswert?

Tobias Neumann schrieb:
> @ Karl Heinz
>
> Habe das Test Programm aufgespielt und die LEDs gehen etwa alle 11
> sekunden aus bzw an! Was soll ich nun tun? :)

Deinen µC so umstellen, dass er den Quarz auch benutzt

http://www.mikrocontroller.net/articles/AVR_Fuses#Taktquellen_Fuse_Einstellung

von Tobias Neumann (Gast)


Lesenswert?

@ Jo das ich meinen Quartz nicht benutze ist eine sehr hilfreiche 
Erkentniss, danke! Aber letztendlich löst es nicht mein Problem das die 
ISR nicht aufgerufen wird.. woran könnte das liegen?.. ich vermute 
schwer das es was mit dem übergebenen Argument von ISR zu tun hat!

von Justus S. (jussa)


Lesenswert?

Tobias Neumann schrieb:
> @ Jo das ich meinen Quartz nicht benutze ist eine sehr hilfreiche
> Erkentniss, danke! Aber letztendlich löst es nicht mein Problem das die
> ISR nicht aufgerufen wird.. woran könnte das liegen?.. ich vermute
> schwer das es was mit dem übergebenen Argument von ISR zu tun hat!

? Ich denke, die LED blinkt jetzt..dann muss doch die ISR aufgerufen 
werden...

von Tobias Neumann (Gast)


Lesenswert?

Ja die LEDs haben nur in dem "Takt-Testprogramm" geblinkt.. aber dort 
wurde die ISR ja nicht benutzt.

In meinem Programm besteht das Problem weiter!

von Karl H. (kbuchegg)


Lesenswert?

Tobias Neumann schrieb:
> @ Jo das ich meinen Quartz nicht benutze ist eine sehr hilfreiche
> Erkentniss, danke! Aber letztendlich löst es nicht mein Problem das die
> ISR nicht aufgerufen wird.. woran könnte das liegen?.. ich vermute
> schwer das es was mit dem übergebenen Argument von ISR zu tun hat!

Deine Vermutung ist falsch. An eine ISR werden keine Argumente 
übergeben.

Aber speck doch dein Programm mal etwas ab. In diesem langen 
Programmwust findet man doch nichts mehr
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/wdt.h>
4
5
6
volatile uint8_t z;
7
volatile uint8_t stop = 1;
8
9
ISR(TIMER1_COMPA_vect)
10
{
11
  z++;
12
  if( z >= 40 )
13
  {
14
    stop ^= 1;
15
    z = 0;
16
  }
17
}
18
19
int main()
20
{
21
  DDRA = 0xFF;
22
23
  TIMSK  = (1<<OCIE1A);
24
  OCR1A  = 2500;
25
  TCCR1B = (1<<CS10)/*|(1<<CS12)*/|(1<<WGM12);
26
27
  sei();
28
29
  while(1) {
30
    if ( stop == 1 )
31
    {
32
      PORTA = 0x00;
33
    }
34
    else
35
    {
36
      PORTA = 0xFF;
37
    }
38
  }
39
}

Damit müsstest du schon ein Blinken sehen können

von Tobias Neumann (Gast)


Lesenswert?

Hm wenn ich dies versuche auf meinen MC zu brennen habe ich einen sehr 
koischen Effekt beim AVR-dude:

tobias@linux-zpyf:~/AVRprogramme/hello-atmega16> make brennen f=led
avr-gcc -Wall -g -mmcu=atmega16 -DF_CPU=11059200   -c -o led.o led.c
led.c:6:1: warning: "F_CPU" redefined
<command line>:1:1: warning: this is the location of the previous 
definition
In file included from led.c:9:
/opt/cross/lib64/gcc/avr/4.1.2/../../../../avr/include/util/delay.h:90:3 
:  warning: #warning "Compiler optimizations disabled; functions from 
<util/delay.h> won't work as designed"
avr-gcc   led.o   -o led
avr-objcopy -j .text -j .data -O ihex led led.hex
avrdude -u -e -c avrisp2 -P usb -p m16 -U flash:w:led.hex

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 
0.01s

avrdude: Device signature = 0x1e9403
avrdude: erasing chip
avrdude: reading input file "led.hex"
avrdude: input file led.hex auto detected as Intel Hex
avrdude: writing flash (374 bytes):

und danach passiert NICHTS mehr.. sehr komisch oder?

von Karl H. (kbuchegg)


Lesenswert?

Tobias Neumann schrieb:
> Hm wenn ich dies versuche auf meinen MC zu brennen

Wenn du was auf deinen MC brennst.

Das zuletzt gepostete Programm kann es nicht sein, denn

> led.c:6:1: warning: "F_CPU" redefined
> <command line>:1:1: warning: this is the location of the previous
> definition

weder habe ich eine F_CPU Definition im Programmtext, noch ....

> warning: #warning "Compiler optimizations disabled; functions from
> <util/delay.h> won't work as designed"

wird <util/delay.h> includiert

von Tobias Neumann (Gast)


Lesenswert?

Also ich habe nun folgendes Program versucht:

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


volatile uint8_t z;

ISR(TIMER1_COMPA_vect)
{
        z++;
        if(z>=40)
        {
                PORTA ^= 0xFF;
                z=0;
        }
}

int main()
{
        z = 0;
        DDRA = 0xFF;

        TIMSK = (1<<OCIE1A);
        OCR1A = 2500;
        TCCR1B = (1<<CS10)|(1<<CS12)|(1<<WGM12);

        PORTA = 0x00;

        sei();

        while(1);
}

Nachdem ich dies auf den MC gebrannt habe leuchtet der PORTA konstant.
Habe quasi dein Programm noch ein bisschen abgespeckt und CS12 in TCCR1B 
gesetzt, jedoch ohne irgendwelche auswirkungen.
danke schonmal
~
~

von Tobias Neumann (Gast)


Lesenswert?

PS: Dies sind meine Compileranweisungen

avr-gcc -Wall -mmcu=atmega16    -c -o led2.o led2.c
avr-gcc   led2.o   -o led2
avr-objcopy -j .text -j .data -O ihex led2 led2.hex
avrdude -u -e -c avrisp2 -P usb -p m16 -U flash:w:led2.hex

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Für mich ist nicht offensichtlich, was da schief läuft.

Häng vielleicht das led2.hex an deine nächste Frage an, damit man es 
Disassemblieren (Linksammlung: Disassembler) oder Simulieren kann.

Hast du selbst die Möglichkeit per (AVR-Simulation) das Programm im 
Einzelschritt zu debuggen?

von Oliver (Gast)


Lesenswert?

Tobias Neumann schrieb:
> tobias@linux-zpyf

So einen Fall gab es hier letztens doch schonmal. Die mit den 
Linux-Distributionen mitgelieferten avr-gcc's sind wohl nicht alle up to 
date, und nicht alle funktionsfähig. Da wird dann einfach kein 
ISR-Vector eingetragen.

Welche Version hat denn dein Compiler?

Sinnvoll ist es auch, zunächst mal mit MFile ein makefile zu erstellen, 
und das zum comöilieren zu benutzen.

Oliver

von Stefan B. (stefan) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hier Dein Quellcode und die im Simulator des AVR Studio funktionierende 
HEX-Datei für Atmega16 @ 11.0592 MHz. Bei 1 MHz sind die Blinkzeiten 
natürlich nicht 1 s sondern 11.0592 s.

von Tobias Neumann (Gast)


Lesenswert?

Hallo,
ich habe nun herausgefunden woran es damals gelegen hat. Es lag am 
Linker.. ich hab im Makefile nicht angegeben mit welchem Controller es 
der linker zu tun hat. Nachdem ich dann "LDFLAGS=-mmcu=atmega16" ins 
Makefile gepackt habe hat es dann funktioniert.

Danke nochmal für alle Hilfe!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.