Forum: Mikrocontroller und Digitale Elektronik Atmega8 Uart & ADC


von Max K. (Gast)


Lesenswert?

Hallo Leute,

ich versuche gerade über den den PC0 Per internen ADC die spannung 
einzulesen die an diesem liegt und das ganze über Uart an den PC zu 
senden:


Mein Code sieht wie folgt aus
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#define F_CPU 4000000
4
#include <util/delay.h>
5
#define BAUD 9600
6
#define UBRR_VAL F_CPU/16/BAUD-1
7
8
9
volatile uint16_t result;
10
volatile uint16_t wert;
11
uint8_t i;
12
13
14
15
16
void delay_ms(int delay) {
17
        int i;
18
        for (i=0;i<=delay;i++) {
19
                _delay_ms(1);
20
        }
21
}
22
23
void init_uart(unsigned int ubrr) {
24
        UBRRH = (unsigned char)(ubrr>>8);
25
        UBRRL = (unsigned char)(ubrr);
26
        UCSRB |= (1<<RXEN);
27
        UCSRB |= (1<<TXEN);
28
        UCSRB |= (1<<RXCIE);
29
        UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
30
}
31
32
void send_char(unsigned char data) {
33
        while (!(UCSRA & (1<<UDRE)));
34
        UDR = data;
35
}
36
37
void send_string(char *data) {
38
        while (*data) {
39
                send_char(*data);
40
                data++;
41
        }
42
}
43
44
volatile uint16_t adc(uint8_t mux)
45
{
46
  
47
  ADMUX = mux;
48
  ADMUX |= (0<<REFS1) | (1<<REFS0);     // AVcc nutzen
49
    ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);   // Frequenzvorteiler setzen auf 8 und ADC aktivieren
50
 
51
    /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
52
       also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
53
    ADCSRA |= (1<<ADSC);                // eine ADC-Wandlung 
54
    while ( ADCSRA & (1<<ADSC) );       // auf Abschluss der Konvertierung warten 
55
    result = ADCW;        // ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten Wandlung nicht übernommen.
56
 
57
    /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
58
    result = 0; 
59
     for( i=0; i<4; i++ )
60
    {
61
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
62
      while ( ADCSRA & (1<<ADSC) );     // auf Abschluss der Konvertierung warten
63
      result += ADCW;            // Wandlungsergebnisse aufaddieren
64
    }
65
    ADCSRA &= ~(1<<ADEN);               // ADC deaktivieren (2)
66
 
67
    result /= 4;                       // Summe durch vier teilen = arithm. Mittelwert
68
 
69
}
70
71
72
73
int main(void) {
74
  init_uart(UBRR_VAL);
75
76
77
  wert = adc(0);  
78
79
  send_string("Wert: ");
80
  send_string(wert);
81
82
83
}


Das Problem ist nun das ich im Terminal keinen Zahlenwert angzeigt 
bekomme sondern "Wert: " und daruaf folgen dann irgendwelche kryptische 
zeichen. An der Baudrate kann es ja schonmal nicht liegen.

Hat jemand eine Ahnung woran es liegen könnte?

Vielen Dank,
Max

von Stefan B. (stefan) Benutzerseite


Lesenswert?


von Oliver J. (skriptkiddy)


Lesenswert?

Du musst den Wert noch in einen "String" umwandeln.

utoa müsste dir helfen
1
send_string(utoa(wert));


Gruß Skriptkiddy

von Max K. (Gast)


Lesenswert?

Danke habe den Code jetzt etwas angepasst aber leider bekomm ich immer 
Werte wie
1
333332
 raus das kann doch nicht ganz stimmen oder??

Hier nocheinmal der neue Code.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#define F_CPU 4000000
4
#include <util/delay.h>
5
#define BAUD 9600
6
#define UBRR_VAL F_CPU/16/BAUD-1
7
8
volatile uint16_t result;
9
volatile uint16_t wert;
10
uint8_t i;
11
12
13
14
void delay_ms(int delay) {
15
        int i;
16
        for (i=0;i<=delay;i++) {
17
                _delay_ms(1);
18
        }
19
}
20
21
void init_uart(unsigned int ubrr) {
22
        UBRRH = (unsigned char)(ubrr>>8);
23
        UBRRL = (unsigned char)(ubrr);
24
        UCSRB |= (1<<RXEN);
25
        UCSRB |= (1<<TXEN);
26
        UCSRB |= (1<<RXCIE);
27
        UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
28
}
29
30
void send_char(unsigned char data) {
31
        while (!(UCSRA & (1<<UDRE)));
32
        UDR = data;
33
}
34
35
void send_string(char *data) {
36
        while (*data) {
37
                send_char(*data);
38
                data++;
39
        }
40
}
41
42
volatile uint16_t adc(uint8_t mux)
43
{
44
  
45
  ADMUX = mux;
46
  ADMUX |= (1<<REFS0);         // AVcc nutzen
47
    ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);   // Frequenzvorteiler setzen auf 64 und ADC aktivieren
48
 
49
    /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
50
       also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
51
    ADCSRA |= (1<<ADSC);                      // eine ADC-Wandlung 
52
    while ( ADCSRA & (1<<ADSC) );             // auf Abschluss der Konvertierung warten 
53
    result = ADCW;  // ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten Wandlung nicht übernommen.
54
 
55
    /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
56
    result = 0; 
57
     for( i=0; i<4; i++ )
58
    {
59
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
60
      while ( ADCSRA & (1<<ADSC) );     // auf Abschluss der Konvertierung warten
61
      result += ADCW;            // Wandlungsergebnisse aufaddieren
62
    }
63
    ADCSRA &= ~(1<<ADEN);               // ADC deaktivieren
64
 
65
    result /= 4;                       // Summe durch vier teilen = arithm. Mittelwert
66
 
67
  return result;
68
}
69
70
71
72
int main(void) {
73
  init_uart(UBRR_VAL);
74
75
  wert = adc(0);  
76
77
  send_string("wert: ");
78
  send_string(utoa(wert));
79
80
81
82
}

von Huch (Gast)


Lesenswert?

Ganz sicher das, dass
1
send_string("wert: ");
ohne Fehler und Warnings compiliert? So à la: "... redefinition of 
utoa..."?

Eigentlich:

char utoa (unsigned int __val, char __s, int __radix)

Welchen Compiler verwendest Du?. Welche lib?

von Huch (Gast)


Lesenswert?

Sorry, falsche Zeile:
1
send_string(utoa(wert));

ist die fragliche Zeile.

von Max K. (Gast)


Lesenswert?

Ich bekomme folgende Warnings angezeigt.
1
../main.c:83: warning: implicit declaration of function 'utoa'
2
../main.c:83: warning: passing argument 1 of 'send_string' makes pointer from integer without a cast

von Huch (Gast)


Lesenswert?

>Ich bekomme folgende Warnings angezeigt.

OK. Sehe gerade das Du stdlib nicht uncludet hattest. Deswegen wohl kein 
redefinition. Aber die Warnung hätte Dir eine Warnung sein sollen. Eine 
"implizite" Deklaration heisst, es gibt keine explizite, was bei library 
Funktionen immer der Fall sein sollte.

Also es fehlt:
1
#include <stdlib.h>
2
...
3
char buffer[10];            // oder ein anderer passender Wert
4
...
5
send_string(utoa(wert, buffer, 10));
6
...

Lies Dir mal die Beschreibung der avr-libc durch.

von Lukas K. (carrotindustries)


Lesenswert?

Max K. schrieb:
> Ich bekomme folgende Warnings angezeigt.
>
>
1
../main.c:83: warning: implicit declaration of function 'utoa'
2
> ../main.c:83: warning: passing argument 1 of 'send_string' makes pointer
3
> from integer without a cast
4
>
http://www.mikrocontroller.net/articles/FAQ#Wie_kann_ich_Zahlen_auf_LCD.2FUART_ausgeben.3F
insb. das itoa Beispiel. utoa gibt keinen Pointer/String zurück, sondern 
erwartet einen Puffer, in welchem der String gespeichert wird.

von Huch (Gast)


Lesenswert?

>utoa gibt keinen Pointer/String zurück
Das ist so nicht richtig. Es gibt einen Zeiger auf den übergebenen 
Buffer zurück.
Aber Du meintest wohl auch eher die Tatsache, dass utoa selbst keinen 
Buffer alloziiert.

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.