PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : kann globale variable nicht im interrrupt beschreiben



LittleBoy
17.08.2015, 10:18
Hallo Leute,
Ich will für den Nibobee ein Odometriesystem schreiben und stoße dabei auf ein kleines Problem:
Ich kann eine globale Countervariable nicht korrekt beschreiben.



// mit und ohne static, sowie auch ohne volatile negativ getestet
/*static*/ volatile unsigned int odometry_count_r=0;
/*static*/ volatile unsigned int odometry_count_l=0;

/* wenn etwas überläuft, wird das ausgeführt */
// mit und ohne volatile getestet
/*volatile*/ void ( * odometry_l_overflow)(void);
/*volatile*/ void ( * odometry_r_overflow)(void);


ISR(INT0_vect)
{
// u.U. muss man das nicht atomisch machen
// sei();
odometry_count_l++;
#ifdef __TEST
set_led(LED_L_Y,1);
_delay_ms(20);
set_led(LED_L_Y,0);
#endif
// eigentlich 0, da dann ein ueberlauf da ist, 3 zum testen.
if(odometry_count_l==3)
{
odometry_l_overflow();
}
reti();
}
// analog dazu vect1

void _init_odometrie(void)
{
GICR|= 1<<INT0;
GICR|= 1<<INT1;
MCUCR|= 1<<ISC01 | 1<<ISC00;
MCUCR|= 1<<ISC11 | 1<<ISC10;
sei();
#ifdef __TEST
// lauffeuer laesst leds der reihe nach blinken.
odometry_l_overflow=lauffeuer;
odometry_r_overflow=lauffeuer;
#else
odometry_l_overflow=nop;
odometry_r_overflow=nop;
#endif

#ifdef __TEST
_init_led();
#endif
}

void nop(void)
{
asm("nop");
}



Aber es wird nie odometry_l_overflow ausgeführt. Eigentlich sollte auch der Speicher nicht korrumpiert sein
und der Funktonspointer funktioniert auch. Die ganzen Led-Sachen sind nur da um zu sehen wann der Interrupt ausgelößt wurde.

Danke im Vorraus
LittleBoy

shedepe
17.08.2015, 10:59
Also ein paar Sachen:
1. Warum rufst du in einem Interrupt sei() auf.
2. reti() brauchst du wenn du mit einem Atmega arbeitest nicht. -> Hier wird sogar gesagt (http://cboard.cprogramming.com/c-programming/145134-returning-reti-another-function.html) dass das Programm dann crashen kann.
Siehe dazu auch: http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html#ga3b991e8168db8fc866e3 1f9a6d10533b

Ich vermute mal, dass es funktioniert wenn du reti() weglässt.

LittleBoy
17.08.2015, 11:57
Ja ok das reti() hat alles kaput gemacht.
Danke!
btw:
das sei() ist da, damit ich lange Prozeduren nicht atomisch ausführen kann.
Das wird dann per Variable ein und aus geschaltet.

shedepe
17.08.2015, 13:39
Das sei bewirkt in dem Interrupt absolut gar nichts. Wenn das System in den Interrupt gesprungen ist, dann sind die interrupts bereits aktiv.

LittleBoy
19.08.2015, 12:49
tja jetzt funktioniert es immer noch nicht so ganz:
ich habe zwei variablen eingefügt, die wie ein timer compare interrupt funktionieren sollen,
allerdings kann ich die nicht immer erfolgreich beschreiben:


static volatile unsigned int odometry_count_r=0;
static volatile unsigned int odometry_count_l=0;
// auch static getestet
volatile unsigned int odometry_comp_r=0;
volatile unsigned int odometry_comp_l=0;

/*wie gesagt compare */
void ( * odometry_l_comp)(void);
void ( * odometry_r_comp)(void);


ISR(INT0_vect)
{
odometry_count_l++;
#ifdef __TEST
set_led(LED_L_Y,1);
_delay_ms(20);
set_led(LED_L_Y,0);
#endif

if(odometry_count_l==odometry_comp_l)
{
odometry_l_comp();
}
}
void _init_odometrie(void)
{
if(add_mod(_MOD_ODO));
{
GICR|= 1<<INT0;
GICR|= 1<<INT1;
MCUCR|= 1<<ISC01 | 1<<ISC00;
MCUCR|= 1<<ISC11 | 1<<ISC10;
sei();
#ifdef __TEST
odometry_l_comp=lauffeuer;
odometry_r_comp=lauffeuer;
#else
odometry_l_comp=nop;
odometry_r_comp=nop;
#endif
// das wuerde funktionieren
// odometry_comp_l=5;
// odometry_comp_r=5;


}
}

// aus odtest.c

int main(void)
{
// funktioniert nicht.
odometry_comp_l=5;
odometry_comp_r=5;
//auch andersherum getestet
_init_odometrie();
while(1);
}





irgendwie kommt mir das komisch vor.
Danke in Vorraus
LittleBoy

seite5
19.08.2015, 22:55
hi,
hast Du die beiden Variablen im Modul odtest.c mit extern deklariert ?
mfg
Achim

LittleBoy
20.08.2015, 10:58
nein,
da ich die Variablen in odometrie.h definiert habe und in odotest.c mit `#include"odometrie.h"`
eingebunden habe, genauso wie in
odometrie.c, wo die Funktion `_init_odometrie()` drin ist.
Das ist das was mich ja so wundert.
lg
LittleBoy

Wsk8
20.08.2015, 12:07
Eine Variable im Header kann gar nicht funktionieren. Da würde ein normaler, funktionierender Compiler sofort melden, dass "multiple definitions" vorhanden sind und abbrechen.

Pack die Variablen als static ins source-file und implementiere Funktionen zum ändern.


inline void IncrOdoCount();
inline int GetOdoCount();
etc...

Dann hast du eine funktionierende, saubere und Design-konforme Lösung. Globale Variablen sind sch*****!!

mfg