Hallo zusammen ich versuche einen Ausgang in bestimmten Zeitabständen zu schalten (soll mal eine Steuerung für eine Heizung werden). Da ich absoluter Anfänger bin, habe ich ich zuerst mit einer einfachen Funktion mit entprechenden Delays angefangen. Das funktioniert auch. Jetzt bin ich dabei das ganze mit einem Timer+Interrupt zu realisieren. Sprache: C Controller: ATmega8 Entwicklungsumgebung: AVR Studio 4 + STK 500 Compilermeldungen: keine Da der Controller neben der Heizung später noch wesentlich mehr machen soll (PWM, Entpellung, LCD) möchte ich ein Sekundenflag erzeugen, auf welches dann verschiedene Funktionen in der Hauptschleife ihre Laufzeiten aufbauen können. Mein Programm ist im Anhang. Ich kriege es einfach nicht zu laufen (vielleicht ist es auch einfach zu spät :-). Über einen konstruktiven Hinweis wäre ich wirklich dankbar. Martin
Wozu ist das "return 0;" ? Wird damit die main() funktion verlassen ? Ich kanns nicht so gut lesen, weil die einrückungen nicht da sind, wie ichs gewohnt bin.
Ich habs mal zum Spass im Simulator laufen lassen. PB6 blinkt hübsch langsam vor sich hin... Sind die Fuses richtig gesetzt ?
wow bis 3 hab ich nicht durchgehalten :-) Wie gesagt ich bin ein absoluter Anfänger. Ich hab mir einen Leitz-Ordner voll Tutorials und das Datenblatt vom ATmega8 ausgedrucket und versuche mir das ganze jetzt selbst beizubringen. Das mit dem Return 0 hab ich irgendwo hier gelesen. Wenn ich es richtig verstanden habe, hat es damit zu tun, dass Int Main (void) einen Rückgabewert verlangt, auch wenn das durch die while-Schleife nie erreicht wird. Muss ich an den Fuses was einstellen?? Die erste Version mit Delays hat ja mal funktioniert ?! Wenn ich das Programm jetzt auf den Controller brenne leuchtet die LED dauerhaft... Kann man mit dem Studio 4 C-Programme simulieren? Das es bei dir im Simulator läuft heißt ja, dass ich gar nicht so weit weg vom Ziel bin. Martin
Mach' doch mal direkt in den Interrupt ein
1 | PORTB ^= 1<<PB6; |
rein und schau, ob es dann (schnell) blinkt bzw. flackert. Wenn nicht, hast Du möglicherweise irgendwo den falschen Microcontroller-Typ eingestellt, weil er gar nicht an der ISR vorbeikommt. EDIT: Die Zugriffe auf die LED in der Hauptschleife musst Du für diesen Test rausnehmen oder eine andere LED verwenden (sofern vorhanden).
Martin Löffler schrieb: > Das mit dem Return 0 hab ich irgendwo hier gelesen. Wenn ich es richtig > verstanden habe, hat es damit zu tun, dass Int Main (void) einen > Rückgabewert verlangt, auch wenn das durch die while-Schleife nie > erreicht wird. Das ist an dieser Stelle gar nicht der springende Punkt. Worauf Ohforf hinaus will: Rücke deinen Code ein! Dein Code hat eine logische Struktur. Diese Struktur lässt sich durch Einrückungen sichtbar machen! Damit erkennt man, welche Anweisungen innerhalb von Schleifen sind, welche Anweisungen von einem if abhängen usw. Die Optik eines Codes ist nicht Selbstzwecke, sondern ein wichtiger Bestandteil der Verstehbarkeit. vergleich mal damit
1 | int main (void) |
2 | {
|
3 | //PORTS
|
4 | DDRB = 0b00100000; //PortB = PB6->out |
5 | |
6 | //VARIABLEN
|
7 | uint8_t a=0; //Zählvariablen |
8 | uint8_t betrieb=5; //Variable Betrieb = Betriebszeit in Sekunden |
9 | uint8_t pause=3; //Variable Pause = Pausenzeit in Sekunden |
10 | |
11 | //Timer2 konfigurieren---------------------------------------------
|
12 | TCCR2 |= (1<<WGM21); //Timer Mode "Compare Match" |
13 | TCCR2 &= ~(1<<WGM20); |
14 | OCR2 = 194; //Compare Register mit 194 laden -> 5,008/s |
15 | TCCR2 |= (1<<CS20); //Timer startet mit Prescaler von 1024 = 976,56/s |
16 | TCCR2 |= (1<<CS21); |
17 | TCCR2 |= (1<<CS22); |
18 | TIMSK |= (1<<OCIE2); //CTC Interrupt freigegeben |
19 | |
20 | sei(); //Interrupts freigeben |
21 | |
22 | //Hauptschleife-----------------------------------------------------
|
23 | while (1) |
24 | {
|
25 | //Heizung
|
26 | if (secflag == 1) |
27 | {
|
28 | a++; |
29 | secflag = 0; |
30 | }
|
31 | |
32 | if (a <= betrieb) |
33 | {
|
34 | PORTB |= (1<<PB6); |
35 | }
|
36 | |
37 | if ((a > betrieb) && (a <= betrieb + pause)) |
38 | {
|
39 | PORTB &= ~(1<<PB6); |
40 | }
|
41 | |
42 | if (a > betrieb + pause) |
43 | {
|
44 | a = 0; |
45 | }
|
46 | }
|
47 | |
48 | return 0; |
49 | }
|
Anhand der Einrückungstiefe kann man ganz leicht erkennen, welche Teile zusammen gehören und zb im Falle eines if, von welcher Bedinung die Ausführung der Anweisungen abhängt. Jetzt sieht man auch auf den ersten Blick, dass das return nicht innerhalb der while Schleife steht, denn alles innerhalb der Schleife wäre eingerückt und das return ist das nun mal nicht. Will ich wissen, welche Teile innerhalb der Schleife sind, dann brauch ich nur von der { in derselben Spalte mit den Augen nach unten gehen, bis ich eine } in derselben Spalte finde. Alles dazwischen ist innerhalb der Schleife.
Hallo Herr Buchecker, danke für den Hinweis. So sieht es viel übersichtlicher aus. Gibt es eine Einstellung, damit der Editor das automatisch macht? Martin
Ich hab es zum laufen gebracht ! Mit dem Tip von Herr Zimmerer hab ich in der ISR eine zusätzliche LED invertieren lassen dafür hab ich PB2 genommen. Diese hat nach dem Brennen dann auch wunderschön geblinkt auf dem STK500. Dann habe ich versuchsweise mal in meinem ursprünglichen Programm PB6 gegen PB2 getauscht und .... es funktioniert ! Also entweder es stimmt was mit der PB6 LED auf dem STK nicht, oder es hat was mit dem Controller zu tun. Auf dem Datenblatt ist der PB6 eigentlich schon rausgefüht auf einen PIN ?! Auf jeden Fall hab ich mich 2 Tage und eine Nacht mit einem Problem rumgeschlagen, was eigentlich gar keins war... Danke für eure Hilfe. Martin PS. Im Anhang nochmal der jetzige Code (noch ohne Einrückungen). Ich hab die Timerinitalisierung noch etwas gestrafft.
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.