PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Interrupt - Problem mit Schreibzugriff auf globale Variablen



cipher
18.08.2008, 08:02
Hallo zusammen,

ich habe ein Problem mit einer Interruptroutine. Über einen Timer soll u. a. eine Zählvariable inkrementiert werden. Irgendwie funktioniert da leider nicht, der Wert der Variablen ändert sich nicht.

Ich habe das Programm mal auf folgendes Beispiel zusammenschneiden können, wobei der Fehler hier immer noch auftritt.



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

volatile char count = 0;

ISR(TIMER0_COMPA_vect) {
count++;
PIND = (1 << PD5);
}

int main(int argc, char **argv) {
// Hier wird Port D und Timer 0 initialisiert

sei();

// Timer 0 starten

while (1)
if (counter != 0)
PORTD |= (1 << PD6);
}
}


Der Timer 0 ruft alle 2.5 ms die obige Interrupt-Routine auf. Das kann ich auch mit meines Oszi am Pin PD5 schön verfolgen. Nur leider ändert sich an der LED am Pin PD6 nie etwas. Auch das Oszi zeigt keine Veränderung am Pin.

Compiliert wird das ganze mit AVR-GCC unter Debian Linux.

Kann mir jemand nen Tipp geben, woran's liegt, dass sich der Inhalt von counter nicht ändert? Ich seh grad die Bits vor lauter Bytes nicht mehr...


Danke und viele Grüße,

Markus

fhs
18.08.2008, 09:17
Hi,


1. "count" ist nicht gleich "counter"!
2. nach dem Setzen von PD6 mit "PORTD |= (1 << PD6);" änderst Du PD6 nicht mehr


Gruß

Fred

cipher
18.08.2008, 11:31
Sorry, Tippfehler. Sollte wirklich "count != 0" heissen.

Die Zeile "PORTD |= (1 << PD6);" stimmt so. Die LED an PD6 sollte angehn, wenn count einen anderen Wert als 0 einnimmt, was eigentlich nach 2.5 ms passieren sollte. Das tut's aber leider nicht, also muss ich davon ausgehen, dass count in der ISR nicht verändert wird.
Der Port ist übrigens richtig initialisiert. Wenn ich count initial auf 1 setze, geht die LED an.

fhs
18.08.2008, 11:50
Hi,

dann poste doch mal Deinen Code mit Initialisierung usw. (als kompilierbare Version). Du hast gesehen, dass Abtippen nur zu Fehlern führt -- also "copy&paste".

Gruß

Fred

cipher
19.08.2008, 07:28
Ok, ich hab gestern nochmal bisschen rumexperimentiert. Irgendwie bring ich das einfach nicht zum Laufen. Hier sit nochmal der vollständige und compilierbare Code:



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

volatile unsigned char count;

ISR(TIMER0_COMPA_vect)
{
PIND = (1 << PD5);
count++;
}

void init_port()
{
PORTD = 0x00;
DDRD = (1 << PD5) | (1 << PD6);
}

void init_timer()
{
// Timer 0
TCCR0B = 0x00;
TCCR0A = 0x02;
OCR0A = 0x32;
TCNT0 = 0;

// Interupt-Maske
TIMSK = 0x01;
}

void start_timer()
{
TCCR0B |= 0x03; // Timer mit 1:64-Prescaler starten
}

int main( int argc, char **argv)
{
count = 0;

init_timer();
init_port();
sei();
start_timer();

while( 1)
{
if( count != 0)
PORTD |= (1 << PD6);
}

return 0;
}


Soweit ich das sehe, sollte die LED an PD5 abwechselnd 2,5ms leuchten und dunkel sein, während die LED an PD6 nach 5ms an geht und auch an bleibt. Die LED an PD5 reagiert wie erwartet, nur die an PD6 bleibt dunkel. Scheinbar wird die Variable count, obwohl als "volatile" deklariert, in der ISR nicht verändert.

fhs
19.08.2008, 07:51
Hi,

da ich nicht weiß, welchen Prozessor Du einsetzt, habe ich Dein Programm mal für den Attiny2313 mit dem AVRStudio simuliert (kompiliert mit WinAVR Dez 2007). Bei F_CPU=4 MHz geht PD6 etwa 0.84ms nach Programmstart von L auf H; PD5 wechselt etwa alle 0.84ms.
Vielleicht hat Deine Entwicklungsumgebung einen Bug?
Bist Du Dir sicher, dass Du immer die neueste Version Deines Programms flashst?


Gruß

Fred

cipher
19.08.2008, 11:50
Controller ist ein ATtiny2313 bei 8 MHz.

An die möglichen Bugs in Hard- und Software hab ich auch schon gedacht und mal verschiedene Programme geschrieben, um den Fehler eingrenzen zu können. Soweit ich sagen kann, ist das Board und der Controller definitiv in Ordnung.
Seltsam ist, dass sich der Wert für count durch die ISR nicht ändern lässt. Wenn ich count in main() einen neuen Wert != 0 zuweise, geht die LED an PD6 an. Sind evtl. spezielle Kommandozeilenoptionen für gcc, avr-objcopy oder avrdude nötigt?

Programmiert wird das Ganze mit avr-gcc und avrdude unter Linux.

fhs
19.08.2008, 12:00
Wie gesagt: bei mir geht es (gcc Version Dez. 2007) mit dem Simulator des AVR-Studio (unter XP-SP2); "count" wird korrekt geändert und die Änderung in "main()" auch erkannt.

Ich hatte neben den unsigned/short/bitfield-Parametern nur die folgenden Optionen gesetzt:
-Wall
-Os
-gdwarf-2

Hast Du mal nach Bugreports für Deine Entwicklungsumgebung gesucht?

Gruß

Fred

Meldungen keim Kompilieren/Linken:
avr-gcc.exe -mmcu=attiny2313 -Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT cipher.o -MF dep/cipher.o.d -c ../cipher.c
avr-gcc.exe -mmcu=attiny2313 -Wl,-Map=cipher.map cipher.o -o cipher.elf
avr-objcopy -O ihex -R .eeprom cipher.elf cipher.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex cipher.elf cipher.eep || exit 0
avr-objdump -h -S cipher.elf > cipher.lss