Forum: Mikrocontroller und Digitale Elektronik sei() - und das Programm läuft nicht


von Flo (Gast)


Lesenswert?

Hi,

wie kann es sein, dass mein Programm nach dem sei() Befehl nicht mehr 
rund läuft. Es wird nur noch die setup() funktion ausgeführt und das 
immer und immer wieder. Die Main while schleife wird nie erreicht. 
Simuliert in AVR-Studio. Ohne sei() funktionierts. Hab ich irgendwo 
ausversehen nen watchdog angeschalten und blicks nicht, oder???
1
int main(void){
2
3
setup();
4
5
while(1){
6
......
7
}
8
return 1;
9
}
10
*
11
*
12
void setup(void){
13
  DDRD = (1<<LEDPIN);
14
  DDRB = 0b00001111; // PB0-1-2-3 ausgang
15
  
16
  Armed = false;
17
18
  //timer0 (8bit) - run 62,5khz
19
  //used to get SumSig
20
  
21
  TCCR0 = (1 << CS02);  //Normal mode - prescalser clk/256
22
            //Overflow nach 4,096ms
23
  TIMSK |= (1<<TOIE0);      //overflow int en
24
  TCNT0 = 0;
25
  GICR = (1<<INT0);                       
26
  MCUCR = ((1<<ISC01)|(1<<ISC00));  //rising edge
27
28
  uart_init();
29
  i2c_init();
30
31
        sei();
32
  _delay_ms(2000);
33
  
34
}//setup

grüße Flo

von Simon B. (nomis)


Lesenswert?

Flo schrieb:
> wie kann es sein, dass mein Programm nach dem sei() Befehl nicht mehr
> rund läuft.

Du hast keinen Interrupt-Handler definiert.

Viele Grüße,
        Simon

von Michel (Gast)


Lesenswert?

Und wie sieht die ISR aus?

von jonas biensack (Gast)


Lesenswert?

genau, du schaltest den interrupt frei und hast keine ISR - Ergebnis: 
reset from controller.

von Flo (Gast)


Lesenswert?

DIe ISR stehen über der Setup funktion.
1
volatile unsigned char cSumSig[5];
2
volatile uint8_t channel=0,valid=0;
3
4
5
ISR(TIMER0_OVF_vect){
6
  channel = 0;
7
  valid=0;
8
}
9
ISR(INT0_vect){
10
  if(valid == 1){
11
    cSumSig[channel] = TCNT0;
12
    armed = cSumSig[channel];
13
    channel++;
14
    }
15
  else{
16
    valid=1;
17
    }
18
  TCNT0 = 0;
19
}

von jonas biensack (Gast)


Lesenswert?

mach mal return aus main raus, sollte zwar nichts verändern aber das ist 
unschön, den da gehen wir nicht raus...

von Flo (Gast)


Lesenswert?

return ist weg.

Nach der sei() hab ich auch noch 2 Zuweisungen stehen. Auch die werden 
direkt übersprungen.

von sei(); gehts direkt zu setup();

von Johann (Gast)


Lesenswert?

Junge, Junge. Du präsentierst hier kleckerlweise Dein Programm und 
erwartest tatsächlich, daß Dir jemand mit diesen Bruchstücken helfen 
kann?

von Flo (Gast)


Angehängte Dateien:

Lesenswert?

Ich dachte nicht dass der Rest des Codes was daran ändert wenn er eh 
auskommentiert war.
Aber vielleicht hilfts. Ich weiss nicht mehr weiter.

von Michael A. (Gast)


Lesenswert?

Warum hast du zwei Header für Interrupts mit eingebunden?
#include <avr\interrupt.h>
#include <avr/signal.h>

Durch den Compiler geht der Code immer noch nicht wegen fehlender 
Definition von GyroCalibrated, Armed und uart_init.h

von Michael A. (Gast)


Lesenswert?

Bei Freigabe mit  sei() steht schon der TIMER0_OVF Irq an. Das Programm 
hängt dan in der Timer0 Overflow ISR.

von Matt (Gast)


Lesenswert?

Es muss #include <avr/interrupt.h> statt #include <avr\interrupt.h> 
heißen.
Durch das falsche Include erzeugt ISR(...) keine ISR und beim ersten 
Interrupt, der Auftritt springt Dein COntroller ins Leere bzw. landet 
wieder am Programmanfang.

von Michael A. (Gast)


Lesenswert?

Matt schrieb:
> Es muss #include <avr/interrupt.h> statt #include <avr\interrupt.h>
> heißen.
Das ist ziemlich egal, sonst würde der Compiler heftig meckern 
(kommentier den Aufruf mal ganz raus).

von Ralf (Gast)


Lesenswert?

In der Timer-ISR kann man, glaube ich nicht hängenbleiben. Und wenn der 
Compiler eine Datei nicht findet, meckert er schon rum.

Aber, wie ist die Variante?:
Deine 2s-Wartefunktion ist ja aus einer Bibliothek. Also nicht im 
Quelltext enthalten. Bei der Ausführung von delay versucht der 
Simulaotor die Funktion zu finden. Geht nicht, also nimmt er irgendeine 
(ich glaube, die am weitesten hinten im Speicher liegt), und die zeigt 
er dann an. Warte mal ~500 "Sprünge zu Setup" ;-) , dann ist die 
Warteschleife abgearbeitet, die ständig durch die Timer-ISR unterbrochen 
wird.

P.S.:
Michael A. schrieb:
> Das ist ziemlich egal, sonst würde der Compiler heftig meckern

...war wieder mal zu langsam

von Simon B. (nomis)


Lesenswert?

Flo schrieb:
> DIe ISR stehen über der Setup funktion.
>
>
1
> volatile unsigned char cSumSig[5];
2
> volatile uint8_t channel=0,valid=0;
3
> 
4
> 
5
> ISR(TIMER0_OVF_vect){
6
>   channel = 0;
7
>   valid=0;
8
> }
9
> ISR(INT0_vect){
10
>   if(valid == 1){
11
>     cSumSig[channel] = TCNT0;
12
>     armed = cSumSig[channel];
13
>     channel++;
14
>     }
15
>   else{
16
>     valid=1;
17
>     }
18
>   TCNT0 = 0;
19
> }
20
>

Kann es sein, dass bei dem sei() direkt ein- bis mehrere INT0 anstehen? 
Darin wird dann munter "channel" inkrementiert, und das - soweit ich 
sehe - auch über 5 hinaus, d.h. wir haben u.U. eine Speicherkorruption.

Viele Grüße,
        Simon

von MitLeser (Gast)


Lesenswert?

vielleicht lässt auch das 2sec-Delay den Watchdog ansprechen.
Wird zwar nicht vom setup() initialisiert, aber was ist wenn die
"Watchdog Always On"-Fuse gesetzt ist?

von Michael A. (Gast)


Lesenswert?

Ralf schrieb:
> ... Warte mal ~500 "Sprünge zu Setup" ;-) , dann ist die
> Warteschleife abgearbeitet, die ständig durch die Timer-ISR unterbrochen
> wird.

Gutes Argument. Da hatte ich auch zu wenig Gedult mit dem Simulator...
Wenn man das 2s-Delay verkürzt sieht alles gut aus.

von Flo (Gast)


Lesenswert?

Danke für die Resonanz, aber:
alle vorschläge durchgemacht. Leider kein Erfolg. Jetzt hab ich ein 
neues Projekt erstellt, in dem ich meiner Meinung nach das gleiche 
Interrupthandling implementiert hab. Und hier funktionierts.

Es wird die while Schleife ausgeführt bis eben einer der gewollten 
Interrupts auftritt.

Wieder zurück ins alte Programm..... gleiches Lied. Kommt am setup(); 
Aufruf nicht vorbei. Seh ich den Wald vor Bäumen nicht, oder??

Testversion:
1
//Atmega32 16MHz
2
#include <avr\io.h>
3
#include <avr\interrupt.h>
4
#include <stdlib.h>
5
#include <inttypes.h>
6
#include <stdint.h>
7
8
volatile unsigned char cSumSig[5];
9
volatile uint8_t channel=0,valid=0;
10
11
12
ISR(TIMER0_OVF_vect){
13
  channel = 0;
14
  valid=0;
15
}
16
17
ISR(INT0_vect){
18
  if(valid == 1){
19
    cSumSig[channel] = TCNT0;
20
    
21
    channel++;
22
    }
23
  else{
24
    valid=1;
25
    }
26
  TCNT0 = 0;
27
}
28
29
void setRX(void){
30
  
31
  TCCR0 = (1 << CS02);  //Normal mode - pre clk/256 -->62,5khz
32
                        //Overflow nach 4,096ms
33
  TIMSK |= (1<<TOIE0);        //overflow int
34
  TCNT0 = 0;
35
  GICR = (1<<INT0);    //GIMSK
36
  MCUCR = ((1<<ISC01)|(1<<ISC00));  //rising edge
37
  sei();
38
}
39
40
void main(void){
41
  
42
  DDRD |= (1<<PD0);
43
  setRX();
44
45
  while(1){
46
    PORTD = PIND ^(1<<PD0);
47
    
48
  }
49
}

von Ralf (Gast)


Lesenswert?

Flo schrieb:
> Jetzt hab ich ein
> neues Projekt erstellt, in dem ich meiner Meinung nach das gleiche
> Interrupthandling implementiert hab.

Das ist der Unterschied:
Ralf schrieb:
> Warte mal ~500 "Sprünge zu Setup" ;-) , dann ist die
> Warteschleife abgearbeitet, die ständig durch die Timer-ISR unterbrochen
> wird.

Möglicherweise gravierend.
Und: Hat zwar nichts mit der Funktionalität zu tuen. Lass der 
Init-Funktion die Freude, sich schnell beenden zu können und mach das 
sei() in die main().

von Stefan E. (sternst)


Lesenswert?

Du bist uns immer noch den Code von uart_init() schuldig. Nicht 
unwahrscheinlich, dass dort der Fehler ist.

von Matthias (Gast)


Lesenswert?

Flo schrieb:
> Testversion:

Diese Version auf einen mega8 @3.6864 MHz gespielt mit PD2 als Ausgabe, 
schaltet alle 18.4 µs den Pin kurz auf low.

so well...

von Flo (Gast)


Angehängte Dateien:

Lesenswert?

Dann werd ich die uarts mal nachreichen. Glaub aber nicht, dass da ein 
Fehler drin ist. Hab ja nicht ich programmiert :)

Die sei() in die main oder wie in der Testversion in ne eigene RXinit 
rein werd ich heut Abend mal versuchen. Die 2 s Delay kann ich mir dann 
schenken!?
KLappt ja auch ohne warten...

von Stefan E. (sternst)


Lesenswert?

Flo schrieb:
> Dann werd ich die uarts mal nachreichen. Glaub aber nicht, dass da ein
> Fehler drin ist. Hab ja nicht ich programmiert :)

Ist es aber. Diese Zeile ist die Quelle deines Problems:
1
  UCSRB =~(1<<RXEN); // RX enable
Hier werden sämtliche UART-Interrupts erlaubt, und der UDRE-Interrupt 
löst dann sofort nach dem sei() aus. Und da es keine entsprechende ISR 
gibt, gibt es einen Software-Reset und dein Programm beginnt von vorn.

von Flo (Gast)


Lesenswert?

Das ists !!
MERKE: das nächste mal alles Posten. SORRY.

Aber ich dachte mit
1
UCSRB =~(1<<RXEN);
 wird nur der Empfänger Eingeschalten. Und nur mit setzen des RXCIE bzw. 
TXCIE werden die Interrupts angeschalten!?

Wenn ein Zeichen zu senden ist, wird ja hier
1
while(!(UCSRA & (1<<UDRE)))
gewartet bis der EMpfänger bereit ist. Das ist die Polling Methode,oder? 
Warum läuft während der Zeit der Timer1 weiter, aber der Timer0 nicht?

Ich dachte bisher, da der Timer0 OVF die höhere Priorität hat, dass die 
ISR auf jeden Fall ausgelöst wird während auf UDRE gewartet wird.

Muss ich statt
1
 while(!(UCSRA & (1<<UDRE)))
 - das Senden mit einer ISR handeln? Welchen Vektor muss ich da 
abfangen? USART _RXC | _UDRE | _TXC

grüeß FLo

von Flo (Gast)


Lesenswert?

Ach misst, des  =~ ist ja die Bitweise Invertierung.

Kopf --> Tisch

von Stefan E. (sternst)


Lesenswert?

Flo schrieb:
> Aber ich dachte mit
1
UCSRB =~(1<<RXEN);
> wird nur der Empfänger Eingeschalten.

Nein, diese Zeile setzt alle Bits in UCSRB auf 1 außer RXEN (und ist 
damit völlig sinnlos).

> Und nur mit setzen des RXCIE bzw.
> TXCIE werden die Interrupts angeschalten!?

Richtig, und genau das passiert in der Zeile.

> Das ist die Polling Methode,oder?

Ja.

> Warum läuft während der Zeit der Timer1 weiter, aber der Timer0 nicht?

Beide Timer laufen weiter.

> Ich dachte bisher, da der Timer0 OVF die höhere Priorität hat, dass die
> ISR auf jeden Fall ausgelöst wird während auf UDRE gewartet wird.

Die ISR löst auch während des Wartens aus (was aber nichts mit 
Proritäten zu tun hat). Oder versuchst du innerhalb einer anderen ISR zu 
senden?

von Flo (Gast)


Lesenswert?

Nein, das hab ich durcheinander gebracht. Prios sind ja nur bei 
paralellem auftreten der INT's wichtig.

Ich hoffe ja, dass es nur das aktivieren der UART interrupts war was 
mich die letzten 2 Tage geärgert hat.

Thx für die Unterstützung.

FLo

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.