Hallo, ich bin "Neuling" im Bereich µC Programmierung mit C. Ich programmiere schon seit längerem im Bereich Objective-C (iOS), aber wie mir scheint gibt's in diesem Bereich so einige Sachen, welche anders sind... Zum Beispiel habe ich mit folgendem Code meine Probleme, genauer gesagt mit dem IF Statement nach dem 1. IF. Im Simulator klappts, dann auf dem STK600 mit ATmega2560 nicht mehr - entweder habe ich einen Denkfehler oder das Board / MCU ist kaputt...??? Hier der Code: #include <avr/io.h> #include "stdint.h" volatile uint8_t counter; int main(void) { DDRB = 0b00000010; PORTB = (1 << PB1); while(1) { if(PORTB & (1 << PB1)) { if(counter < 5) // dieses if wird vom Board nicht "erkannt" { PORTB &= ~(1 << PB0); counter++; } else { PORTB |= (1 << PB0); } } else { PORTB |= (1 << PB0); counter = 0; } } } Gibts bei den IF Statements hier in C mehr zu beachten bzw. Besonderheiten? Vielen Dank schon mal im Vorraus! Grüße, Alex PS: Ich "lerne" mit dem AVR-GCC-Tutorial hier von Mikrocontroller.net.
Hallo Alex, beschreibe doch bitte erst einmal welche Reaktion du von dem Programm erwartest. Dass es im Simulator funktioniert könnte vielleicht daran liegen, dass du es dort Schritt für Schritt durchgehst, es auf dem Board dann aber alles viel schneller abläuft. Gruß André
Alexander F. schrieb: > Im Simulator klappts, dann auf dem STK600 mit ATmega2560 nicht mehr - > entweder habe ich einen Denkfehler oder das Board / MCU ist kaputt...??? Die Klammern sind nicht richtig eingerückt. Kein Wunder, dass das zu Unklarheiten führt.
Hallo André, ein Eingang gibt ein permanentes Signal zum einschalten, ein Motor wird aktiviert - dieser liefert Impulse zurück welche der µC zählen und nach X Impulsen den Motor wieder deaktivieren soll. Gruß, Alex
... schrieb: > Die Klammern sind nicht richtig eingerückt. Kann es aufgrund des Einrückens bzw. der Klammern zu fehlern führen??? if(1 == 1) { } else { } ODER if(1 == 1) { } else { } ODER if(1 == 1) { } else { } macht das in dieser Sprache einen unterschied?
Alexander F. schrieb: > if(PORTB & (1 << PB1)) Was soll das bezwecken? http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Zugriff_auf_IO-Ports
J.-u. G. schrieb: > Was soll das bezwecken? sorry, sollte natürlich PINB heissen... Ich hab diesen Beispielcode vom Original verkürzt...
Alexander F. schrieb: > sorry, sollte natürlich PINB heissen... PB1 wird als Ausgang definiert. Dieser wird vor der while-Schleife auf HIGH gesetzt und danach nie mehr angefasst. Demzufolge ist diese if-Abfrage sinnlos. Insbesondere wird nie der zugehörige else-Zweig erreicht und damit wird auch counter auch nie auf 0 zurückgesetzt.
J.-u. G. schrieb: > Alexander F. schrieb: >> sorry, sollte natürlich PINB heissen... > > PB1 wird als Ausgang definiert. ich sollte das was ich kopiere vorher definitiv genauer durchsehen... int main(void) { DDRB = 0b00000001; PORTB = 0b00000010; while(1) { if(PINB & (1 << PB1)) { if(counter < 5) { PORTB |= (1 << PB0); counter++; } else { PORTB &= ~(1 << PB0); } } else { PORTB &= ~(1 << PB0); counter = 0; } } } das sollte dann so korrekt sein?
Alexander F. schrieb: > Kann es aufgrund des Einrückens bzw. der Klammern zu fehlern führen??? Nein, nicht in C, wohl aber zu fehlendem Durchblick, der dann wiederum zu Fehlern führt. Oder die Forenleser so verwirrt, dass sie sich weigern, sich dem eigentlichen Thema zu widmen. Tipp fürs Posten: TABs sind hier sehr unpraktisch.
A. K. schrieb: > aber zu fehlendem Durchblick Ah gut, dann bin ich beruhigt. ^^ Ok, werde es beachten!
Woran erkennst du, dass das if nicht erkannt wird? Der µC ist so schnell, dass schon beim ersten Impuls bis 5 gezählt wird. Und die Zeit ist zu kurz, dass da irgend etwas sinnvolles am Motor passiert.
DirkB schrieb: > Woran erkennst du, dass das if nicht erkannt wird? Ich hatte vorhin eine LED als Ausgang geschalten und diese sollte, nach Betätigung eines Tasters und herunterzählen von ca. 1000 Schritten deaktiviert werden... Es passierte nichts, die LED ging nicht aus. (In der IF Abfrage hatte ich PINB verwendet) Vielleicht hatte ich heute einfach nur "den Wald vor lauter Bäumen nicht gesehen" oder das STK600 bzw. die MCU ist defekt... gg
Wie und wo hast Du counter deklariert? Bitte immer den exakten Code (mit
Copy+Paste) posten, sonst versäumst Du die Zeit allfälliger Foren-Helfer
mit unnötigen Tippfehlern
>herunterzählen von ca. 1000 Schritten
Wo sind denn diese 1000 Schritte zu sehen / zu finden?
1 | if(counter < 5) |
2 | {
|
3 | PORTB |= (1 << PB0); |
4 | counter++; |
5 | }
|
6 | else
|
7 | {
|
8 | PORTB &= ~(1 << PB0); |
9 | }
|
Der counter wird schneller auf 5 gezählt, als Dein Auge den LED-Blitz mitkriegen kann!
Peter schrieb: > Wie und wo hast Du counter deklariert? Der erste Code, den ich gepostet hatte...
1 | volatile uint8_t counter; |
Naja die LED sollte komplett erlischen da der Counter ja "voll" ist, erst nach loslassen des Tasters würde der Counter wieder auf 0 gesetzt werden...
Alexander F. schrieb: > Naja die LED sollte komplett erlischen Also in meinen eigentlichen Code sollte der Motor stoppen... in dem Beispielcode hier wollt ich auf das IF Statement bezug nehmen. Hier würde es ja tatsächlich nur kurz blitzen.
Alexander F. schrieb: > Ich hatte vorhin eine LED als Ausgang geschalten und diese sollte, nach > Betätigung eines Tasters und herunterzählen von ca. 1000 Schritten > deaktiviert werden... > Es passierte nichts, die LED ging nicht aus. (In der IF Abfrage hatte > ich PINB verwendet) 1000 Schritte? Mit einem uint8_t?
auf ein neues:
1 | #include <avr/io.h> |
2 | #include <stdint.h> |
3 | |
4 | #define MOTORSTEPS 10000
|
5 | |
6 | volatile int16_t stepCounter; |
7 | |
8 | int main(void) |
9 | {
|
10 | DDRA = 0xff; |
11 | DDRD = 0x00; |
12 | PORTD = 0xff; |
13 | while(1) |
14 | {
|
15 | if(PIND & (1 << PIND1)) { |
16 | if(stepCounter < MOTORSTEPS) { |
17 | PORTA |= (1 << PA0); |
18 | stepCounter++; |
19 | }
|
20 | else { |
21 | PORTA &= ~(1 << PA0); |
22 | }
|
23 | }
|
24 | else { |
25 | PORTA &= ~(1 << PA0); |
26 | stepCounter = 0; |
27 | }
|
28 | }
|
29 | }
|
Nach dem Upload auf das STK600 sind seltsamerweise alle Pins am PORTA (Ausgang) aktiv. Wenn ich dann PD1 betätige und wieder los lasse schaltet sich die LED kurz aus (wahrscheinlich die 10000 schritte lang). Entferne ich nun das IF Statment "if(stepCounter < MOTORSTEPS)" und ersetze es mit einem einfachen "PORTA |= (1 << PA0);" dann läuft alles normal, d.h. die LED an PA0 ist von Anfang an aus und wird erst bei Betätigung PD1 aktiv... Was ist hier falsch?
Was genau hängt bei dir am PD1? Dir ist bewusst, dass der Eingangspin vom STK600 mit Taster so funktioniert, dass er bei NICHT gedrücktem Taster eine 1 liefert (Bit ist gesetzt) und bei gedrücktem Taster dieses Bit eine 0 liefert. Will man also etwas tun, wenn ein Taster gedrückt ist, dann lautet die Abfrage if( !(PIND & (1 << PIND1) ) { // Taster PD1 ist gedrückt
Karl Heinz Buchegger schrieb: > Dir ist bewusst, dass der Eingangspin vom STK600 mit Taster so > funktioniert, dass er bei NICHT gedrücktem Taster eine 1 liefert (Bit > ist gesetzt) und bei gedrücktem Taster dieses Bit eine 0 liefert. Vielen Dank, das hilft mir ungemein weiter. War mir leider nicht bewusst... Kann es auch sein, dass die Ausgangsschaltung verkehrt ist??? PORTA &= ~(1 << PA0) = Ein PORTA |= (1 << PA0) = Aus
Alexander F. schrieb: > Vielen Dank, das hilft mir ungemein weiter. > War mir leider nicht bewusst... > > Kann es auch sein, dass die Ausgangsschaltung verkehrt ist??? > PORTA &= ~(1 << PA0) = Ein > PORTA |= (1 << PA0) = Aus Probiers doch einfach aus
1 | int main() |
2 | {
|
3 | DDRA = 0xFF; |
4 | PORTA = 0b11110000; |
5 | |
6 | while( 1 ) |
7 | ;
|
8 | }
|
welche LED leuchten? Die bei denen du ein 0-Bit gesetzt hast, oder die bei denen du ein 1-Bit gesetzt hast? Und schon hast du das selber rausgefunden.
Ja, Danke. Ich hatte gedacht ich hab einen Fehler im Code, anstatt zu wissen dass eben diverse Bits hierbei anders zu setzen sind...
Alexander F. schrieb: > Ja, Danke. > > Ich hatte gedacht ich hab einen Fehler im Code, anstatt zu wissen dass > eben diverse Bits hierbei anders zu setzen sind... Genau aus dem Grund beginnen alle Tutorien hier auf der Mikrocontroller-Website damit, dass erst mal einzelne Ausgänge auf 0 oder 1 gesetzt werden um LED zum Leuchten oder Nicht Leuchten zu bringen. Sie sind quasi das "Hallo Welt" der µC Szene mit dem Nebeneffekt, dass man rauskriegt was eine 0 oder eine 1 am Ausgabepin bewirkt. Es ist ja kein Naturgesetz, dass eine 1 etwas einschalten muss. Für den "nicht gedrückter Taster liefert eine 1" gibt es allerdings einen guten Grund. Im AVR gibt es nur Pullup Widerstände. Pullup bedeutet, dass ein offener Eingang damit auf 1 gezogen wird. Ein nicht gedrückter Taster ist aber so ein offener Eingang. Erst durch das Drücken des Tasters wird der Eingang mit irgend einer Spannung verbunden. Wenn ich aber nur einen Pullup habe und damit einen offenen Eingang nur auf 1 ziehen kann, dann bleibt für den Taster nicht mehr viel übrig als nach GND zu schalten. Und damit liefert dann ein gedrückter Taster eine 0 (weil der Taster den Eingang nach Masse verbindet) und wenn der Taster nicht gedrückt ist, dann zieht der Pullup-Widerstand den Eingang auf 1.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.