Hallo, ich habe leider ein Problem mit meinem Code, und ich hoffe ihr
könnt mir helfen.
Hier mein code, copy/paste:
1
while(1){
2
Init();
3
4
if(RC1==1){
5
for(i=0;RC1==1;i++){/* solange RC0 == 1, i hochzählen... */
6
PutChar(0xAF);/* ...Ausgabe machen... */
7
__delay_ms(20);/* ...und 20ms warten */
8
}
9
PutChar(0xCE);
10
__delay_ms(20);
11
break;
12
}/* hier ist jetzt RC0 != 1, da for beendet ist */
13
14
if(RC0==1){
15
for(j=0;j==i;j++){
16
PutChar(0xAF);
17
__delay_ms(20);
18
if(j==i){
19
PutChar(0xCE);
20
__delay_ms(20);
21
}
22
}
23
break;
24
}
25
26
27
}
Nochmal genau was ich machen will:
Ich will in der ersten For-Schleife i solange höchzählen, bis die
Bedingung RC1 == 1 nicht mehr erfüllt ist. i hat ja danach den Wert des
aktuellen schleifendurchgangs, oder nicht?
In der zweiten schleife will ich, dass wenn die Bedingung RC0 == 1
erfüllt ist, eine weitere for-schleife genau an den selben Punkt
hinzählt, wie die schleife zuvor, also bis j == i, dann soll sie
abbrechen.
Nur funktioniert das ganze leider nicht, bzw. die variable i ist leer,
an was kann das liegen?
Hintergedanke ist der, dass ich einen Servomotor mit RC1 manuell
einstelle, und die Position mit RC0 wieder abrufen kann.
Vielen Dank im vorraus :)
Stefan H. schrieb:> for( i = 0; RC1 == 1; i++ ) { /* solange RC0 == 1, i> hochzählen... */> PutChar(0xAF); /* ...Ausgabe machen... */> __delay_ms(20); /* ...und 20ms warten */> }
Das ist entweder eine Endlosschleife oder wird gar nicht ausgeführt, da
RC1 nicht verändert wird.
Außerdem wird i immer nach dem Schleifendurchlauf inkrementiert, also
auch noch einmal bevor die Schleife abbricht,
Stefan H. schrieb:> for( j = 0; j == i; j++ ) {
Diese Schleife wird 0 oder 1x ausgeführt, je nachdem ob i==0 ist (dann
1x) sonst gar nicht. Das 2. Feld in "for" ist die Bedingung damit die
Schleife läuft, nicht abbricht.
PS: Würdest du deinen Code richtig einrücken, wäre er gleich viel
lesbarer.
> Nochmal genau was ich machen will:
Ich hab zwar nicht verstanden, wozu das ganze gut sein soll, aber:
> eine weitere for-schleife genau an den selben Punkt hinzählt, wie die> schleife zuvor, also bis j == i, dann soll sie abbrechen.
dann kann aber das hier
> for( j = 0; j == i; j++ ) {
nicht stimmen.
Die for-Schleife wird solange wiederholt, solange die Bedingung erfüllt
ist. Die Bedingung j == i ist aber höchst wahrscheinlich NICHT erfüllt.
Was du tatsächlich wolltest, ist, dass die Schleife solange wiederholt
wird, solange die beiden UNGLEICH sind. Mit jedem Schleifendurchlauf
wird j dann um 1 erhöht, solange, bis die beiden dann irgendwann gleich
sind.
a)
Dein Kommentar passt nicht zum Code
if ( RC1 == 1 ) {
for( i = 0; RC1 == 1; i++ ) { /* solange RC0 == 1, i
hochzählen... */
b)
> /* hier ist jetzt RC0 != 1, da for beendet ist */
Sicher nicht, denn hier ist RC1 != 1
c)
So programmiert man nicht.
i++ zählt ewig bis zum Überlauf wenn "RC1" nicht rechtzeitig !=1 wird
(keine Ahnung was RC1 ist, ein solches Flag des AVR kenne ich nicht,
aber es ist ja zu viel Mühe zu den Grundlagen der Frage was zu
schreiben)
Wie man es richtigerweise programmiert hätte, kann man ohne Kenntnis
nicht sagen aber maximal ein PutChar pro while(1) Schleifendurchlauf
klingt wie eine richtige Idee, welches Zeichen (und ob) dabei ausgegeben
wird würde man wohl mit einer state machine bestimmen.
Was versteckt sich eigentlich hinter RC1?
Das muss irgendein Makro oder sonstwas anderes sein. Denn wie sonst
könnte hier
1
for(i=0;RC1==1;i++){/* solange RC0 == 1, i hochzählen... */
2
PutChar(0xAF);/* ...Ausgabe machen... */
3
__delay_ms(20);/* ...und 20ms warten */
4
}
RC1 seinen Wert jemals ändern?
(Wenn ich mal davon ausgehe, dass PutChar keine globale Variable namens
RC1 verändert).
Achtung: Solche Abfragen auf 1 sind gefährlich! Je nachdem, was sich
hinter RC1 wirklich versteckt, solltest du es dir zur Gewohnheit machen,
die Dinge aus C Sicht zu sehen: Entweder etwas ist 0, oder es ist nicht
0. 1 ist zwar nicht 0, aber 5 ist auch nicht 0 - jedoch ist 5 nicht
gleich 1.
Eine Abfrage
if( PIND & ( 1 << PD4 ) )
wird dir zwar 0 liefern, wenn PD4 den Pegel 0 hat. Aber sie liefert dir
eben NICHT 1, wenn PD4 den Pegel 1 hat!
Ich habe das ganze schon auf einen uC gebrannt und es funktioniert auch
wie gewollt, nur eben die zweite forschleife nicht, in der ich zu dem
"abbruchpunkt" der ersten zählen will.
Dr. Sommer schrieb:> Das 2. Feld in "for" ist die Bedingung damit die> Schleife läuft, nicht abbricht.
ja, aber sobald die bedingung nicht mehr erfüllt ist, bricht die
schleife doch ab oder?
Ich habe mich übrigens vertippt, sollte
Stefan H. schrieb:> for( j = 0; j <= i; j++ )
heißen, funktioniert aber leider trotzdem nicht wie gewollt :(
Karl Heinz Buchegger schrieb:> Was versteckt sich eigentlich hinter RC1?
RC1 ist das zweite bit von Port C. Also einen Taster als eingangssignal.
Also wäre es besser immer RC1 != 0 bzw. RC1 == 0 schreiben?
PutChar ist lediglich eine funktion um einen char auf einen anderen PIC
zu übertragen.
> Hintergedanke ist der, dass ich einen Servomotor mit RC1 manuell> einstelle, und die Position mit RC0 wieder abrufen kann.
Die Idee scheint logisch zu sein. Aber die Implementierung passt nicht
so recht.
Mir fehlen da schon mal ein paar Variablen.
Da wird es eine Variable geben müssen, die aussagt
* wo steht der Servomotor zur Zeit - die aktuelle tatsächliche Position
* eine gespeicherte Position
Beim Anfahren der vorher gespeicherten Positione gibt es dann auch 2
Fälle: entweder die aktuelle POsition ist größer als die gespeicherte
Position - dann muss in die eine Richtung gefahren werden. Oder die
aktuelle Position ist kleiner als die gespeicherte Position - dann muss
in die andere Richtung gefahren werden. Oder aber als 3.ten Fall: die
aktuelle Position stimmt bereits mit der gespeicherten Position überein
- in dem Fall muss gar nichts gemacht werden.
Alles in allem sehe ich in deinem Code ein paar Schleifen. Aber nichts
davon geht auch nur ansatzweise in die Richtung, die du in deiner
textuellen Beschreibung als Ziel das ganzen genannt hast.
Wenn an PORTC.0 und/oder PORTC.1 ein Taster o.ä. hängt, dann ist die
Portkonfiguration <TRISC = 0x00> falsch - damit ist der gesamte PORTC
nämlich OUTPUT.
Stefan H. schrieb:> Karl Heinz Buchegger schrieb:>> Was versteckt sich eigentlich hinter RC1?>> RC1 ist das zweite bit von Port C. Also einen Taster als eingangssignal.
Dachte ich es mir doch.
> Also wäre es besser immer RC1 != 0 bzw. RC1 == 0 schreiben?
Lass den Vergleich überhaupt weg.
Jaaaaa! In C braucht es keinen Vergleich!. Das if
1
if ( ausdruck )
will lediglich einen Ausdruck haben. Irgendetwas, was einen numerischen
WErt liefert. Und dieser Wert wird darauf untersucht ob er 0 (logisch
falsch) oder nicht 0 (logisch wahr) ist. Mehr steckt da nicht dahinter
1
if(5)
ist ein perfekt gültiges C. 5 ist nicht 0 und daher logisch wahr. Daher
wird der if genommen.
Aber eigentlich sind das Grundlagen, wie fragt man Eingänge korrekt ab,
die du längst im kleinen Finger beherrschen solltest, ehe du dich an
reale Projekte wagst.
Stefan H. schrieb:> Ich habe mich übrigens vertippt, sollte>> Stefan H. schrieb:>> for( j = 0; j <= i; j++ )> heißen
Damit machst du dir hier ganz schnell keine Freunde mehr.
Tippe Code nicht ab - Copy&Paste den Code so wie er ist ins Forum. Hier
hat nämlich keiner Lust, Fehler für dich zu finden, die beim Abtippen
entstanden sind.
Bronco schrieb:> Ist das Absicht, daßInit();> regelmäßig aufgerufen wird?
Ja
Karl Heinz Buchegger schrieb:> Beim Anfahren der vorher gespeicherten Positione gibt es dann auch 2> Fälle: entweder die aktuelle POsition ist größer als die gespeicherte> Position - dann muss in die eine Richtung gefahren werden. Oder die> aktuelle Position ist kleiner als die gespeicherte Position - dann muss> in die andere Richtung gefahren werden. Oder aber als 3.ten Fall: die> aktuelle Position stimmt bereits mit der gespeicherten Position überein> - in dem Fall muss gar nichts gemacht werden.
Meine Steuerung funktioniert etwas anders: Wird ein Signal gesendet:
0xAF Bewegt sich mein Servo von der Anfangsposition so lange weiter, bis
0xCE gesendet wird. Liegt das Signal 0xAF zu lange an, springt der Servo
wieder zum anfang und läuft den weg erneut. Hintergedanke ist, dass die
Position, die er anfahren soll, durch eine zwet gesteuert wird, sprich:
Laufe 2,5sec vom anfang und bleibe da stehen. Kommt ein nächstes signal,
spring er zum anfang und läuft die nächste zeit.
Deshalb will ich schleifendurchgänge zählen, abspeichen und
wiederverwenden, sollten sie gebraucht werden.
Chris B. schrieb:> Wenn an PORTC.0 und/oder PORTC.1 ein Taster o.ä. hängt, dann ist die> Portkonfiguration <TRISC = 0x00> falsch - damit ist der gesamte PORTC> nämlich OUTPUT.
Das habe ich schon angepasst, war ein alter code aus einer Sicherung,
der rest stimmt aber überein.
Karl Heinz Buchegger schrieb:> Jaaaaa! In C braucht es keinen Vergleich!. Das if if ( ausdruck )> will lediglich einen Ausdruck haben. Irgendetwas, was einen numerischen> WErt liefert. Und dieser Wert wird darauf untersucht ob er 0 (logisch> falsch) oder nicht 0 (logisch wahr) ist. Mehr steckt da nicht dahinter> if( 5 )> ist ein perfekt gültiges C. 5 ist nicht 0 und daher logisch wahr. Daher> wird der if genommen.
Okay, das mit dem vergelich habe ich verstanden, aber ich will doch,
dass er das if ausführt, sobald der Port von low auf high schaltet, da
muss ich ihm doch sagen RC1.... sonst weiß der Controller ja nicht, was
er überprüfen soll oder?
Karl Heinz Buchegger schrieb:> Aber eigentlich sind das Grundlagen, wie fragt man Eingänge korrekt ab,> die du längst im kleinen Finger beherrschen solltest, ehe du dich an> reale Projekte wagst.
Wie schon damals gesagt, hab ich leider nur grundkenntnisse in Java und
habe vorher nur Konsolenprogramme für PC geschrieben..leider keine PIC
Karl Heinz Buchegger schrieb:> Tippe Code nicht ab - Copy&Paste den Code so wie er ist ins Forum. Hier> hat nämlich keiner Lust, Fehler für dich zu finden, die beim Abtippen> entstanden sind.
Okay, ich werde daran denken, habe es aber jetzt überprüft, keine fehler
mehr vom abtippen :)
Bronco schrieb:> Täusche ich mich, oder springst Du mit dembreak;> aus der Hauptschleife raus?
Ja, aber das ist gewollt.
Stefan H. schrieb:> Bronco schrieb:>> Täusche ich mich, oder springst Du mit dembreak;>> aus der Hauptschleife raus?>> Ja, aber das ist gewollt.
Denke ich nicht, weil dann bist du ja ausserhalb von while(1). also am
Ende von main.
>Das habe ich schon angepasst, war ein alter code aus einer Sicherung,>der rest stimmt aber überein.
Damit machst Du Dir genauso wenig Freunde. Wir wollen keinen alten Code
sehen, sondern den an dem Du aktuell arbeitest.
>Okay, das mit dem vergelich habe ich verstanden, aber ich will doch,>dass er das if ausführt, sobald der Port von low auf high schaltet, da>muss ich ihm doch sagen RC1.... sonst weiß der Controller ja nicht, was>er überprüfen soll oder?
Natürlich. Was Karl Heinz meinte, war, daß der Port-Wert selbst schon
ein Ausdruck ist und, falls das sinngemäß passt, auch als solcher
verwendet werden kann.
Die wesentliche Frage ist, was RC1, RC0 etc. jeweils als Wert annehmen
kann, falls am entsprechenden Pin eine 0 oder eine 1 anliegt. Ist der
Wert dann 0 oder RC1 oder 0x02 oder was? Falls eine der beiden
Alternativen 0 ist, dann reicht es if(RC1) zu schreiben. Für die
Wahrheit der Bedingung muss der Wert nur ungleich 0 sein. (Was Du
eigentlich wissen solltest).
Patrick B. schrieb:> Denke ich nicht, weil dann bist du ja ausserhalb von while(1). also am> Ende von main.
ja, aber die main startet ja wieder neu.
Habe es jetzt mal weggelassen und es funktioniert auch, whatever :D
hatte gedacht das muss so sein.
Patrick B. schrieb:> uint8_t i = 0;> uint8_t j = 0;>> while((RC1 != 0) && (i < 0xFF)){ // Schleife wird bei max 0xFF> abgebrochen> PutChar(0xAF);> i ++;> __delay_ms(20);> }>> if (( RC0 == 1 ) && (i > 0)){> for( j = 0; j <= i; j++ ) {> PutChar(0xAF);> __delay_ms(20);> if ( j == i ) {> PutChar(0xCE);> __delay_ms(20);> }> }> }
okay, ich habe das jetzt mal ausprobiert, einziges problem hierbei ist,
dass bei while nicht die stoppbedinung 0xCE gesendet wird, nachdem der
taster losgelassen wurde. Wie kann ich das hier noch einbauen?
1
while((RC1!=0)&&(i<0xFF)){// Schleife wird bei max 0xFF abgebrochen
2
PutChar(0xAF);
3
i++;
4
__delay_ms(20);
5
}
6
PutChar(0xCE);
7
__delay_ms(20);
8
if((RC0==1)&&(i>0)){
9
for(j=0;j<=i;j++){
10
PutChar(0xAF);
11
__delay_ms(20);
12
if(j==i){
13
PutChar(0xCE);
14
__delay_ms(20);
15
}
16
}
17
}
habe es jetzt so versucht und so scheint es zu funktionieren, nur ist
das maximum von 0xFF zu niedrig und i lässt sich nicht überschreiben,
muss dann erst den uC neu starten
Hmm schrieb:> Die wesentliche Frage ist, was RC1, RC0 etc. jeweils als Wert annehmen> kann, falls am entsprechenden Pin eine 0 oder eine 1 anliegt. Ist der> Wert dann 0 oder RC1 oder 0x02 oder was? Falls eine der beiden> Alternativen 0 ist, dann reicht es if(RC1) zu schreiben. Für die> Wahrheit der Bedingung muss der Wert nur ungleich 0 sein. (Was Du> eigentlich wissen solltest).
Okay, jetzt habe ich das verstanden :)
Stefan H. schrieb:> Patrick B. schrieb:>> Denke ich nicht, weil dann bist du ja ausserhalb von while(1). also am>> Ende von main.>> ja, aber die main startet ja wieder neu.
Ein großes dickes fettes AUTSCH!
Nein, genau das willst du nicht!
Bei einem µC-Programm ist ein Neustart von main() wie ein Reset zu
werten. Genau das willst du nicht!
Die Hauptschleife in main() wird nicht verlassen. Die komplette
Programmlogik spielt sich innerhalb dieser einen Endlosschleife ab. Wenn
der µC da jemals rauskommt, dann ist das eine Fehlersituation und der µC
muss im Grunde rebootet werden - d.h. Neustart bei 0. Alles zurück in
den Grundzustand, retten was zu retten ist und zusehen, dass man das
ganze Werkl entweder aus der momentanen Situation weiterfahren lassen
kann (was oftmals nicht so einfach ist), oder eben: alles zurück in den
Grundzustand und alles beginnt von vorne bei 0
Karl Heinz Buchegger schrieb:> Nein, genau das willst du nicht!> Bei einem µC-Programm ist ein Neustart von main() wie ein Reset zu> werten. Genau das willst du nicht!
Okay, wieder etwas gelernt, werde das in zukunft nicht mehr machen :)
Stefan H. schrieb:> Patrick B. schrieb:>> Denke ich nicht, weil dann bist du ja ausserhalb von while(1). also am>> Ende von main.>> ja, aber die main startet ja wieder neu.> Habe es jetzt mal weggelassen und es funktioniert auch, whatever :D> hatte gedacht das muss so sein.
Das gute an einem Microcontroller ist, daß es ein deterministisches
System ist: Alles, was passiert, passiert aus einem Grund ;)
Wenn man den Grund versteht, versteht man auch, was passiert.
Wenn man nicht versteht, warum etwas passiert, ist es durchaus
wissenswert, warum es passiert!
Stefan H. schrieb:> Karl Heinz Buchegger schrieb:>> Nein, genau das willst du nicht!>> Bei einem µC-Programm ist ein Neustart von main() wie ein Reset zu>> werten. Genau das willst du nicht!>> Okay, wieder etwas gelernt, werde das in zukunft nicht mehr machen :)
Es hat schon seinen Sinn, warum die µC-Programmierungstutorials mit
banalen LED, ein- ausschalten von LED, kleine Lauflichter, einfache
Tasterproblemstellungen etc. anfangen.
Ein Überspringen dieser Grundübungen spart einem KEINE Zeit, sondern
verlängert die Lernzeit, weil man eben die ganzen Grundtechniken nicht
lernt.
Stefan H. schrieb:> Okay, wieder etwas gelernt
Ich hätte da auch noch was zum Thema "Lernen":
1
for(i=0;RC1==1;i++){/* solange RC0 == 1, i hochzählen... */
Und wieder ein Beispiel für einen sinnlosen und falschen Kommentar:
Sinnlos, weil genau das selbe in der Sprache C gleich davor steht, und
Falsch, weil nicht RC0 abgefragt wird...
Kurz: lass solche Kommentare lieber weg, und schreib besser hin, was
du da machst (z.B. "Start-Taster abfragen"), nicht wie du es machst.
Denn wie du es machst steht da ja schon klar in C hingeschrieben...