Hallo
verwende einen Atmega 128 mit 16Mhz. Bei dem Stück Prg kommt es zu einem
ungleichmässigen Zeit bei an und aus. Teilweise wird sogar eine längere
Pause (1s) eingelegt. Verstehe leider nicht warum.
1
voidnibo_timer2()// Timer 1ms - 1000ms=1Sekunde
2
{
3
TCNT2=0;
4
OCR2=249;
5
TCCR2=(1<<WGM21)|(1<<CS21)|(1<<CS20);
6
TIMSK|=(1<<OCIE2);
7
}
8
9
ISR(TIMER2_COMP_vect)// wait1=1ms,
10
{
11
if(wait1<500)// Takt 1ms auf 10ms
12
{
13
wait1++;// erhöht um je 1ms
14
}
15
else// wenn dann ...
16
{
17
wait1=0;// setzt wait1 auf 0
18
signal_wait1=0xFF;// Signal alle 10ms
19
}
20
}
21
22
habeschoneinigesprobiert
23
24
while(1){
25
26
if(signal_wait1==0xFF)
27
{
28
//cli();***
29
signal_wait1=0;
30
//sei();***
31
leds_set_status(1,5);/* Led5 soll 5sek lang rot sein */
32
}
33
34
35
if(signal_wait1==0xFF)
36
{
37
//cli();***
38
signal_wait1=0;
39
//sei();***
40
41
leds_set_status(0,5);/* Led5 soll 5sek lang rot aus sein */
42
}
43
}
44
return0;
45
}
Das Ziel ist es eigentlich ein Stück Prg zu haben, wie es als Beispiel
bei Johann steht. möchte mit signal_wait eine Pause machen ohne das Prg
zu stoppen ode in delay zu verzweigen. Vielleicht seht ihr mein Fehler.
danke
Hier (mit einer vernünftigen Formatierung sieht man es besser) ...
1
while(1){
2
3
if(signal_wait1==0xFF)
4
{
5
ledeinschalten
6
}
7
8
if(signal_wait1==0xFF)
9
{
10
ledausschalten
11
}
12
}
13
14
return0;
15
}
... hast du etwas, was man eine 'race condition' nennt. Schau dir die
beiden if an. Sie haben beide dieselbe Bedingung. D.h. abhängig davon,
wo deine Hauptschleife ganz genau steht, wenn der entscheidende
Interrupt kommt, wird einmal das obere if ausgeführt und einmal das
untere. Welches der beiden aber genommen wird, hängt von den exakten
Umständen innerhalb der Schleife ab. Mit einer kleinen Programmänderung,
und damit einem klitzeklein anderem Timing, kann sich das alles
umdrehen.
Das ist so, wie wenn du zu deinem Kumpel sagst:
2 Regeln:
* wenn die Sonne scheint, mach das Fenster auf
* wenn die Sonne scheint, mach das Fenster zu
Dann wird dir der sagen: "Ja was denn nu? auf oder zu? Du widersprichst
dir doch selber!"
Deinem µC hingegen ist das wurscht. Der hackelt stur seine beiden Regeln
ab, wieder und immer wieder, viele tausend mal in der Sekunde. Und je
nachdem wann genau die Sonne hinter einer Wolke hervorkommt prüft er
gerade die eine oder die andere Regel und führt dann auch
dementsprechend die Konsequenz (auf oder zu) aus.
Wenn dein signal_wait1 auf 0xFF geht, weißt du erst mal nur, dass 1
halbe Sekunde rum ist. Mehr nicht. Davon losgelöst ist dann die Aktion,
die passieren soll: Wenn die LED brannte, dann schaltest du sie aus.
Wenn sie ausgeschaltet ist, dann schaltest du sie ein.
1
while(1){
2
3
if(signal_wait1==0xFF)
4
{
5
signal_wait1=0;
6
7
if(ledistausgeschaltet)
8
ledeinschalten
9
else
10
ledausschalten
11
}
12
}
13
14
return0;
15
}
Und rück deinen Code ordentlich ein. Sonst wirst du immer Hilfe bei
seltsamen Logikfehlern brauchen, die du selber nicht siehst, weil dein
Code einfach nur unübersichtlich ist.
> ISR (TIMER2_COMP_vect) // wait1=1ms,> {> if(wait1<500) // Takt 1ms auf 10ms> ...> signal_wait1=0xFF; // Signal alle 10ms
Die Zahl 500 verstehe ich nicht, wenn ich die Kommentare betrachte.
Erst mal vielen Dank für Eure Hilfe, besonders Karl Heinz. Werde deine
Worte befolgen und es so machen, wie du es sagst.
Sorry wegen den Kommentaren. Habe einfach was rauskopiert und die
Kommentare drin gelassen. Eigentlich ist das meine Arbeitsroutine zum
testen der Programme oder Teile. Im Original steht 10 ms. Der Timer und
die ISR dienen zum Erzeugen von 10 ms Impulsen. Diese möchte ich nutzen
um entsprechende
ISR (TIMER2_COMP_vect) // wait1=1ms,
{
if(wait1<9) // Takt 10ms
{
wait1++; // erhöht um je 1ms
}
else // wenn dann ...
{
wait1=0; // setzt wait1 auf 0
signal_wait1=0xFF; // Signal alle 10ms
Verzögerungen zu schalten. Dies sollen im Prg genutzt werden um z.B. die
Entprellung zu machen. Besonders aber in einer Funktion von Johann um
delay zu ersetzen und damit Zeitverzögerungen zu umgehen. Es könne
dadurch auch verschiedene Zeiten gleichzeizig ablaufen. Es gibt ja schon
einiges in den einzelnen Artikeln. Bei Ihm sieht es so aus:
if(0==count.ms10.led1)
{
PIN_LED|=)(1<<PAD_LED1)
count.ms10.LED1=100
}
Habe den Artikel gerade nicht zur Hand. Das ist nur ein Teil da von.
Im Kommentar heisst es dazu:
Falls Countdown für LED1 abgelaufen ist, neu aufziehen auf 1 Sekunde und
toggle LED1
Was mir nicht gefällt, ist die Grösse der Datein und Anweisungen die
dazu nötig sind. Wenn ich den Timer für 10ms einmal aufrufe und die ISR
dazu nehm geht es doch auch kleiner und Einfacher (?). Das oberste Ziel
dabei ist eigentlich auch die Entprellung für verschiedene Zeiten zu
machen, so das ich mit einem Taster ein Menue bedienen kann. Aber alles
der Reihe nach.
achim
Hallo
Muss noch mal nachfragen. Habe das Prg so geändert, doch leider ohne
Funktion jetzt. Der Timer und ISR sind gleich beblieben,
while(1){
if (signal_wait1==0xFF)
{
signal_wait1=0;
}
if(PINC & (0<<PC5)) // Abfrage Eingang zu LED 5 Grün
{
leds_set_status(1,5); // setzt LED 5 Grün auf ein
}
else
{
leds_set_status(0,5); // schaltet LED 5 Grün auf aus
}
}
return 0;
}
Die LED 5 Grün liegt bei mir auf dem PC5
Irgend was mache ich wieder falsch. Habe mich an dein Vorbild gehalten.
Schau es dir noch mal an Karl Heinz. Hast du für die andere Sache auch
eine Idee.
Achim Seeger schrieb:> Hallo> Muss noch mal nachfragen. Habe das Prg so geändert
Du hast aber etwas ganz anderes programmiert, als das was ich dir da
oben gezeigt habe. Die {}-Klammern sind da nicht zum Spaß vorhanden,
sondern haben eine Bedeutung.
Hallo Karl Heinz
habe die Klammern weggenommen. Geht immer noch nicht
while(1)
{
if (signal_wait1 == 0xFF)
{
signal_wait1 = 0;
if(PINC&(0<<PC5)) // Abfrage PortC PC5 LED 5 Grün
leds_set_status(1,5); // schaltet LED 5 Grün auf ein
else
leds_set_status(0,5); // schaltet LED 5 Grün auf aus
}
}
return 0;
}
PINC & .. ist die Abfrage des Ports C PC5 auf 0. Was habe ich wieder
falsch gemacht?
achim
Hallo
in der Antwort von KH steht, "led ausgeschaltet". Diese LED 5 Grün liegt
bei mir am PC5. Welche Möglichkeit zur abfrage des Ports habe ich sonst
noch?
Es wird abgefragt ob der PC5 ausgeschaltet ist
if(PINC&(0<<PC5)) // Abfrage PortC PC5 LED 5 Grün
ist PC5 aus, wenn dann einschalten
leds_set_status(1,5); // schaltet LED 5 Grün auf ein
sost einschalten
else
leds_set_status(0,5); // schaltet LED 5 Grün auf aus
sorry, unklar
Achim Seeger schrieb:> Welche Möglichkeit zur abfrage des Ports habe ich sonst> noch?> if(PINC&(0<<PC5))
eine & (und) bedingung mit 0 ist immer 0. So kann die bedingung nie wahr
werden.
Überlegt doch mal wie man es abfragen würde?
Tip: normale auf "1" abfragen und das ergebnis negieren
Hallo
habe es jetzt so gemacht:
while(1)
{
if (signal_wait1 == 0xFF)
{
signal_wait1 = 0;
if(!PINC&(1<<PC5)) // Abfrage PortC PC5 LED 5 Grün
leds_set_status(1,5); // schaltet LED 5 Grün auf ein
else
leds_set_status(0,5); // schaltet LED 5 Grün auf aus
}
}
return 0;
}
Die Abfrage ist jetzt auf 1 und wird negiert. Geht aber trotzdem nicht.
Wie ist es mit den Klammern. In meinem C-Buch stehen für jede if und
else abfrage ein paar Klammern {} drin. Wieso werden diese hierbei nicht
gebraucht.
Achim Seeger schrieb:> Hallo> in der Antwort von KH steht, "led ausgeschaltet".
Und womit? Mit Absicht.
Ich wollte nämlich wissen, wie gut du deine Basics gelernt hast.
Ehe man irgendetwas anderes macht, wie zb Timer, ist es unabdingbar,
dass man die Grundlagen beherrscht. Diese Grundlagen sind:
* Wie setze ich einen Portpin auf 1?
* Wie setzt ich einen Portpin auf 0?
* Wie frage ich einen Portpin ab (sowohl auf 1 als auch auf 0)?
Bitmanipulation
Achim Seeger schrieb:> if(!PINC&(1<<PC5)) // Abfrage PortC PC5 LED 5 Grün
Operatoren Reihung!
Das hier wird als
( !PINC ) & ( 1 << PC5 )
gewertet. Das ist aber nicht das was du willst.
Du willst nicht, dass der Inhalt vom Pin Register logisch negiert wird
und dann mit einem & ein Bit herausgeholt wird. Du willst
* das Pin Register holen PINC
* mit einem & und einer Maske ein PINC & ( 1 << PC5 )
Bit ausmaskieren
* und dann das Ergebnis davon
(welches nur noch von diesem Bit abhängt)
logisch umdrehen !(PINC & ( 1 << PC5 ))
> Wie ist es mit den Klammern. In meinem C-Buch stehen für jede if und> else abfrage ein paar Klammern {} drin. Wieso werden diese hierbei nicht> gebraucht.
Weil dein Buch mies ist.
Das heißt, dein Buch ist nicht unbedingt mies. Grundsätzlich ist es
guter Stil diese Klammern auch dann zu machen, wenn sie eigentlich nicht
benötigt werden. Aber dein Buch sollte dir erklären, wie die Sache
wirklich ist (wenn es sich dabei um ein C-Lehrbuch handelt, was du nicht
ausdrücklich erwähnt hast)
Ausserdem war das nicht dein Problem.
Wenn du endlich mal deinen Code richtig einrücken würdest, würdest du
erkennen, dass zwischen ....
1
if(Bedingung_A)
2
{
3
mach_was;
4
}
5
6
if(Bedingung_B)
7
{
8
mach_was_anderes;
9
}
... und ....
1
if(Bedingung_A)
2
{
3
mach_was;
4
5
if(Bedingung_B)
6
{
7
mach_was_anderes;
8
}
9
}
ein Unterschied besteht, der sich auch durch die Einrückung optisch
zeigt. Im ersten Beispiel muss NUR Bedingung_B erfüllt sein, damit
mach_was_anderes ausgeführt wird. Das muss auch im zweiten Beispiel so
sein, aber zusätzlich muss im zweiten Beispiel auch noch Bedingung_A
erfüllt sein, weil die Abfrage nach Bedingung_B überhaupt nicht gemacht
wird, wenn Bedingung_A schon nicht erfüllt ist. Das zweite if ist ins
erste hineingeschachtelt! Die Einrückung zeigt das auch. Die { }
klammern Code! Der Codeteil innerhalb dieser Klammern
1
if(Bedingung_A)
2
{
3
....
4
....
5
....
6
}
wird nur dann, und zwar der komplette Codeteil, ausgeführt, wenn
Bedinung_A zutrifft. Und wenn dieser abhängige Codeteil 25
Bildschirmseiten lang ist, dann ist eben dieser 25-seitige Codeteil
davon abhängig und wird nur dann ausgeführt, wenn Bedingung_A wahr ist.
Und wenn da weitere if sich innerhalb dieses Blocks befinden, Schleifen,
Funktionsaufrufe, Datenbankabfragen, weitere Blöcke,
Feuerwerkszündungen, .... spielt alles keine Rolle. Der Block (so nennt
man das, wenn mehrere Codezeilen mittels einer umschliessenden { }
Klammerung zusammengebunden werden, wird nur dann ausgeführt, wenn
Bedingung_A zutrifft. Ist Bedingung_A nicht zutreffend, wird der
komplette Block überhaupt nicht in Angriff genommen sondern es wird zum
else, wenn es eines gibt, gegangen und dort die Ausführung fortgesetzt.
Gibt es kein else, dann geht die Codeausführung dann eben direkt nach
dem if weiter.
Und spätestens jetzt sollte klar sein, dass es natürlich auch zwischen
...
1
if(Bedingung_A)
2
{
3
mach_was;
4
5
if(Bedingung_B)
6
{
7
mach_was_anderes;
8
}
9
else
10
{
11
jag_den_Panzer_in_die_Luft;
12
}
13
}
... und ...
1
if(Bedingung_A)
2
{
3
mach_was;
4
5
if(Bedingung_B)
6
{
7
mach_was_anderes;
8
}
9
}
10
else
11
{
12
jag_den_Panzer_in_die_Luft;
13
}
... einen Unterschied gibt. Das eine mal gehört das else zur
Bedingung_B, das andere mal zur Bedingung_A. Der Panzer wird also unter
unterschiedlichen Voraussetzungen in die Luft gejagt.
Und weil das alles Unterschiede sind, die eine andere Programmlogik
bewirken, ist es überaus wichtig, dass man schnell und eindeutig
erkennen kann,
* wo ein Block anfängt
* wo ein Block aufhört
* und was sich alles innerhalb des Blocks befindet.
Und damit sind wir bei der Begründung, warum korrektes Code-Einrücken
nicht eine Frage der Code-Schönheit sondern eine Frage der
Fehlervermeidung ist. Wie du schon gesehen hast, gibt es 2 Arten von
Fehlern. Die einen sind Syntaxfehler, grob gesagt, wenn du dich nicht an
die Sprachregeln hältst. Dann klopft dir der Compiler auf die Finger.
Die anderen Fehler sind aber unangenehmer. Das sind die logischen
Fehler, wenn deine Programmlogik nicht stimmt. Da diese Logik aber
einzig und alleine dein Bier ist, bist du dafür verantwortlich, alles zu
tun, damit die Logik auch stimmt.
"Das U-Boot frühstückte durch den Bürosessel." ist ein völlig korrekter
deutscher Satz, der allen Grammatikregeln genügt. Trotzdem ist er
logisch gesehen unsinnig - unlogisch.
Ich verwende das Buch "C von A bis Z" von Jürgen Wolf. Hoffe das es das
richtige ist.
Noch was zu dem Artikel Bitmanipulatin. Habe den Artikel hier und vorher
durchgearbeitet. Steht viel drin, so mit Verschiebung und so, aber was
gerade such und brauche, Port Abfrage und setzen steht so nicht. In
einem anderen Prg von mir, geht das wunderbar mit der Abfrage eines
Einganges und weiteren Verarbeitung. Unterschied ist nur, das dort ein
Taster dran hängt und eine vereinfachte Abfrage Taster ist. Ich kann
auch mit den Port Befehlen Ausgänge setzen.
Muss halt weieter lesen. Werde erst das mal KH durcharbeiten.
Danke
Hallo
nach eueren letzten Hilfen habe ich das Prg in Funktion bekommen. Werde
weiterhin alles lesen was so da steht. Möchte es aber euch noch mal
zeigen. Man kann es sehr gut nutzen z.B. um einen Timer zu testen oder
für Einstellungen. Habe es auf 1Hz (2x0,5) gestellt im Timer.
while(1) // Beginn Hauptschleife
{
if (signal_wait == 0xFF) // Frage signal wait
{
signal_wait = 0; // signal wait = 0
if(!(PINC&(1<<PC5))) // Abfrage PortC PC5 LED 5 Grün
leds_set_status(1,5); // schaltet LED 5 Grün auf ein
else
leds_set_status(0,5); // schaltet LED 5 Grün auf aus
}
}
return 0;
}
Als Timer könnt ihr das obere Teil nehmen.
Zeig mal alles. Da gibt es sicherlich noch einiges zu verbessern.
Der erste Punkt, den ich anmäkeln möchte
1
if(!(PINC&(1<<PC5)))// Abfrage PortC PC5 LED 5 Grün
2
leds_set_status(1,5);// schaltet LED 5 Grün auf ein
Bei beiden Dingen handelt es sich konzeptionell um die gleiche Sache:
Den µC Pin an dem eine LED angeschlossen ist.
Das eine mal wird die Pin Abfrage direkt durch Zugriff auf das PINC
Register gemacht, das andere mal wird eine Hilfsfunktion benutzt, so
dass nicht mehr ersichtlich ist, welcher Pin da eigentlich manipuliert
wird.
Nicht besonders schön, zumal es zur Verwirrung beiträgt. Wenn man einen
Mechanismus benutzt (entweder direkte PIN/PORT Zugriffe oder
Hilfsfunktionen), dann sollte man das dann auch konsequent durchziehen.
@ Achim Seeger (achims)
>Noch was zu dem Artikel Bitmanipulatin. Habe den Artikel hier und vorher>durchgearbeitet.
Aber nicht verstanden. -> Noch einmal.
> Steht viel drin, so mit Verschiebung und so, aber was>gerade such und brauche, Port Abfrage und setzen steht so nicht.
Jaja, die gebratenen Tauben fliegen nicht in den Mund. Sowas auch. Und
mit logischem Denken ist das auch so eine Sache . . .
Von Grundlagen der C-Programmierung mal ganz zu schweigen. Ja, die
mussten wir uns alle erarbeiten.
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Eing.C3.A4nge_.28Wie_kommen_Signale_in_den_.C2.B5C.29
Hallo KH
stelle dir das Prg rein. Denke bitte daran, es ist eigentlich für einen
Nibo geschrieben, arbeitet mit dem 128 bei 16 Mhz. Falls es
Verbesserungen gibt, sehe ich keinen Grund etwas nicht zu ändern. Es
kann allerdings sein, das das Einrücken jetzt nicht so aussieht wie im
ori.
Bleibt aber noch mein zweites Problem. Der Timer und das Prg ohne delay.
Werde anschliessend dort weiter machen. Es lässt sich auch auf anderen
Plattformen einiges damit machen. Besonders die Kürze der Anweisungen.
Werde bestimmt damit noch mal zu dir kommen.
Hallo Falk, danke für deinen Himweis. Werde es annehmen und es noch
ausführlicher machen. Leider ist der Stoff teoretisch sehr trocken.
Bevorzuge daher die Version mit Prg und Irrtum. Nach dem Motto, eine LED
sagt mehr als tausend Worte.
Falls das Prg nicht richtig kommt, bringe ich es nochmal.
achim
@ Achim Seeger (achims)
>ausführlicher machen. Leider ist der Stoff teoretisch sehr trocken.
jain.
>Bevorzuge daher die Version mit Prg und Irrtum.
Das ist nicht sehr clever.
"Der Mensch hat dreierlei Wege, klug zu Handeln;
erstens durch Nachdenken, das ist das Edelste,
zweitens durch Nachahmen, das ist das Leichteste,
und drittens durch Erfahrung, das ist das Bitterste.
Konfuzius
chinesischer Philosoph und Staatsmann (551 v. Chr. - 479 v. Chr.)"
>Falls das Prg nicht richtig kommt, bringe ich es nochmal.
Dein Formatierung ist schlecht. Nutze nur echte Leerzeichen, keine
Tabulatoren. Schau es dir selber in der Codeansicht an.
MfG
Falk
Hallo Falk
habe mit die Codeansicht angesehen. Es ist das erste mal das ich hier
einen Code veröffentliche. Daher habe ich diese Erfahrungen noch nicht
sammeln können. Ich arbeite aber dran.
Ich kenne diese Aussage von Konfuzius. Leider gibt es eine Frage dazu,
die bis heute nicht beantwortet ist. Möchte auf keinen Fall etwas daran
zweifeln. Doch woher weiss er es? Hat er auch die selben Erfahrungen
gemacht wie andere oder ist er durch einfaches(?) Nachdenken zu dieser
Aussage gekommen. Mein Weg liegt irgendwo dazwischen. Ich denke über ein
Problem nach. Schaue wie es andere machen und sammle die Erfahrungen die
ich zum Nachdenken über ein Problem zur Lösung brauche. Es ist nicht
eleganteste, nicht der schnellste, nicht der leichteste, auch nicht der
bitterste Weg zur Erkenntnis, es ist aber ein Weg zur Lösung.
achim