Forum: Compiler & IDEs ADC mit mega32 funktioniert nicht


von S. L. (slehner)


Lesenswert?

Hallo alle zusammen,

seit etwa 3 Monaten programmiere ich jetzt den mega32 und habe soweit 
alle Funktionen in Betrieb nehmen können dich ich brauche (I2C, UART, 
PORTS) Nun möchte ich über den ADC gerne eine Spannung einlesen. Im 
Internet habe ich bereits auch ein beispiel gefunden und teilweise etwas 
angepasst. Ich poste euch erstmal den Code der Funktion und dann den 
Programmteil, der diese aufruft. Der Wert soll über Port C ausgegeben 
werden. (oder testweise und die unteren 8 Bit. Es wäre super wenn mir 
jemand helfen könnte und nen Fehler in dem Code findet.

Funktion:
1
uint16_t ReadChannel(uint8_t mux)
2
{
3
  uint8_t i;
4
  uint16_t result = 0; //Initialisieren wichtig, da lokale Variablen
5
  uint8_t temp;
6
  
7
  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);   // requenzvorteiler
8
                          // setzen auf 8 (1) und ADC aktivieren (1)
9
  ADMUX = mux; // Kanal waehlen
10
  //ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen
11
  ADMUX |= (1<<REFS0);
12
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
13
  also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
14
  ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
15
16
  while ( ADCSRA & (1<<ADSC) )   {
17
                  //konvertierung abwarten
18
                  }
19
20
21
  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
22
  for(i=0;i<4;i++)
23
  {
24
    ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
25
    while ( ADCSRA & (1<<ADSC) ) 
26
    {
27
    ; // auf Abschluss der Konvertierung warten
28
    }
29
30
    result += ADCL; // Wandlungsergebnisse aufaddieren
31
    temp = ADCH;
32
  }
33
  ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2)
34
  result /= 4; // Summe durch vier teilen = arithm. Mittelwert
35
  return result;
36
}

aufrufender Programmteil:
1
uint16_t adcval;
2
  uint8_t ausgabe;
3
  for(;;){
4
    adcval = ReadChannel(0); /* MUX-Bits auf 0b0000 -> Channel 0 */
5
    //adcval = ReadChannel(2); /* MUX-Bits auf 0b0010 -> Channel 2 */
6
    DDRB = 0xFF;
7
    ausgabe = adcval | 0xFF;
8
    PORTB = ausgabe;
9
    delayloop16(16000);
10
    }

  

von yalu (Gast)


Lesenswert?

>   ausgabe = adcval | 0xFF;

Sollte da statt des | nicht ein & stehen? Sonst wird immer 0xff an den
Port gegeben.

von Joerg X. (Gast)


Lesenswert?

...oder ein "^", um die Bits umzudrehen, falls es um low-active-LEDs 
geht
(Und war da nicht was mit PORTC und JTAG...)
hth. Jörg

von S. L. (slehner)


Lesenswert?

Die Wandlung vom ADC funktioniert. Das Problem war ein anderen, nähmlich 
die Ausgabe. Ich möchte die 16bit Zahl ausgeben und dabei macht er 
verrückte Sachen. Ich glaube dass ich die zahl nicht anständig ich 8 bit 
Variablen aufteilen kann. Weiß jemand wie man das macht? Ich habe es nun 
mit folgendem probiert und es klappt nicht(Die Ausgabe über die serielle 
Schnittstelle funktioniert mit bytes bereits):
1
    zahl = AD_in();      // uint_16
2
    unsigned char tausender = (unsigned char) (zahl/1000) & 0x00FF;
3
    unsigned char hunderter = (unsigned char) (mod(zahl,1000)/100) & 0x00FF;
4
    unsigned char zehner = (unsigned char) (mod(zahl,100)/10)& 0x00FF;
5
    unsigned char einer = (unsigned char) mod(zahl,10) & 0x00FF;
6
    //PORTB = zahl_l;
7
    
8
    USART_transmit(tausender+48);
9
    
10
    USART_transmit(hunderter+48);
11
    USART_transmit(zehner+48);
12
    USART_transmit(einer+48);
13
    USART_transmit(45);// -

  

von yalu (Gast)


Lesenswert?

Ich kann in dem geposteten Programmteil keinen Fehler erkennen. Der
Fehler liegt entweder in USART_transmit (aber du schreibst, dass die
Ausgabe einzelner Zeichen schon funktioniert) oder die Funktion mod
tut nicht das Erwartete.

Was wird denn verrücktes ausgegeben? Wird wenigstens das '-' am Ende
angezeigt?

Woher kommt überhaupt die mod-Funktion? Hast du die selbst
geschrieben? Sonst gibt es für solche Dinge in C auch den
Modulooperator '%'.

Die "& 0x00FF" kannst du dir sparen. Sie haben keinen Effekt.

von S. L. (slehner)


Lesenswert?

danke für die Idee mit dem % Operator, den hab ich ganz vergessen.


Die Ausgabe funktioniert auch inzwischen. Der Fehler lag darin, dass ich 
die Stromversorgung des Atmels vor dem UART Anschluss angeschlossen habe 
und dadurch das Hyperterminal mitten im Byte angefangen hat das die 
Zeichenkette aufzunehmen. Deshalb wurden auch wirre Zeichen ausgegeben

von Oliver (Gast)


Lesenswert?

????

Das muß man jetzt aber nicht verstehen, oder?

Falls du das meinst, was ich glaube, zu verstehen (aber eigentlich nicht 
glauben kann): Ein Reset-Taster kostet nur ein paar Cent, und ist Gold 
wert.

Oliver

von S. L. (slehner)


Lesenswert?

Ja Oliver das stimmt. Es ist ein Projekt von 3 Leuten und ich 
programmiere den Atmel nur. Die Elektronik mach ich nicht. Mit wäre es 
auch lieber gewesen nicht bei jedem überspielen den Programmes den 
Stromstecker ziehen zu müssen und anschließend den Programmerstecker 
abziehen zu müssen. (Von der Masse des Oszis ganz zu schweigen) Aber das 
war dem Elektroniker zu viel Arbeit...

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
Noch kein Account? Hier anmelden.