Forum: Mikrocontroller und Digitale Elektronik Warum läuft mein Programm nicht?!


von Matthias K. (gidarrnmatze)


Angehängte Dateien:

Lesenswert?

Hallo ,
ich bins mal wieder...

Der Display geht genau bis zur Ausgabe "SERVUS UND HALLO"
und dann ist Ende....warum?! Auch wenn ich die Begrüßung weglasse
kommt die Zeit und Temperatur dann steht das Ding.

Das ganze soll zu einem kleinen Projekt werden:
Eine Giesanlage in der ich eine Pumpe über Uhrzeit und
Bodenfeuchte (kapazitiv) steuern kann.

Die Uhr allein funktioniert.
Die Temperatur über einen LM335. klappt auch für sich.
Die Bodenfeuchte auch, da bekomm ich eine schöne Frequenz(ist aber in 
diesem Programm noch nicht dabei)

Das geht mir etz schon aufn Keks :-) Warum klappt das ganze nicht?!
Ich bin echt geduldig aber wenn man ständig hängt ARGHHH :-)

Vielen Dank wenn ihr mir auf die Sprünge helft.
Grüße Matthias

von Gero N. (geronimo76)


Lesenswert?

jetzt mal grob drüber geschaut sehe ich sofort, das deine 
Interruptroutinen unvollständig sein ..

von der struktur her sollten sie so aufgebaut sein (habs mal eben aus 
meinem akt. projekt kopiert)
1
#pragma code high_vector=0x08
2
void MY_HIGH_INT (void)
3
  {
4
  _asm GOTO MY_HIGH_HANDLER _endasm
5
  }
6
7
#pragma code low_vector=0x18
8
void MY_LOW_INT (void)
9
  {
10
  _asm GOTO MY_LOW_HANDLER _endasm
11
  }
12
#pragma code
13
#pragma interrupt MY_HIGH_HANDLER
14
void MY_HIGH_HANDLER(void)
15
  {
16
        .... high interrupt routine ....
17
  }
18
19
/********************************************************/
20
/********************* L O W ****************************/
21
/********************************************************/
22
#pragma interruptlow MY_LOW_HANDLER
23
void MY_LOW_HANDLER(void)
24
  {
25
  .... low interrupt routine ...
26
  }

von Floh (Gast)


Lesenswert?

deine initTimer (die in init aufgerufen wird) enthält eine 
Endlosschleife.
Beabsichtigt?

von Michael (Gast)


Lesenswert?

Kurz überflogen. Im Timerinit ist ne while-Schleife der Form
1
while(1){
2
    /*Hier kann die aktuelle Zeit
3
      ausgeben werden*/
4
}

Dein Programm bleibt so natürlich im Init hängen, genauer im initTimer() 
;)

von Matthias K. (gidarrnmatze)


Angehängte Dateien:

Lesenswert?

Hallo

steinigt mich bitte nicht! :-)
Ich hab gerade das falsche hochgeladen. Tut mir leid..

Hab mal den PIN 2 in der ISR wackeln lassen das geht schon.
also der Timer scheint zu laufen.

von dr.schmock (Gast)


Lesenswert?

Wenn es ein 8-Bit-Controller ist, und unsigned int von 0 bis 255 zählt, 
dann wird die 1000 nie erreicht.
(weiß aber nicht wie "unsigned int" bei die definiert ist)

von dr.schmock (Gast)


Lesenswert?

...ich meinte natürlich die 1000 in
1
if(millisekunden == 1000)

von Karl H. (kbuchegg)


Lesenswert?

Wo ist Debounce_D0 ?

(Lass mal den ganzen Input-Teil weg, also eine möglichst einfache 
Hauptschleife:
1
    while(1){
2
      
3
      //******** Display und Counter aktualisieren ************  
4
      if ( sek_alt != sekunde ) {
5
        sek_alt = sekunde;
6
        lcd_ausgabe();
7
      }
8
    }


(Deine Kommemntare an dieser Stelle sind unsinnig und geben nur das was 
ohnehin im Code steht in mehr oder weniger denselben Worten wieder. Lass 
sie lieber weg, dann können sie wenigstens nicht falsch sein.)


Für Sekunde, Minute, Stunde solltest du einen unsigned char nehmen. Dann 
brauchst du dir auch um atomaren Zugriff keine Gedanken machen.

von Karl H. (kbuchegg)


Lesenswert?

dr.schmock schrieb:
> Wenn es ein 8-Bit-Controller ist, und unsigned int von 0 bis 255 zählt,
> dann wird die 1000 nie erreicht.
> (weiß aber nicht wie "unsigned int" bei die definiert ist)

kann nicht sein.
ein int hat immer mindestens 16 Bit. Das ist so normiert.

von Karl H. (kbuchegg)


Lesenswert?

>     TIMSK |= (1<<TOIE0); //Timer-Interrupt aktivieren

Wo ist die zugehörige ISR?

Wenn du einen Interrupt freigibst, dann MUSST du auch eine zugehörige 
ISR schreiben. Freigeben und keine ISR haben geht gar nicht.
(D.h. es geht schon. Nur führt das dazu, dass der Standardhandler einen 
Prozessor-Reset auslöst)


Ich denke, das ist dein eigentliches Problem.

von hans (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> kann nicht sein.
> ein int hat immer mindestens 16 Bit. Das ist so normiert.

wo ist das normiert?
also ich bin da der selben meinung wie dr.schmock und konnte eben auf 
die schnelle auch im c-standard nichts finden, was deine aussage 
unterstützt.

von Matthias K. (gidarrnmatze)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Wenn du einen Interrupt freigibst, dann MUSST du auch eine zugehörige
> ISR schreiben. Freigeben und keine ISR haben geht gar nicht.

Das wars..Volltreffer!
Vielen Dank!

eine Frage noch:
"(D.h. es geht schon. Nur führt das dazu, dass der Standardhandler einen
Prozessor-Reset auslöst)"

Ich habe in die Initi Funktion mal den PinWackler eingebaut
(das mag etz lustig klingen, aber so versuche ich immer Festzustellen 
wie weit das Programm geht):
PORTC ^= (1<<PC2);
mit dem Oszi hab ich erkennen können das der Pin auch dort hin und her 
wackelt.

Also ist es so zu verstehen das ich bis in die Init() gekommen bin dann 
er den Pinzustand geändert hat und dann im Timer sich quasi wieder 
resetet?
Sorry für meine Laienhafte Ausdrucksweise :-)

von Karl H. (kbuchegg)


Lesenswert?

hans schrieb:
> Karl Heinz Buchegger schrieb:
>> kann nicht sein.
>> ein int hat immer mindestens 16 Bit. Das ist so normiert.
>
> wo ist das normiert?

C Standard

> also ich bin da der selben meinung wie dr.schmock und konnte eben auf
> die schnelle auch im c-standard nichts finden, was deine aussage
> unterstützt.

Ich hab jetzt keinen C Standard bei mir. Es ist aber mit 100% Sicherheit 
festgelegt, dass ein int mindestens 16 Bit haben muss. Er kann größer 
sein, aber kleiner ist nicht zulässig.

von Karl H. (kbuchegg)


Lesenswert?

Matthias Kugler schrieb:

> Also ist es so zu verstehen das ich bis in die Init() gekommen bin dann
> er den Pinzustand geändert hat und dann im Timer sich quasi wieder
> resetet?


So ungefähr.
Das Programm ist soweit gekommen, bis der Timer seinen Overflow erreicht 
hat. Da du keine ISR hast, wurde alles resettet und das Programm hat 
wieder von vorne angefangen. Wieder und immer wieder

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:

>> also ich bin da der selben meinung wie dr.schmock und konnte eben auf
>> die schnelle auch im c-standard nichts finden, was deine aussage
>> unterstützt.
>
> Ich hab jetzt keinen C Standard bei mir. Es ist aber mit 100% Sicherheit
> festgelegt, dass ein int mindestens 16 Bit haben muss. Er kann größer
> sein, aber kleiner ist nicht zulässig.


Da ich auf die Schnelle kein frei zugängliches ISO C-Standard Dokument 
finden konnte, darf ich mir erlauben auf Wiki (ich weiß, Wiki kann man 
auch nicht alles glauben) zu verweisen

http://en.wikipedia.org/wiki/C_variable_types_and_declarations

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Karl Heinz Buchegger schrieb:
>
>>> also ich bin da der selben meinung wie dr.schmock und konnte eben auf
>>> die schnelle auch im c-standard nichts finden, was deine aussage
>>> unterstützt.
>>
>> Ich hab jetzt keinen C Standard bei mir. Es ist aber mit 100% Sicherheit
>> festgelegt, dass ein int mindestens 16 Bit haben muss. Er kann größer
>> sein, aber kleiner ist nicht zulässig.
>
>
> Da ich auf die Schnelle kein frei zugängliches ISO C-Standard Dokument
> finden konnte, darf ich mir erlauben auf Wiki (ich weiß, Wiki kann man
> auch nicht alles glauben) zu verweisen
>
> http://en.wikipedia.org/wiki/C_variable_types_and_declarations

Ah. Hab einen gefunden

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf
(Ist zwar nur ein Draft, allerdings von 2005. Diese Dinge sind aber seit 
Anbeginn von C immer gleich geblieben, waren also auch so schon in 
vorhergehenden Standards und wenn ich mich nicht sehr täusche schon im 
Ur-C von K&R schon mit dieser Konsequenz beschrieben.)

1
Seite 21. Clause 5.2.4.2 "Numerical Limits"
2
3
5.2.4.2.1 Size of integer types
4
5
1  ..... Their implementation-defined values shall be equal or greater
6
   in magnitude (absolute value) to those shown, with the same sign.

Also: die Limits müssen gleich oder größer sein, als die im Dokument 
gezeigten.

Welche sind
1
— minimum value for an object of type short int
2
      SHRT_MIN -32767 // −(2^15 − 1)
3
— maximum value for an object of type short int
4
      SHRT_MAX +32767 // 2^15 − 1
5
— maximum value for an object of type unsigned short int
6
      USHRT_MAX 65535 // 2^16 − 1
7
— minimum value for an object of type int
8
      INT_MIN -32767 // −(2^15 − 1)
9
— maximum value for an object of type int
10
      INT_MAX +32767 // 2^15 − 1
11
— maximum value for an object of type unsigned int
12
      UINT_MAX 65535 // 2^16 − 1

mit weniger als 16 Bits sind diese Limits nicht zu erreichen. Daher: ein 
int muss mindestens 16 Bit haben. Drunter geht nicht. Mehr ist möglich.


(und damit keine Missverständnisse aufkommen. Das Wörtchen 'shall' 
bedeutet in diesem Standard Dokument nicht, dass man es sich aussuchen 
darf, sondern es ist ein definitives 'das muss so sein')

von Rolf Magnus (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> (und damit keine Missverständnisse aufkommen. Das Wörtchen 'shall'
> bedeutet in diesem Standard Dokument nicht, dass man es sich aussuchen
> darf, sondern es ist ein definitives 'das muss so sein')

Das bedeutet es in Spezikfikationen eigentlich immer. Sonst müßte es 
auch "should" heißen. Aber auch das ist in der C-Norm explizit 
definiert:

4. Conformance
In this International Standard, ‘‘shall’’ is to be interpreted as a 
requirement on an implementation or on a program; conversely, ‘‘shall 
not’’
is to be interpreted as a prohibition.

von dr.schmock (Gast)


Lesenswert?

Das hier hatte ich vorhin in der Library Reference von Atmel gefunden:
1
typedef signed char   int8_t
2
typedef unsigned char   uint8_t
3
typedef signed int   int16_t
4
typedef unsigned int   uint16_t
5
typedef signed long int   int32_t
6
typedef unsigned long int   uint32_t
7
typedef signed long long int   int64_t
8
typedef unsigned long long int   uint64_t

definiert in der stdint.h

Interessant ist, dass eindeutige Typen wie "uint16_t" durch das 
"unsigned int" definiert ist, und nicht umgekehrt.
... also scheinen die ausdrücke "int", "long int" ... wohl wirklich der 
Standard für alle zu sein - so wie Karl-Heinz gesagt hat

von Karl H. (kbuchegg)


Lesenswert?

dr.schmock schrieb:

> Interessant ist, dass eindeutige Typen wie "uint16_t" durch das
> "unsigned int" definiert ist, und nicht umgekehrt.

Hat historische Gründe


ursprünglich gab es die ganzen uint16_t (und wie sie alle heißen) nicht, 
sondern nur int, long, unsigned, short int etc. etc.

Die Idee war, dass es den Programmierer gar nicht kümmern soll, wieviele 
Bits der jeweilige Datentyp hat. Er wusste: ein int geht auf jeden Fall 
von -32766 bis +32767 und das war alles was ihn interessieren sollte. 
Wenn jetzt es auf einer CPU so wäre, dass Integer Operationen mit 3 
Bytes schneller sind als solche mit 2 Bytes (konstruiertes Beispiel ich 
weiß), dann sollte der Compiler in der Lage sein, das auch nutzen zu 
dürfen, selbst wenn er damit 1 Byte zuviel rumschleppt. 'int' sollte 
sowas wie der 'Leib und Magendatentyp' der jeweiligen CPU sein. Erlaubt 
ist was gefällt und was für Dampf auf der CPU sorgt, solange es nur 
mindestens den Bereich -32766 +32767 abdeckt.


Das war auch alles schön und gut. Nur in der µC Programmierung ist man 
halt gezwungen, manchmal konkrete Bitzahlen vorzuschreiben. Auch beim 
Einlesen von binären Files oder überhaupt Datenkommunikation ist es eher 
hinderlich, wenn man keine konkreten Bitzahlen festgelegt hat.

Das hat dazu geführt, dass jeder Programmierer sein eigenes Süppchen 
gekocht hat, indem er sich einen Header ähnlich wie stdint.h aufgebaut 
und benutzt hat. Das Problem: Jeder hat natürlich seine eigenen Namen 
für die Datentypen erfunden.
Und um das abzustellen, hat man sich dann endlich im Normungsgremium 
erbarmt und dafür einen Standard-Header ins Leben gerufen.

von Rolf Magnus (Gast)


Lesenswert?

dr.schmock schrieb:
> Interessant ist, dass eindeutige Typen wie "uint16_t" durch das
> "unsigned int" definiert ist, und nicht umgekehrt.

Abgesehen davon, daß anfangs nur letztere gab, wäre das ungeschickt. C 
ist ja so ausgelegt, daß es auf möglichst viel - auch sehr exotische - 
Hardware abbildbar ist. Und da muß es einen uint16_t oder uint32_t nicht 
unbedingt geben, einen unsigned int aber schon (typisches Beispiel: Ein 
DSP, der alles auf 24-Bit-Basis rechnet).

> ... also scheinen die ausdrücke "int", "long int" ... wohl wirklich der
> Standard für alle zu sein - so wie Karl-Heinz gesagt hat

Spielt ja letztendlich auch keine Rolle. Der Compiler weiß, wofür er das 
Programm übersetzt und welche Größen er für diese Typen definiert hat, 
also ist es für ihn kein Problem, einen Header mitzubringen, der die 
passenden Typedefs enthält.

von Matthias K. (gidarrnmatze)


Lesenswert?

Ich wollt hier nochmal einhaken, da sich das ganze sehr interessant 
entwickelt.

ist es jetzt besser ich verwende

uint8_t statt unsigned char
uint16_t statt unsinged int
usw...
oder andersrum?

Wenn ich mir das durchlese ist es für C Programmierung auf uC besser ich 
verwende die uint8_t Bezeichnungen um mit konkreten Bitzahlen zu 
arbeiten?!

von Rolf Magnus (Gast)


Lesenswert?

Matthias Kugler schrieb:
> Ich wollt hier nochmal einhaken, da sich das ganze sehr interessant
> entwickelt.
>
> ist es jetzt besser ich verwende
>
> uint8_t statt unsigned char
> uint16_t statt unsinged int
> usw...
> oder andersrum?

Kommt drauf an, was du damit machen willst. uint*_t sollte man 
eigentlich nur benutzen, wenn es an dieser Stelle wichtig ist, daß der 
Typ exakt die angegebenen Bitzahl hat. Es gibt auch noch unit_fast16_t 
für einen möglichst schnellen Typ, der mindestens 16 Bit hat und 
uint_least16_t für einen möglichst kleinen Typ, der mindestens 16 Bit 
hat. Die wären eine gute Wahl an Stellen, wo die Größe nicht exakt 
stimmen muß, aber man eben auf Zeit oder auf Speicherplatz optimieren 
möchte. In der Praxis habe ich diese Typen aber bisher eher selten 
gesehen.

von Werner B. (werner-b)


Lesenswert?

Das hängt (wie immer) vom Einsatz ab.

Für einen Schleifenzähler der 0 bis 10 zählt ist (in der Regel) ein 
int oder unsigned int "optimal", da hier der Compiler den 
schnellsten internen Datentyp verwenden darf. Alternativ kann man noch 
etwas nachhelfen indem man den "schnellsten Datetyp" der mindestens n 
Bits breit ist "anfordert". Das ist in diesem Fall int_fast8_t oder 
uint_fast8_t. Damit darf sich der Compiler (oder besser gesagt, der 
Compilerentwickler) den schnellten Typ der diese Bedingung erfüllt 
aussuchen. Je nach Zielprozessor und Compilerhersteller kann dabei etwas 
anderes eingestellt sein. Was eben auf dieser Plattform am schnellsten 
ist. Auf dem AVR wird daraus zB ein 8-Bit char, auf einem i386 ein 
32-Bit int.

Anderersets hat du zB beim FAT Dateisystem Strukturen mit fest 
definierten Feldlängen. Hier für einen 16Bit Wert einfach unsigned int 
zu verwenden und für 32 Bit unsigned long mag auf dem einen System 
funktionieren, ist aber höchst unportabel, da unsigned int auf einer 
anderen Architektur oder Compiler auch 32 Bit breit sein darf. Darum 
nimmt man hierfür besser die Datentypen mit der fest definierten Länge.

Edit. da war Rolf wieder schneller ;-(

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.