Forum: Mikrocontroller und Digitale Elektronik Interrupts Programm wird unterbrochen warum?


von Sebastian -. (zettixzehner)


Lesenswert?

Hallo zusammen der angehängte Quelltext bereitet mir Kopfzerbrechen!

Ich möchte es gern möglich machen, dass Auf Knopfdruck die methode 
herunterfahren(); aufgerufen wird. das funktioniert auch, wenn ich das 
sei(); drin lasse also alle interrupts erlaube. Problem an der ganzen 
geschichte ist, dass alles was nach dem aufruf sei(); ist gar nicht mehr 
ausgeführt wird. werden da irgendwelche anderen Interrupts aktiv oder 
wie kann das kommen?

Meine Frage also wie kann ich es ermöglichen ab diesem Punkt wo das 
sei(); steht interrupts zu erlauben aber wenn kein interrupt kommt 
sollen die anderen unterprogramme ganz normal weiter ausgeführt werden?

Danke und lieben Gruß
1
ISR(INT4_vect)
2
{
3
  herunterfahren();
4
}
5
6
7
8
9
int main (void)
10
{
11
  
12
  
13
  DDRC=0xFF;
14
  PORTC=0x01;
15
  
16
  EICRB|=(0<<ISC41)|(0<<ISC40); 
17
  EIMSK|=(1<<INT4);
18
  
19
  DDRE=0x00;
20
  PORTE=0xFF;
21
22
  
23
  spannungsmessung();
24
  
25
  sei();
26
  spannungeinschalten();
27
  
28
  while(1)
29
  {
30
  spannungsmessung();
31
  }
32
33
  
34
}

von Karl H. (kbuchegg)


Lesenswert?

Sebastian -.- schrieb:

> Ich möchte es gern möglich machen, dass Auf Knopfdruck die methode
> herunterfahren(); aufgerufen wird. das funktioniert auch, wenn ich das
> sei(); drin lasse also alle interrupts erlaube. Problem an der ganzen
> geschichte ist, dass alles was nach dem aufruf sei(); ist gar nicht mehr
> ausgeführt wird. werden da irgendwelche anderen Interrupts aktiv oder
> wie kann das kommen?

Das kann daher kommen, dass bereits die Interruptbedingung aufgetreten 
ist und im entsprechend Interrupt-Requested Flag vermerkt wurde. Wenn 
dann Interrupts global freigegeben werden, wird dieser bereits vermerkte 
Interrupt dann abgearbeitet

von holger (Gast)


Lesenswert?

>Problem an der ganzen
>geschichte ist, dass alles was nach dem aufruf sei(); ist gar nicht mehr
>ausgeführt wird.

Wie ist dein Taster angeschlossen? Ändere deinen Interrupt mal
von Pegel auf Flanke.

von Sebastian -. (zettixzehner)


Lesenswert?

OKay das werde ich mal probieren das ist einfach ein taster auf dem 
DVK90CAN Board der North Taster und zieht den pin für den interrupt auf 
gnd!

von Sebastian -. (zettixzehner)


Lesenswert?

Hat sonst noch jmd. eine Idee woran es liegen könnte will das morgen 
endlich in den Griff bekommen :(

von Karl H. (kbuchegg)


Lesenswert?

Sebastian -.- schrieb:
> Hat sonst noch jmd. eine Idee woran es liegen könnte will das morgen
> endlich in den Griff bekommen :(

Wie schon gesagt, schau dir deine Init-Sequenz an und überleg wie 
sinnvoll die ist.
1
  EICRB|=(0<<ISC41)|(0<<ISC40); 
2
  EIMSK|=(1<<INT4);
3
  
4
  DDRE=0x00;
5
  PORTE=0xFF;
6
7
  
8
  spannungsmessung();
9
  
10
  sei();

du schaltest also zuerst den Interrupt ein, noch ehe der Pin auf Eingang 
und Pullup ist. Und da wunderst du dich tatsächlich, dass der Interrupt 
bei Low-Level am Pin feuert?

Das Interrupt System wird nicht erst mit dem sei() aktiv!
Der sei() ermöglicht nur, dass Interrupts auch abgearbeitet werden 
können. Aber registriert werden Interrupt Anforderungen ab dem Moment, 
ab dem du den Interrupt mit seinem Bit (in dem Fall INT4) aktivierst!

von Sebastian -. (zettixzehner)


Lesenswert?

Achso ist es so, dass der sich praktisch merkt dass der pin auf 0 war 
und dann später den interrupt ausführt? Egal ob ich den pin auf High 
gesetzt hab bevor alle interrupts erlaubt werden?

Also muss ich es so regeln, dass er bei einem Flankenwechsel von pos auf 
negativ reagiert und nicht bei einem Low Level richtig?

von spess53 (Gast)


Lesenswert?

Hi

Lösche doch einfach mal vor dem SEI() EIFR (0xFF reinschreiben).


>  EICRB|=(0<<ISC41)|(0<<ISC40);

Das ist nicht sehr günstig. Der Interrupt wird ständig ausgelöst solange 
der PIN L ist.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

Sebastian -.- schrieb:

> Also muss ich es so regeln, dass er bei einem Flankenwechsel von pos auf
> negativ reagiert und nicht bei einem Low Level richtig?

Nein.
Du musst die Reihenfolge in der du die Dinge aktivierst ändern.
Ist das wirklich so schwer zu verstehen, dass man sich zuerst vom Acker 
macht und erst dann den Bewegungsmelder einschaltet?

von Sebastian -. (zettixzehner)


Lesenswert?

Entschuldige, dass ich in der Richung was schwer von begriff bin!

Aber ich glaub so müsste das dann klappen oder
1
  DDRE=0x00;
2
  PORTE=0xFF;
3
4
  EICRB|=(0<<ISC41)|(0<<ISC40); 
5
  EIMSK|=(1<<INT4);
6
  
7
8
  
9
  spannungsmessung();
10
  
11
  sei();

Also erst den Port high setzen und dann Interrupt initialisieren dann 
klappts auch mit dem Low Level

von Karl H. (kbuchegg)


Lesenswert?

ALternativ kann man auch die Falschmeldung vom Bewegungsmelder 
rücksetzen, die der auswirft weil er die einschaltende Person beim 
weggehen registriert hat, ehe man die Auswertelogik in Gang setzt.

(Sprich: man kann auch das mitlerweile gesetzte Interrupt Flag in EIFR 
löschen, ehe man mittels sei() die Interrupt Bearbeitung generell 
freigibt.)

von Sebastian -. (zettixzehner)


Lesenswert?

Danke der Bewegungsmelder ist eine gelungene Demonstation für das 
Verständnis in der großen weiten AVR Welt ist das erste mal dass ich 
mich mit Interrups beschäftige bin sowieso erst seit knapp 2 monaten 
dabei mich mit µC zu beschäftigen.

Ich denke so komm ich nun weiter schönen Abend euch noch!

von Sebastian -. (zettixzehner)


Lesenswert?

Hallo hab mich heut nochmal versucht und hab nun vorher EIFR=0xFF 
gesetzt aber es klappt trotzdem nicht kann es denn sein,dass der durch 
irgend einen anderen Interrupt unterbrochen wird er geht auch nicht in 
das Unterprogramm herunterfahren wenn er unterbrochen wird sondern 
irgendwo anders hin.

Danke im Vorraus!
1
ISR(INT4_vect)
2
{
3
  herunterfahren();
4
}
5
6
7
8
9
int main (void)
10
{
11
  
12
    
13
  
14
  DDRC=0xFF;
15
  PORTC=0x01;
16
  
17
  DDRE=0x00;
18
  PORTE=0xFF;
19
  
20
  
21
  
22
    EICRB|=(1<<ISC41)|(0<<ISC40);
23
  EIMSK|=(1<<INT4);
24
  
25
26
  
27
  EIFR=0xFF;
28
  sei();
29
  
30
  
31
  
32
  spannungsmessung();
33
  
34
35
  spannungeinschalten();
36
  
37
  while(1)
38
  {
39
  spannungsmessung();
40
  }
41
  
42
  
43
}

von Sebastian -. (zettixzehner)


Lesenswert?

So hier mein gesamter Quellcode noch einmal ich komm einfach nicht mehr 
weiter! :(

das Problem ist nun dass die funktion spannung einschalten nicht mehr 
korrekt ausgeführt wird sonst funktioniert alles er bleibt dort einfach 
hängen und setzt Pin C2 nicht auf High!

Danke im Vorraus!
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
void herunterfahren(void)
6
{
7
  
8
  PORTA=0xF0;
9
  PORTC=0x03; //PIN C2 auf 0 setzen für 12V
10
  int y;
11
  
12
  for(y=0;y<1000;y++)  
13
    
14
    {
15
    _delay_ms(1); // Wartezeit starten bis 12V abgeschaltet
16
    }
17
  PORTC=0x01; //Pin C1 auf 0 setzen für 5V
18
  PORTC=0x00; //Pin C0 auf 0 setzen um Spannung für µC zu kappen
19
20
  while(1);
21
  
22
}
23
24
void spannungsmessung (void)
25
26
{
27
  
28
  unsigned int wert;
29
  ADMUX=(1<<REFS1)|(1<<REFS0)|(1<<MUX1);
30
  ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADIE);
31
32
  
33
    ADCSRA|=(1<<ADSC);
34
35
    while((ADCSRA & (1<<ADIF))==0);
36
37
    wert=ADCW;
38
    
39
    DDRA=0xFF;
40
    
41
    if(wert>856)
42
    {
43
      PORTA=0x01;
44
    }
45
46
    if(wert>876)
47
    {
48
      PORTA=0x03;
49
    }
50
51
    if(wert>896)
52
    {
53
      PORTA=0x07;
54
    }
55
56
    if(wert>916)
57
    {
58
      PORTA=0x0F;
59
    }    
60
61
    if(wert>936)
62
    {
63
      PORTA=0x1F;
64
    }
65
66
    if(wert>956)
67
    {
68
      PORTA=0x3F;
69
    }
70
71
    if(wert>976)
72
    {
73
      PORTA=0x7F;
74
    }
75
76
    if(wert>996)
77
    {
78
      PORTA=0xFF;
79
    }
80
81
    else if (wert<=856)
82
83
    {              
84
      
85
      herunterfahren();//Spannung zu gering daher abschalten!
86
87
    }
88
89
    
90
91
}
92
93
94
void spannungeinschalten(void)
95
{  
96
  
97
  PORTC=0x03; //Pin C1 auf 1 setzen für 5V
98
  
99
  int y;
100
  
101
  for(y=0;y<1000;y++)  
102
    
103
    {
104
    _delay_ms(1); //Wartezeit bis 5V eingeschaltet
105
    }
106
107
  PORTC=0x07; //PIN C2 auf 1 setzen für 12V
108
  
109
}
110
111
ISR(INT4_vect)
112
{
113
  herunterfahren();
114
}
115
116
117
118
119
int main (void)
120
{
121
  
122
  
123
  
124
  DDRC=0xFF;//Port C als Ausgang definiere
125
  PORTC=0x01; //Pin C0 auf 1 setzen für Selbsthaltung
126
  
127
  spannungsmessung();
128
  
129
  spannungeinschalten();
130
  
131
132
  DDRE=0x00;
133
  PORTE=0xFF;
134
  
135
  
136
  
137
    EICRB|=(1<<ISC41)|(0<<ISC40);// Interrupterkennung bei fallender Flanke
138
  EIMSK|=(1<<INT4);
139
  
140
  
141
142
143
  
144
  sei();
145
  
146
  
147
  while(1)
148
  {
149
  
150
  spannungsmessung();
151
  
152
  }
153
  
154
  
155
}

von Karl H. (kbuchegg)


Lesenswert?

Schmeiss mal die ganzen
1
  int y;
2
  
3
  for(y=0;y<1000;y++)  
4
    
5
    {
6
    _delay_ms(1); //Wartezeit bis 5V eingeschaltet
7
    }

raus und ersetz das durch
1
  _delay_ms( 1000 );

ist kürzer und zieht daher den Code nicht so sehr in die Länge. 
Ausserdem erhebt sich die Frage in wie weit sich die 16 Bit Arithmetik 
in der Ausführungszeitlich bei dir schon bemerkbar macht.

Weiters würde ich mir an einem Portpin eine LED anhängen und die 
benutzen um zu debuggen. LED ein ist ein guter Indikator, ob dein 
Programm an einer bestimmten Stelle vorbeikommt. Zb würde es dem Anfang 
von herunterfahren() gut tun, wenn da eine LED aufleuchten würde um zu 
sehen, ob die Funktion aufgerufen wird.

PS: grauslicher Code.
Irgendwo stimmts schon. Diejenigen mit dem grauslichsten und 
unübersichtlichstem Code sind auch diejenigen die immer die seltsamsten 
Fehler im Programm haben.
1
int main (void)
2
{
3
  
4
  
5
  
6
  DDRC=0xFF;//Port C als Ausgang definiere
7
  PORTC=0x01; //Pin C0 auf 1 setzen für Selbsthaltung
8
  
9
  spannungsmessung();
10
  
11
  spannungeinschalten();

Aha. Du misst also zerst, noch ehe du die Spannungen einschaltest. Und 
was macht spannungsmessung(), wenn es Unterspannung detektiert?
1
void spannungsmessung (void)
2
3
{
4
  
5
  ....
6
    else if (wert<=856)
7
8
    {              
9
      
10
      herunterfahren();//Spannung zu gering daher abschalten!
11
12
    }

Es fährt das System runter.

Ach nö. So macht das keinen Spass. Du hast doch die simpelsten 
Reihenfolgefehler. Es scheint so, als ob du dich in deinen eigenen 20 
Zeilen Code (die du unnötigerweise über 3 Bildschirmseiten verteilt 
hast) überhaupt nicht auskennst!

Räum erst mal den Code auf und achte auf Reihenfolgen! So ein µC ist 
doch kein Excel, welches sich selbst die richtige Reihenfolge aus den 
Fingern saugt.

Viele Leerzeilen hintereinander ziehen Code nur in die Länge, erhöhen 
aber nicht die Übersicht! Ganz im Gegenteil.
Einzelne Leerzeilen hingegen machen Sinn, wenn sie den Code in optische 
Blöcke aufteilen. Sobald jede 2te Zeile aber eine Leerzeile ist, haben 
sie ihren Sinn verloren.

Funktionen sollen das tun, was aussen drauf steht.
Deine Funktion 'spannungsmessung' misst die Spannung. Soweit so gut. 
Aber: sie wertet sie auch aus, steuert LEDs und und fährt auch das 
System runter. All das würde man nicht wirklich hinter einer Funktion 
spannungsmessung vermuten.

Namen: Sie sollen aussagekräftig sein. Schon richtig. Aber man soll auch 
nicht in der Länge des Funktionsnamens übertreiben! In deinem Code geht 
es um Spannungen. Was also wird wohl gemessen werden? Sicherlich nicht 
der Luftdruck. Das 'spannung' in 'spannungsmessung' ist also mehr als 
entbehrlich. Man läuft kaum Gefahr, dass man ein simples 'messen' 
missverstehen könnte.

von Sebastian -. (zettixzehner)


Lesenswert?

Ach meinst du ja?

die spnnung die gemessen wird geht an den ADC des µC der bekommt 
allerdings schon vorher spannung über die selbsthalteschaltung und die 
anderen spannungen sind spannungen auf einer extra platine, die 
geschaltet werden das spannungeinschalten ist also ein einschalten 
unterschiedlicher versorgungsspannungen nicht der betriebsspannungen!

Sorry aber ich fnde es kacke jmd runter zu machen der nach hilfe fragt 
und es ist ja auch nicht so dass ich mich nicht bemühe das programm 
funktioniert einwandfrei! Soviel dazu. Es geht lediglich um die 
geschichte mit den interrupts mehr habe ich nicht verlangt!

Und zum Delay so lange Delayzeiten funktionieren nicht korrekt! Sowas 
kann man berechnen findet man ja hier auf der Seite!

Das herunterfahren ist das herunterfahren der vorher geschalteten 
spannungen und zum schluss das kappen der selbsthaltung!

Hoffe das ist nun so zu verstehen! Deine Letzte Kritik war keine 
Konstuktive.

Das problem ist einfach, dass das mim interrupt läuft aber das programm 
einfach an der stell spannungeinschalten unterbrochen wird. Debugging 
funktioniert nur bis zu dieser stelle dann schmierts ab!

von MWS (Gast)


Lesenswert?

> Es geht lediglich um die geschichte mit den interrupts mehr habe ich
> nicht verlangt!
Dann schau mal in ein Ofenrohr, dann siehst Du ganz genau was Du 
verlangen kannst.

Ist ja wohl ein Witz, Karl Heinz müht sich wirklich manchmal bis zur 
Schmerzgrenze. Aber seine Zeit an einen unverschämten Nixblicker zu 
verschwenden, ist ja wie Perlen vor die Säue zu werfen.
Bildlich gesprochen selbstverständlich.

von Sebastian -. (zettixzehner)


Lesenswert?

Achso nun bin ich der Böse oder wie? Ich bemühe mich ja auch aber es 
kann halt nicht jeder alles so gut wie andere!

Und ich hatte den Quelltext ja vorher auch ohne unterprogramme gepostet 
da wurden mir vorschläge gegeben und ich bin wieder gescheitert so 
langsam weiß ich halt nicht mehr weiter! -.-

von MWS (Gast)


Lesenswert?

> da wurden mir vorschläge gegeben und ich bin wieder gescheitert so
> langsam weiß ich halt nicht mehr weiter! -.-

Du scheiterst auch, weil Du Ratschläge nicht annimmst, Karl Heinz hat 
schon ziemlich viel Ahnung davon, was er schreibt. Der Code wie gezeigt 
ist unübersichtlich und schaut grausam aus, da macht's auch Gutwilligen 
wenig Spass nach Fehlern zu suchen.

Und ansonsten helfen Dir andere Mitglieder weil oder wenn sie Lust 
haben, aber verpflichtet ist hier niemand zu gar nichts. Wenn Du also 
denkst Du kannst fordern, wirst Du hier am ausgestreckten Arm 
verhungern.

> Achso nun bin ich der Böse oder wie?
Weis nicht, ob das so zu bezeichnen ist, ich seh' daß Karl Heinz Dir 
(freiwillig) helfen will, und Du forderst wie er Dir zu helfen hat. Ist 
schon ein bisserl unverschämt.

von Lutz (Gast)


Lesenswert?

Sebastian -.- schrieb:
> Debugging
> funktioniert nur bis zu dieser stelle dann schmierts ab!
Geht es etwas konkreter?

Und komm' mal wieder runter. Die Tipps von Karl-Heinz passen schon ganz 
gut, finde ich. An Deinem Code ist wirklich nicht viel Gutes. Da must Du 
noch sehr viel dran machen.
Ich bin jetzt nicht inhaltlich in den Code eingestiegen, weil ich keine 
Lust habe, das Datenblatt zu wälzen, was z.B. gerade
> ADMUX=(1<<REFS1)|(1<<REFS0)|(1<<MUX1);
> ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADIE);
so bedeuten könnte. Dafür bieten sich Kommentare an.

> PORTC=0x03; //PIN C2 auf 0 setzen für 12V
Damit setzt Du exakt die Pins 1 und 2 des Port C auf 1.
> PORTC=0x01; //Pin C1 auf 0 setzen für 5V
ist schlicht gelogen.
Prinzipiell solltest Du Dir noch mal 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Ver.C3.A4ndern_von_Registerinhalten 
anschauen, das vermeidet vieles auch in der Zukunft. Also Register nicht 
nur mit "=" beschreiben.

Und bei der ganzen if-Arie solltest Du mal durchspielen, wie Dein Port 
Aabzappelt, wenn wert z.B. 980 ist. Der arbeitet alle if ab ...

von Sebastian -. (zettixzehner)


Lesenswert?

Ich schalte mit dem pin wo hinter steht 5V einen Transistor auf einer 
selbst erstellten paltine der kümmert sich ums schalten der 5V und dann 
einen adneren Transistor der die 12V schaltet! Und das Programm 
funktioniert ja auch soweit verbesserungen hin oder her sind ja schön 
aber ich würd halt ganz gern das problem mit den interrupts lösen denn 
da komm ich nicht weiter :( vielleciht war ich was aufbrausend. Wenn ja 
tuts mir leid vielelciht weil ich einfach dran verzweifel!

Gruß Sebastian

von MWS (Gast)


Lesenswert?

>  unsigned int wert;
>  ADMUX=(1<<REFS1)|(1<<REFS0)|(1<<MUX1);
>  ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADIE);

1<<ADIE ohne deklarierte ADC ISR schickt den µC in AVR GCC in's Nirvana.

> while((ADCSRA & (1<<ADIF))==0);
Funktioniert genau einmal (würde einmal funktionieren, wenn nicht: siehe 
oben), dann ist das Flag gesetzt und wird nicht mehr gelöscht. 
Normalerweise fragt man auf das ADSC Flag ab. Beim ADIF wird's nur 
funktionieren, wenn man es vor Start der Wandlung löscht.

von Sebastian -. (zettixzehner)


Lesenswert?

Meinst du damit kommt es dann zu einem Interrupt durch das ADIF Bit 
würde es helfen wenn ich es dann zurücksetze bevor ich den Programmteil 
verlasse?

Bei  Testen klappt die dauerhafet Spannungsmessung allerdings schließe 
eine Variable Spannungsquelle an und bekomme immer ne aktualisierte 
Ausgabe. Die dann auf Port A als LED Leiste ausgegeben wird ist ne 
Spannung zwischen ca.10,5V-12,2V die dort ausgegeben wird. Wird 
allerdings vorher per Spannungsteiler runter geteilt, damit die Referenz 
stimmt zu den 2,56V.

Wenn ihr wollt kann ich auch mal das gesamte Projekt Posten. Vielleciht 
ist es dann einfacher zu helfen wobei bei dem Rest ja keine Probleme 
aufgetaucht sind ausser halt bei der Software.

von Karl H. (kbuchegg)


Lesenswert?

Sebastian -.- schrieb:


> die spnnung die gemessen wird geht an den ADC des µC der bekommt
> allerdings schon vorher spannung über die selbsthalteschaltung und die
> anderen spannungen sind spannungen auf einer extra platine, die
> geschaltet werden das spannungeinschalten ist also ein einschalten
> unterschiedlicher versorgungsspannungen nicht der betriebsspannungen!

Oh. Verzeihung.
Das kann man natürlich aus dem Code alles so wunderbar auslesen. Das 
liegt daran, dass er so toll kommentiert ist
1
  PORTC=0x03; //Pin C1 auf 1 setzen für 5V

Ja genau. jetzt seh ich es auch. Wenn man 0x03 auf den Port schreibt 
(also einen Wert mit 2 mal 1 Bits) dann schaltet man die 5 Volt ein.
Völlig klar.

> Sorry aber ich fnde es kacke jmd runter zu machen der nach hilfe fragt
> und es ist ja auch nicht so dass ich mich nicht bemühe das programm
> funktioniert einwandfrei!

Na dann.
Wenn es einwandfrei funktioniert, wo ist dann das Problem?

> Soviel dazu. Es geht lediglich um die
> geschichte mit den interrupts mehr habe ich nicht verlangt!

Manchmal ist es aber mehr als nur 1 Fehler.
Und dann spielen viele Dinge zusammen.

Der AVR macht ja nicht aus Jux und Tollerei einen Interrupt Aufruf oder 
nicht (ob er einen macht oder nicht, wissen wir ja nicht. Du weigerst 
dich ja standhaft in die ISR einen Indikator einzubauen, der dir das 
verraten würde)

> Und zum Delay so lange Delayzeiten funktionieren nicht korrekt!

Sagt wer?
SChon mal in die Doku in delay.h hineingeschaut?

> Sowas
> kann man berechnen findet man ja hier auf der Seite!

Muss man nicht berechnen.
_delay_ms( 1000 )
funktioniert perfekt und bis auf ein paar Zerquetschte wartet es 1 
Sekunde lang. Wenn nicht, dann bring deine Tollchain mal auf den neusten 
Stand, denn dann muss sie schon mindestens 2 Jahre alt sein.

> Das herunterfahren ist das herunterfahren der vorher geschalteten
> spannungen und zum schluss das kappen der selbsthaltung!
>
> Hoffe das ist nun so zu verstehen! Deine Letzte Kritik war keine
> Konstuktive.

Ach?
Na wenn du meinst, dass ein Kraut und Rüben Programm einfacher zu 
verstehen und nachzuvollziehen ist ... ich kann es auch lassen mir in 
deinem Programm die Einzelteile zusammenzusuchen.

> Das problem ist einfach, dass das mim interrupt läuft aber das programm
> einfach an der stell spannungeinschalten unterbrochen wird. Debugging
> funktioniert nur bis zu dieser stelle dann schmierts ab!

Ein AVR schmiert nicht einfach ab. Der Simulator vielleicht, der ist 
auch nur ein Programm welches auf einem PC läuft und hat seine Fehler. 
Aber auf dem AVR musst du schon arg um Stack manipulieren oder Array out 
of bounds Zugriffe machen, damit so etwas ähnliches wie 'abschmieren' 
eintritt. Aber selbst dann schmiert er nicht ab. Er arbeitet weiterhin 
Befehle ab. Nur halt nicht die, die du vorgesehen hast.

von Sebastian -. (zettixzehner)


Lesenswert?

Okay mein COde ist nicht der übersichtlichste und nicht der schönste und 
das mit dem

PORTC=0x03 hab ich nur gemacht damit damit Pin C0 und Pin C1 auf 1 sind 
mittlerweile hab ich gelernt, dass es eleganter geht indem man eines 
einfach nur an die gewünschten stellen schiebt. Ich versuche ja mich zu 
bemühen habe gerade noch nen Ansatz gefunden werde es morgen mal 
ausprobieren und dann versuchen deinen Anweisungen nachzukeommen den 
Quellcode besser zu strukturieren und die if leiter so umzuändern, dass 
ich mit else if arbeite und nicht in jeden zweig hinein springe danach 
werde ich nochmal posten vielleciht würdest du ja dann nochmal 
reinschauen und dich besser zurecht finden und auch meinen Fehler 
finden. Entschuldige nochmal, dass ich so unhöflich war. Vielelciht eher 
ein Schrei nach Verzweiflung!

Danke schonmal im VOrraus!

Gruß Sebastian

von MWS (Gast)


Lesenswert?

> Meinst du damit kommt es dann zu einem Interrupt durch das ADIF Bit
> würde es helfen wenn ich es dann zurücksetze bevor ich den Programmteil
> verlasse?

Nein, aber Du hast den Ablauf des ADC nicht verstanden. Sobald die 
Wandlung fertig ist, wird das ADIF-Flag gesetzt. Du prüfst auf das 
ADIF-Flag und übernimmst das Wandlungsergebnis wenn es gesetzt wurde. 
Beim ersten Mal klappt das auch, aber bei der zweiten Wandlung bereits 
nicht mehr, denn das Flag wurde nicht gelöscht. Damit ist diese 
Anweisung:
while((ADCSRA & (1<<ADIF))==0);
ab da wirkungslos. Diese Anweisung sollte aber auf das Ende der Wandlung 
warten, es wird also nicht mehr gewartet und damit können falsche 
Ergebnisse eintreten.

Da Du nun auch noch das ADCSRA=...|(1<<ADIE) Bit gesetzt hast, springt 
der µC sobald das ADIF-Flag auf 1 steht in den ADC Conversion Complete 
Interrupt Vektor. Beim AVR GCC ist dort meines Wissens bei nicht 
deklarierter ISR ein Sprung auf den Resetvektor drin, das ist dann eine 
Endlosschleife zwischen ADC und Reset, und deswegen kommst Du über 
"spannungsmessung" nicht hinaus.

Um das mit dem ADIF-Flag zu machen, muss man es VOR der Wandlung 
löschen. Aber wie gesagt, jeder nimmt das ADSC-Flag, da dies auf 1 
steht, solange die Umwandlung im Gang ist, bei 0 ist das Ergebnis 
bereit.

von Karl H. (kbuchegg)


Lesenswert?

MWS schrieb:
>> Meinst du damit kommt es dann zu einem Interrupt durch das ADIF Bit
>> würde es helfen wenn ich es dann zurücksetze bevor ich den Programmteil
>> verlasse?
>
> Nein, aber Du hast den Ablauf des ADC nicht verstanden. Sobald die
> Wandlung fertig ist, wird das ADIF-Flag gesetzt. Du prüfst auf das
> ADIF-Flag und übernimmst das Wandlungsergebnis wenn es gesetzt wurde.
> Beim ersten Mal klappt das auch, aber bei der zweiten Wandlung bereits
> nicht mehr, denn das Flag wurde nicht gelöscht. Damit ist diese
> Anweisung:
> while((ADCSRA & (1<<ADIF))==0);
> ab da wirkungslos. Diese Anweisung sollte aber auf das Ende der Wandlung
> warten, es wird also nicht mehr gewartet und damit können falsche
> Ergebnisse eintreten.

Bei dem Glück das er hat, löscht er es tatsächlich

   ADCSRA|=(1<<ADSC);

löscht das Flag mit. (PeDa hat mich heute drauf aufmerksam gemacht).
Nicht das ich das trotzdem empfehlen würde. Das ist so versteckt, dass 
man es auch nach dem 5. mal Lesen nicht sieht.

>
> Da Du nun auch noch das ADCSRA=...|(1<<ADIE) Bit gesetzt hast, springt
> der µC sobald das ADIF-Flag auf 1 steht in den ADC Conversion Complete
> Interrupt Vektor.

Das ist allerdings übel.
Soviel zum Thema: Konzentriert euch auf den INT4, der Rest funktioniert 
ohnehin.

von MWS (Gast)


Lesenswert?

> Bei dem Glück das er hat, löscht er es tatsächlich
>    ADCSRA|=(1<<ADSC);
> löscht das Flag mit.

Stimmt, da auch das Flag wieder mit sich selbst ver-odert und mit 1 
gelöscht wird. Ist mir wieder eingefallen grad' wo ich's gelesen hab', 
denn es gab mal bei Bascom ein Problem damit.

>> Interrupt Vektor.
> Das ist allerdings übel.

Nicht nur übel, sondern tödlich :D

von Sebastian -. (zettixzehner)


Lesenswert?

Hallo zusammen wollt mich mal bei euch bedanken nun klappt alles und ich 
hab das Programm mal ein bisschen aufgeräumt bin allerdings noch nicht 
ganz fertig. Werds mal posten. Es lag tatsächlich am ADC hatte das nich 
ganz verstanden aber nun bin ich schlauer :)

Wenn das programm komplett geschönt ist werd ichs mal posten:)

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.