Das Programm soll eine Spannung die durch eine Led gemessen wird und per AD Wandler umgewandelt wird per PWM eine andere LED dimmen, je nach Größe der Spannung. Die optische Led hängt an PC5. Die Led welche gedimmt werden soll an PB2. Kann jemand sagen welche Teile in diesem Programm nicht stimmen? Denn leider funtioniert es nicht... :-( #include <stdlib.h> #include <stdio.h> #include <avr/io.h> #include <avr/interrupt.h> #include <stdbool.h> void ad_init(void); void wandeln(void); void timer0(void); void initialisierung(void); void PWM(void); #define TEILER1 5000 //?????????????? #define TEILER2 5000 //?????????????? unsigned int softwareteiler1, softwareteiler2; unsigned int wert; bool Takt1 =0; bool Takt2 =0; int main(void) { initialisierung(); // ruft alle Initialisierungen auf while (1) // Endlosschleife { if (Takt1) { Takt1=0; wandeln(); } if (Takt2) { Takt2 = 0; PWM(); } } } // Timer0 initialisieren void timer0(void) { sei(); TCCR0B |= (1<<CS01); //Prescaler / 8 TIMSK0 |= (1<<TOIE0); } // Initialiserung AD-Wandler void ad_init(void) { PRR = 0x00; MCUCR = 0x10; ADCSRA |= (1<<ADEN); // A/D-Wandler Enable ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Prescaler auf 128 stellen ADMUX |= (1<<REFS0) | (1<<MUX2) | (1<<MUX0); // (AVCC als AREF + external C) (ADC5 = input) ADCSRB = 0x00; // Free runing mode DIDR0 = 0x3f; // Digital Input Disable Register } // Interrupt Routine Timer0 Overflow ISR (TIMER0_OVF_vect) { softwareteiler1--; if (softwareteiler1 == 0) { softwareteiler1 = TEILER1; Takt1 = 1; // Takt1 Flag = True softwareteiler2--; if (softwareteiler2 == 0) { softwareteiler2 = TEILER2; Takt2=1; // Takt2 Flag = True } } } // WANDELN void wandeln (void) { ADCSRA |= (1<<ADEN); // A/D Wandler einschalten // Dummy-Messung (eine Messung wird durchgeführt und dann verworfen) ADCSRA |= (1<<ADSC); // eine ADC-Wandlung while ( ADCSRA & (1<<ADSC) ); // Auf Abschluss der Wandlung warten wert = ADCW; // Dummy Messung wert = 0; ADCSRA |= (1<<ADEN); //Free Running Modus wir eingeschaltet ADCSRB |= 0x00; wert=ADCW; //Register wird ausgelesen und wert wird übergeben } //PWM void PWM(void) { DDRB = (1 << PB2 ); TCCR2A = (1<<COM2A1) | (1<<WGM21)| (1<<WGM20); TCCR2B = (1<<WGM22) | (1<<CS00); ICR1 = 0x00FF; OCR2A = wert; } //Initialisierung in main void initialisierung(void) { softwareteiler1 = TEILER1; //Variablen konstanten Wert zuweisen softwareteiler2 = TEILER2; DDRB |= (1<<PB2); // Port B2 als Ausgang (gelbe LED) DDRC &= ~(1<<PC5); // Pin 5 an Port C als Eingang definieren (weise LED) timer0(); // Initialisierung Timer0 ad_init(); // Initialisierung AD-Wandler }
- Takt1, Takt2 müssen 'volatile' werden - softwareteiler1 und softwareteiler2 wahrscheinlich auch. - Sind die TEILERx Macros geraten?
1 | 5000 * 5000 * 256 * 8 |
2 | TEILER1 |
3 | TEILER2 |
4 | 8-Bit -Timer |
5 | Prescaler |
...sind eine Menge Takte zwischen zwei Wandlungen - Musst du den ADC immer ab- und wieder anschalten? Es reicht doch (wenn's nicht ultra-mobil werden soll) wenn der ADC bei der Initialisierung angeschaltet (ADEN-Bit) wird - bei "wandlung()" passen Bits und Kommentare nicht zusammen ("ADCSRA |= (1 << ADEN); //Free Running Modus wir eingeschaltet") - Warum gibt "wandlung()" nicht einfach den gemessenen Wert zurück? hth. Jörg
Hallo Jörg danke das du dir die Mühe gemacht hast das Programm durch zu schauen. Was meinst du mit Makros das verstehe ich nicht? Die 5000 hab ich einfach mal so reingetippt das was da steht ich weis noch nicht wie ich auf richtige Werte komme. Ja es müsste okay sein wenn ich den ADC in der Initialisierung einschalte das müsste ja dann so aussehen? void initialisierung(void) { softwareteiler1 = TEILER1; //Variablen konstanten Wert zuweisen softwareteiler2 = TEILER2; DDRB |= (1<<PB2); // Port B2 als Ausgang (gelbe LED) DDRC &= ~(1<<PC5); // Pin 5 an Port C als Eingang definieren (weise LED) timer0(); // Initialisierung Timer0 ad_init(); // Initialisierung AD-Wandler ADCSRA |= (1<<ADEN); //ADC wird eingeschaltet } und diese Zeile dann überall rauslöschen?! Wie kann ich bei wandlung() nur den gemessen Wert zurück geben? Das hab ich noch nicht verstanden. Sorry für so viele Fragen aber ist halt echt Neuland
... Weiter im text: - Der PWM-ausgang, den du im Programm einschaltest (OC2A) liegt auf PB*3*, nicht PB2. Du musst also die LED anders anschließen oder OC*1B* benutzen. - Verrate doch bitte, wie die LED zu messung angeschlossen ist -- wenn die LED einfach so angeschlossen ist (direkt am ADC-pin), wirst du da nicht so wahnsinnig viel messen können. - wenn du 8-Bit-PWM benutzt, musst du den Wert anpassen (wert>>2, wert/4, ADLAR setzen und nur das ADCH-Register benutzen, etc.) - Es reicht auch den Timer am anfang einzustellen, und im laufenden Programm NUR noch das OCnx-Register zu verstellen. hth. Jörg ps.: sry wegen der 'Meckerei' ;)
Ich hab dein Programm mal nach meinem Geschmack umstrukturiert, es kompiliert (mit WinAVR-20071221), ist aber ungetestet. Poste unbedingt deine Schaltung (auch wenn ich dir damit wahrscheinlich nicht wirklich helfen kann) hth. Jörg ps.: besorg dir ein C-Buch! pps.: als Notlösung gibt's im Web ein Openbook über C, ich finde das aber ein bisschen unübersichtlich
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.