Hallo, Ich habe ein Problemchen. LDR hängt an ADC0 (PA0). Besser gesagt, LDR ist zwischen VCC und ADC0, und von ADC0 geht ein 100kOhm an GND. (Und AVCC = VCC.) Gemessen wird (an ADC0 Pin) bei Licht ca. 200-600mV, und in Dunkel fast VCC, also ich kann sagen, LDR u. Spannungsteiler sind in Ordnung. Egal, was ich mache, das Programm zählt immer bis 1023! Das Programmteil: uint16_t ReadADC(uint8_t ch) { ADMUX = (1<<REFS0) | ch; // AVCC = ref. ADCSRA = (1<<ADEN) | (1<<ADSC) | (1<<ADIF) | 6; while ((ADCSRA & (1<<ADIF))==0); return ADC; } Ich weiss, "6" ist ein bisschen unschön, in der entgültigen Version werde ich die Kosmetik auch erledigen. :))) Also "6" heisst: Divider ist 64. Mein AVR läuft mit 11,0592 MHz, es gibt dann ca. 173kHz (vorgeschrieben ist zwischen 50 u. 200kHz) Was mache ich falsch? Habe ich was vergessen/versehen? Danke für Euere Hilfe, Karoly
Karoly Kovacs schrieb: > Egal, was ich mache, das Programm zählt immer bis 1023! > > Das Programmteil: da zählt gar nichts...
:))) OK, wie Du wahrscheinlich siehst, ich bin Ausländer. Also, ich habe es falsch formuliert, das Programm zählt natürlich nichts, sondern der ADC. Karoly
Karoly Kovacs schrieb: > uint16_t ReadADC(uint8_t ch) { > ADMUX = (1<<REFS0) | ch; // AVCC = ref. > ADCSRA = (1<<ADEN) | (1<<ADSC) | (1<<ADIF) | 6; > while ((ADCSRA & (1<<ADIF))==0); Was habt ihr nur immer mit dem Interrupt Flag? Lass das Teil doch in Ruhe. Du setzt ADSC auf 1 damit der ADC loslegt und wenn er fertig ist, setzt er ADSC wieder zurück auf 0.
1 | uint16_t ReadADC(uint8_t ch) { |
2 | ADMUX = (1<<REFS0) | ch; // AVCC = ref. |
3 | ADCSRA = (1<<ADEN) | 6; |
4 | |
5 | ADCSRA |= (1<<ADSC); // und los gehts |
6 | while (ADCSRA & (1<<ADSC)) // und warten ... |
7 | ;
|
8 | return ADC; |
9 | }
|
> return ADC; > } > > Ich weiss, "6" ist ein bisschen unschön, in der entgültigen Version > werde ich die Kosmetik auch erledigen. :))) Machs gleich.
Danke, Karl Heinz, hier steht es auch so: http://www.mikrocontroller.net/articles/AVR-Tutorial:_ADC Es geht aber doch nicht. :( So habe ich es dann gemacht (mit der Kosmetik inbegriffen): uint16_t ReadADC(uint8_t ch) { ADMUX = (1<<REFS0) | ch; // AVCC = ref. ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1); ADCSRA |= (1<<ADSC); // und los gehts while (ADCSRA & (1<<ADSC)) // und warten ... ; return ADC; } Karoly
Karoly Kovacs schrieb: > Es geht aber doch nicht. :( > > So habe ich es dann gemacht (mit der Kosmetik inbegriffen): OK. Da es dann keinen offensichtlichen Fehler mehr gibt (du könntest natürlich ganz einfach auch die ADC routine aus dem Tutorial einfach mal 1:1 übernehmen http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Der_interne_ADC_im_AVR ), widmen wir uns der Fage: woher weißt du, dass da immer 1023 raus kommt. Sprich: Was machst du mit dem Wert?
Hallo, PullUp an PA0 versehentlich eingeschaltet? Gruß aus Berlin Michael
So was habe ich gemacht: int main(void) { ... uint16_t licht; ... licht = ReadADC(0); sprintf(wstr,"Lichtwert: %d\n", licht); Trace(wstr); ... Ergebnis (es ist eine Heizungssteuerung per SMS): ... SendAT: AT+CMGR=15 SendAT: AT+CMGR=6 Lastsms: ON Licht: 1023 ... Trace ist bei mir ein Prozedur, der die Daten einfach an eine Bitbang-UART-Schnittstelle sendet. (Der andere UART ist besetzt.) Übrigens: Atmega ist in Ordnung, mein Programm läuft tadellos, ich wollte es bloss mit diesem Licht-Geschichte erweitern. Danke, Karoly
Nein, Michael, es ist leider, nach wie vor, falsch. Danke aber, Karoly
Probier mal
1 | return ADCW; |
(Auf manchen Prozessoren gibt es irgendwo ein Bit mit dem Namen ADC in irgendeinem der Register)
Juhhheee! Problem gelöst! Es war es blöder Kontaktfehler zwischen AREF (Pin32) u. GND (Pin31). (Es winziger Stück Lötzinn - wie so oft...) Grrrrr! Danke aber für Euere Hilfe! Karoly
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.