Hallo, ich habe ein C-Programm für Atmega 8 geschrieben, womit ich eine Art Uhr am LCD-Display Zeile 1 darstellen kann und Zeile 2 wechselweise den Zählerstatus eines Taster oder den Wert eines ADC anzeige. (Programm siehe Anhang, includiertes ADC.C als Kommentar im Programm unten angehängt) Leider habe ich mit diesem Programm ein Problem: es läuft nur kurz (mal 10sec, mal 1min und ein paar sec), aber nie länger. Weiß nicht warum und würde dazu eure Hilfe benötigen. Die Case sind drin, weil ich hier das Programm noch um verschiedene Funktionen erweitern will. Über eure Hilfe wäre ich wirklich sehr dankbar. Grüße Markus PS: Das AVR-GCC-Tutorial ist super
Argh, immer diese "ausführlichen" Fehlerbeschreibungen. Wie äußert sich denn das "läuft nur kurz"? Was passiert dann?
es bleibt einfach stehen, es passiert nix mehr. Dehr Inhalt des LCD-Displays ändert sich nicht mehr. Im Programm ist auch ein Blinklicht drinn. Auch diese hört dann auf zu blinken.
@ MarkusG (Gast) >es bleibt einfach stehen, es passiert nix mehr. Dehr Inhalt des >LCD-Displays ändert sich nicht mehr. >Im Programm ist auch ein Blinklicht drinn. Auch diese hört dann auf zu >blinken. Tjaaa, da sind einige Schnitzer drin. > while(1) > { > if (TIFR == (1<<TOV0)) Ganz gefährlich. Denn sobald EIN EINZIGES Bit in dem Register zusätlich gesetzt ist, wird die Bedingung nie wieder erfüllt. Du willst eher sowas machen if (TIFR & (1<<TOV0)) Siehe auch Bitmanipulation In alle Zweige teiler++ reinzuschreiben ist sinnfrei, zumal es damit teilweise doppelt ausgeführt wird. Das ist vermutlich auch der Grund, warum dein Programm komisch reagiert. Der Switch wird unsinigerweise rasend schnell und oft abgearbeitet. Der muss mit in die if() Abfrage des Timers! MFG Falk
Hallo Falk Brunner, viele Dank für deinen Hinweis mit der Bitmanupulation. Nachdem ich dies geändert habe, funktioniert das Programm tatsächlich wie gewünscht. Das ich in jedem case teiler ++; break; habe ist absicht, damit dieser nur jeweils einmal pro sec. ausgeführt wird.
@ MarkusG (Gast) >habe ist absicht, damit dieser nur jeweils einmal pro sec. ausgeführt >wird. Wird er auch so, wenn mans richtig macht. Und dein Programm ist noch falsch. Eher so.
1 | while(1) |
2 | {
|
3 | if (TIFR & (1<<TOV0)) |
4 | {
|
5 | // diese Routine wird alle 16384us aufgerufen
|
6 | // dies ergibt sich aus: 16Mhz=0.0625us
|
7 | // 8Bit-Timer: 0.0625us*8=16us
|
8 | // 1024 Prescaler: 16us*1024=16384us
|
9 | |
10 | TIFR |= (1<<TOV0); |
11 | teiler ++; |
12 | |
13 | // zaehlen Impulse PC1
|
14 | if (PINC & ( 1 << PC1)) |
15 | {
|
16 | if (!bin.hold) |
17 | {
|
18 | bin.hold = 1; |
19 | zaehler_1 ++; |
20 | }
|
21 | }
|
22 | else
|
23 | {
|
24 | bin.hold = 0; |
25 | }
|
26 | switch (teiler) |
27 | {
|
28 | case 11: // Aufruf 1* pro sec |
29 | // wechseln des Zusandes PORTD.6
|
30 | PORTD ^= (1<<6); |
31 | break; |
32 | |
33 | case 22: // Aufruf 1* pro sec |
34 | // lesen Analog Channel 0 (10Bit)
|
35 | adcval = ReadChannel(0); /* MUX-Bits auf 0b0000 -> Channel 0 -> PC0*/ |
36 | break; |
37 | |
38 | case 33: // Aufruf 1* pro sec |
39 | if ( sec % 2 ) // sek�nliche Abwechslung der Ausgabe |
40 | {
|
41 | // Ausgabe des ADC-Messwertes auf dem Display
|
42 | utoa( 4.8876 * adcval, buf, 10); // Messbereichsendwert: 5000mVolt, Aufl�sung 10Bit=1023 |
43 | set_cursor(0,2); |
44 | lcd_string("=>_____mVolt"); |
45 | set_cursor(0,2); // Spalte 2, Zeile 2 |
46 | lcd_string(buf); // write ADC-mV to display |
47 | }
|
48 | else
|
49 | {
|
50 | // Ausgabe des Zaehler PinC.1 auf dem Display
|
51 | utoa( zaehler_1, buf, 10); |
52 | set_cursor(0,2); |
53 | lcd_string("=>_____Zaehler1"); |
54 | set_cursor(0,2); // Spalte 2, Zeile 2 |
55 | lcd_string(buf); // write ADC-mV to display |
56 | }
|
57 | break; |
58 | |
59 | case 44: // Aufruf 1* pro sec |
60 | // Ausgabe des Timer 0 auf dem Display
|
61 | set_cursor(0,1); |
62 | lcd_string("________________"); |
63 | |
64 | utoa( sec, buf, 10); // convert uint to char |
65 | set_cursor(10,1); // Spalte 8, Zeile 1 |
66 | lcd_string(buf); // write ADC-value to display |
67 | |
68 | utoa( min, buf, 10); // convert uint to char |
69 | set_cursor(5,1); // Spalte 8, Zeile 1 |
70 | lcd_string(buf); // write ADC-value to display |
71 | |
72 | utoa( std, buf, 10); // convert uint to char |
73 | set_cursor(0,1); // Spalte 8, Zeile 1 |
74 | lcd_string(buf); // write ADC-value to display |
75 | |
76 | break; |
77 | |
78 | case 55: // Aufruf 1* pro sec |
79 | // wechseln des Zusandes PORTD.6
|
80 | PORTD ^= (1<<6); |
81 | break; |
82 | |
83 | case 66: // Aufruf 1* pro sec |
84 | // nun ist eine Sekunde vergangen
|
85 | // erh�he den Sekundenz�hler
|
86 | teiler = 0; |
87 | sec ++; |
88 | |
89 | if (sec==60) { |
90 | min ++; |
91 | sec = 0; |
92 | if (min==60) |
93 | {
|
94 | std ++; |
95 | min = 0; |
96 | }
|
97 | }
|
98 | }
|
99 | }
|
100 | return 0; |
101 | }
|
MFG Falk
OK, bin überzeugt. Vielen Dank für Eure Hilfen.
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.