Guten Abend zusammen, ich beschäftige mich nun seit ein paar Wochen mit der Programmierung in C. Einige Grundlagen habe ich bereits verstanden, vieles mit Sicherheit aber auch noch nicht. Nach einigen I/O Spielereien mit Copy&Paste auf dem Atmega8 habe ich nun erstmals ein kleines Programm komplett selbstständig erstellt. Ich würde mich freuen wenn mal jemand darüber schauen könnte. Es geht mir in erster Linie um Lesbarkeit und Formatierung. Ich denke es ist einfacher Fehler am Anfang zu beheben als wenn man schlechte Angewohnheiten über längere Zeit praktiziert und sie dann ändern möchte. Das Programm lässt sich Fehlerfrei im Atmel Studio compilieren und auch das Ergebnis auf dem Steckbrett ist genau das was ich mir Vorgestellt habe. Es werden zwei kleine Animationen auf vier 7-Segment LED Anzeigen ausgegeben. Als Ansteuerung dient mir ein Schieberegister und die Anzeigen sind 4:1 multiplex mit einer Refreshrate von 250Hz. Für mich ist das eine erste kleine Übung auf dem Weg zum LED-Cube. Ich finde lieber selber den Weg dahin als eine fertige Schaltung inkl. Code aus dem Internet zu benutzen. Beste Grüße Flo
Wenn du dir die ISR für den Timer nochmal genau anschaust, wird dir auffallen, das die Fallunterscheidung sich nur darin unterscheidet, das du in PORTC ein anderes Muster lädst:
1 | TCNT0=128; // Preload für Timer Interrupt 128 = 1ms |
2 | |
3 | switch(in) |
4 | {
|
5 | case0: // Digit 0 |
6 | {
|
7 | PORTC = LED_off; // Alle LEDs aus |
8 | SPDR = liveout[0]; // Daten fŸr Ebene 0 auf SPI ausgeben |
9 | while(!(SPSR & (1<<SPIF))); // warten bis Ÿbertragung beendet |
10 | PORTB &=~ (1<<RCK); // RCK Low |
11 | PORTB |= (1<<RCK); // RCK High - Daten werden in Register Ÿbernommen |
12 | PORTC = ebene_0; // LEDs fŸr ebene 0 an |
13 | break; |
14 | }
|
Du könntest also den Grossteil der Routinen gemeinsam machen und nur das Setzen des PORTC dann mit switch-case machen. Ausserdem ist es normalerweise keine gute Strategie, in einer ISR zu warten, bis irgendeine Übertragung fertig ist, sinnvoll wäre es z.B., am Ende der ISR das SPI zu starten und beim nächsten Durchlauf dann die dazugehörigen Ports zu setzen. > TCNT0=128; // Preload für Timer Schau dir dafür mal den CTC Modus des Timers an. Dann ist ein erneutes Laden des Timers unnötig und er wird ohne jeglichen Eingriff immer wieder nur bis zum gewünschten Wert zählen und dann den Interrupt auslösen. > PORTC = ebene_0; // LEDs fŸr ebene 0 an Für die Muster der Anzeige hast du schon ein Array gemacht, das kannst du ohne weiteres auch für die 'ebene' machen: const uint8_t ebene[5] = {0b11111110,0b11111101,0b11111011.. usw. In der ISR zählst du deine Variable 'in' hoch und greifst auf die ebene genauso zu, wie auf deine Muster,z.B. mit PORTC = ebene[in]. Dann kannst du dir das switch-case ganz sparen. Noch ein Tipp. Konstante wie die ebene und das Muster sind normalerweise im Flash Speicher am besten aufgehoben, dann kosten sie keinen wertvollen RAM und müssen zur Laufzeit nicht noch initialisiert werden. Dafür bietet avr-gcc das Attribut PROGMEM und die Funktionen pgm_read_byte(addr), pgm_read_word(addr) usw. Das kann z.B. so aussehen (Beispiel aus dem ersten erreichbaren Programmstückchen hier):
1 | const PROGMEM uint8_t expectedHallSequenceForward[8] = |
2 | {
|
3 | 0xff, 5, 3, 1, 6, 4, 2, 5 |
4 | };
|
5 | // und dann später
|
6 | startupcount = 0; // kann eine Zahl zwischen 0 und 7 sein |
7 | meinWert = pgm_read_byte(expectedHallSequenceForward+startupcount); |
Ansonsten sieht das doch schon ganz gut aus. Ich hatte hier mit deinen vielen Tabs vor den Kommentaren ein paar Umformatierungsproblemchen, aber das ist oft so und eine der Optionen, mit denen sich Programmierer seit Jahrzehnten beschäftigen (ist ein Tab nun 4 Spaces lang oder 8 oder was?).
> ist ein Tab nun 4 Spaces lang oder 8 oder was?
Deswegen benutze ich Tabs gar nicht mehr, sondern rücke mit Leerzeichen
ein. Die meisten Editoren können das automatisch umsetzen.
Hi, Ich möchte NUR hinzufügen: Einige dich auf eine einrücktiefe, (die meisten Editoren die sich so nenen dürfen können das in der Regel) Tutorials nie C&P machen (Außer du willst deine HW das erste mal testen, sollte man sowie so immer machen), beim Abtippen gleich SELBER gedanken machen was die Zeile bewirken soll. Dann ist das wie bei Radiowerbung, geht durch die Hand bleibt im Kopf. (Letzter Punkt ist Nicht expliziet für dich geschrieben sondern für andere Anfänger (wie mich, hab es früher auch so gemacht hat mir zwar schnelle erfolge gebraucht, aber habe auch viel zw. Zeitlich vergessen)) Sonst hatte ich keine Zeit genaueres zu lesen. MfG ich
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.