Nabend! Ich bin ein interessierter Anfänger was die Microcontroller angeht. Für heute hatte ich mir vorgenommen mit dem integrierten AD-Wandler des ATMega32 zu arbeiten und die Daten dann über UART zum PC zu senden. Orientiert habe ich mich dabei an den Artikeln hier aus dem Forum. Kurzum ich habe den Schleifer eines Potis an den ADC0 Eingang des Controllers gelegt und die anderen beiden Anschlüsse an VCC sowie GND. AREF beträgt ebenfalls 5V. Nun habe ich das Problem das ich mit dem Terminalprogramm immer nur "FF" empfange, egal wie ich das Poti verändere. Könnt ihr mir sagen was ich falsch mache? Anbei der Code: #include <avr/io.h> #include <inttypes.h> #include <stdio.h> #define BAUD 19200UL #define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1) void uart_init(void) // USART initialisieren { UBRRH = (uint8_t) (UBRR_BAUD>>8); UBRRL = (uint8_t) (UBRR_BAUD & 0x0ff); UCSRB = (1<<RXEN)|(1<<TXEN); UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); } int main(void) { int buffer; int i; ADCSRA = (1<<ADEN)|(1<<ADSC); while ( ADCSRA & (1<<ADSC) ) { ; } buffer=ADCW; //------------------------------------------------------------------ uart_init(); // UART initialisieren while ( !( UCSRA & (1<<UDRE)) ) { ; } UDR = buffer; } Ich hoffe ich habe Euch keine essentiellen Informationen unterschlagen ;) Gruß
Was hältst Du davon, die Wandlung und das Senden mal in eine Endlosschleife zu packen? So wie es da steht, wird nur ein einziges Mal gewandelt und gesendet. Außerdem: Wie groß ist Dein F_CPU, wo ist es angegeben und womit erzeugst Du den Takt? Und noch was: AVCC ist intern als Referenz auswählbar (in ADMUX mit REFS0/1) und sollte nicht extern an den AREF-Pin angeschlossen werden! Der AREF-Pin sollte nur dann mit einer externen Spannung verbunden werden, wenn eine Referenzspannung benötigt wird, die der µC intern nicht zur Verfügung stellen kann.
Ach ja, die erste Wandlung nach dem Aktivieren des ADC ergibt i.d.R. kein sinnvolles Ergebnis und sollte verworfen werden.
Das nur einmal gewandelt und gesendet wird sollte eigentlich so sein, hab jetzt aber eine Endlosschleife drumherum gemacht. F_CPU ist 16000000 Erzeugt wird der Takt mit einem 16MHz Quarz. Fusebits sind korrekt. Mit der Endlossschleife empfange ich jetzt: CE 67 99 CE 67 99 EE E3 67 99 was sich dann immer wiederholt. Irgendwie bin ich jetzt doch etwas verwirrt...
Ahh ok Danke. Das mit dem AREF Pin werde ich dann nochmal ändern und auf den internen zurückgreifen.
Beginner wrote: > Ahh ok Danke. Das mit dem AREF Pin werde ich dann nochmal ändern und auf > den internen zurückgreifen. Und dann auch gleich an AREF einen kleinen Kondensator (100 nF) gegen GND. Dürfte aber mit Deinem Problem nichts zu tun haben...
Habe jetzt ADMUX = (1<<REFS0); in den Code eingefügt und auch den Kondensator zwischengeschaltet. Mit dem terminalprogramm empfange ich jetzt das folgende: CE 67 99 CE 67 99 CE 67 CE 67 99 CE 67 99 CE 77 CE 67 99 usw. Drehen am Poti hat nachwievor keinen Einfluß auf die Werte
Nun ja, die Werte an sich kann ich mir momentan auch nicht erklären. Was mir aber noch aufgefallen ist: In UDR passen ja nunmal nur 8 Bit rein, das Wandlungsergebnis hat aber 10 Bit. D.h., Du schneidest bei der Zuweisung "UDR = buffer;" die beiden höchsten Bits ab und überträgst nur die letzten 8. Dass da keine sinnvollen Werte am PC ankommen, sollte klar sein...
Ja da habt ihr natürlich recht, aber wenn ich das Poti von min. nach max. und umgekehrt drehe, dann müssten sich die Werte doch auf jedenfall ändern. Habs nochmal nachgemessen die Spannung am ADC0 Pin ändert sich durch verändern der Schleiferstellung... Könnte man das Problem mit dem Cast Operator lösen? Also im Prinzip: UDR = (char) buffer;
Beginner wrote: > Könnte man das Problem mit dem Cast Operator lösen? > Also im Prinzip: UDR = (char) buffer; Nö. Auf die Weise schneidest Du genauso das High-Byte ab wie in dem anderen Fall, nur dass Du jetzt noch dem Compiler mitteilst, dass das auch beabsichtigt ist... Was Du machen könntest ist, das Bit ADLAR im ADMUX setzen und nur ADCH auslesen (anstelle von ADC(W)). Dann bekommst Du die 8 höherwertigen Bits und die beiden letzten werden weggeworfen. Oder Du schiebst buffer bei der Zuweisung um zwei Stellen nach rechts...
Also wenn ich das richtig verstanden und umgesetzt habe sieht der ADC Teil jetzt folgendermaßen aus: ADCSRA = (1<<ADEN)|(1<<ADSC); ADMUX = (1<<REFS0); ADMUX = (1<<ADLAR); while ( ADCSRA & (1<<ADSC) ) { ; // auf Abschluss der Konvertierung warten } buffer=ADCH; // ADC Wert in Buffer schreiben Ja jetzt passiert folgendes: Ist die Spannung am ADC0 Pin größer als ~4,2V so sendet er "FF" ist die Spannung kleiner dann garnichts. Ich bin etwas ratlos ....
> ADMUX = (1<<REFS0); > ADMUX = (1<<ADLAR); Jetzt ist nur noch das ADLAR-Bit gesetzt. So muß das heissen: ADMUX = (1<<REFS0) | (1<<ADLAR);
oh ja klar da hab ich gepennt ... im ADCSRA Register hatte ich es ja auch schon so gemacht. Am Ergebnis hat sich leider nichts geändert. Bzw. durch das Verändern der Schleiferstellung ändern sich die empfangenen Werte im Terminalprogramm nicht
Die Initialisierungen sollten beide vor die for(;;)-Schleife - schließlich braucht man die Schnittstelle und den ADC nur ein Mal initialisieren. Vermutlich hast du deswegen auch nur unsinnige Werte.
Mhh ja das war schonmal ein guter Schritt in die richtige Richtung! Irgendwo ist aber noch eine Kleinigkeit würde ich sagen. Das Terminalprogramm zeigt mir jetzt nur noch einen hexadezimalen Wert an, welcher sich allerdings auch nicht ändert, wenn man die Schleiferstellung verändert. Die Endlosschleife ist nachwievor im Programm. Ich hab mir grad mal die Spannung am ADC0 Pin gemessen und die dazugehörigen HEX Werte aus dem terminalprogramm notiert: 5V ->8C 3V ->42 1,1V->C6 Das kann doch irgendwie nicht stimmen ...
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.