ATmega16 Problem

Gast #1676641
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;
}
#1676673
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.
Gast #1676685
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!
Persönliche Seite #1676696
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)?
Persönliche Seite #1676707
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?
Gast #1676708
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.
Persönliche Seite #1676712
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.
#1676713
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.
#1676721
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.
Gast #1676722
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!
Gast #1676811
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!
#1676824
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...
#1676833
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
Gast #1676882
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?
#1676915
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
Gast #1676988
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
~
~
Gast #1676990
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
Gast #1677103
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
Gast #1697295
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!

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