Forum: Mikrocontroller und Digitale Elektronik µC+adc+usart+terminal


von Aladin M. (djas020)


Lesenswert?

Hallo,
ich komme zur Zeit irgendwie nicht so ganz zurecht mit der 
Avr-Programmierung von dem Atmega8. Es geht darum, dass ich 3 Spannungen 
in den ADC von dem atmega8 reinschicken will auf 3 verschiedene ports, 
und diese Spannungen möchte ich einfach auf die uart schnittstelle 
senden.
Als Versuch ob die Kommunikation zwischen PC und µC in Ordnung ist hab 
ich folgendes Programm in den Flash-Speicher geschrieben:
1
#include <avr/io.h>
2
3
#define BAUD      9600L
4
#define F_CPU     12000000L
5
#define UBRR_BAUD   ((F_CPU/(16L*BAUD))-1)
6
7
int main(void)
8
{
9
10
UBRRH = (uint8_t) (UBRR_BAUD>>8);
11
UBRRL = (uint8_t) (UBRR_BAUD & 0xFF);
12
13
UCSRB =(1<<TXEN);
14
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
15
16
while(1){
17
while(!(UCSRA & (1<<UDRE)))
18
{
19
}
20
21
UDR='x';
22
}
23
return 0;
24
}

Das Zeichen x das ich schicke kriege ich ins Terminalprogramm, also die 
Kommunikation passt.
Nun kommt erst mein richtiges Problem und zwar, da ich Neuling auf dem 
Gebiet bin, weiß ich nicht wie ich diese 3 Spannungen definieren soll? 
Brauche ich einen Interrupt? Ich habe mir vorgestellt das ungefähr 10 
mal in der sekunde abgetastet werden soll, also ein delay von 100ms und 
die Ausgabe so erfolgen soll: Spannung1,Spannung2,Spannung3
Ein Programm für den ADC habe ich und zwar sieht das folgendermaßen aus:
1
inline void uart_init(uint8_t tx, uint8_t rx)
2
{
3
    uint16_t baudrate;
4
    baudrate = UART_BAUD_RATE/2;
5
    UBRRH    = (uint8_t) (UART_UBRR_CALC(baudrate,F_CPU)>>8);
6
    UBRRL    = (uint8_t) UART_UBRR_CALC(baudrate,F_CPU);
7
    UCSRA |= (1<<U2X);
8
    UCSRB |= (1<<RXCIE);
9
    if(tx) UCSRB |= (1<<TXEN);
10
    if(rx) UCSRB |= (1<<RXEN);
11
    sei();
12
    pause(1);
13
}
14
void uart_putc(uint8_t c)
15
{
16
    while (!(UCSRA & (1<<UDRE)));
17
    UDR = c;
18
}
19
void uart_puti(uint16_t data)
20
{
21
    uint8_t buffer[7];
22
    uart_puts(utoa(data, buffer, 10));
23
}
24
uint16_t adc(uint8_t admux)
25
{
26
    ADCSRA  =  (1<<ADEN)  | (1<<ADPS1) | (1<<ADPS0);
27
    ADMUX   =  admux;
28
    ADMUX  |=  (1<<REFS1) | (1<<REFS0);
29
    ADCSRA |=  (1<<ADSC);
30
    while      (ADCSRA    & (1<<ADSC));
31
    uint16_t val     = ADCW;
32
    ADCSRA &= ~(1<<ADEN);
33
    return val;
34
int main(void)
35
{
36
    uint8_t i;
37
    uart_init(1, 1);
38
    while(1) // Unendlich lang wiederholen
39
    {
40
        for(i=0;i<6;i++)
41
        {
42
            uart_puti(adc(i));
43
            uart_putc(' ');
44
        }
45
        uart_putc('\n');
46
        _delay_ms(200);
47
    }
48
}
49
}

Wäre nett wenn ihr mir helfen könnt :( Übrigens das ist mein 
Diplomprojekt und zwar geht es um eine Ganganalyse die mit einem 
Gehstock aufgenommen wird, an dem ein Drucksensor und ein zweiachsiger 
Neigungssensor befestigt sind, diese drei Spannungen möchte ich nur 
digitalisieren und die Daten mit MATLAB erfassen.
Danke im vorhinein.

von Michael (Gast)


Lesenswert?

und wo ist jetzt dein problem? kannst du das programm compilieren? was 
macht es nicht richtig?

gruß michael

von Aladin M. (djas020)


Lesenswert?

Hallo, danke für deine Antwort.

Meine Frage lautet wie ich das Programm umschreiben kann das es mir auf 
die uart Schnittstelle die drei Werte schickt. Welcher Typ muss es sein? 
wie könnte das zum beispiel ausschauen?

von Rotzgraf (Gast)


Lesenswert?

Da bist ja nicht estgelegt. Gib doch einfach Ganzzahlen aus, oder ein 
Byte Vor- ein Byte Nachkomma. Da es ja dein eigenes "Protokoll" ist, 
hintert dich auch keiner daran 'A' als 5V 'B' als 10V 'C' als 5,1V und 
'56' als 9,999V zu definieren.

von holger (Gast)


Lesenswert?

Dein Beispielprogramm oben kann sich unmöglich
kompilieren lassen.

Schau dir mal die '{' und '}' ab hier an

uint16_t adc(uint8_t admux)

von Aladin M. (djas020)


Lesenswert?

hm.. ich versteh nicht ganz was du damit meinst..

ich habe diese 3 spannungen an 3 verschiedenen ports vom adc am µC. ich 
will diese 3 werte einfach an die uart schicken. meine frage lautet wie 
der code dazu aussehen könnte.. ich kenn mich leider wenig damit aus :S

von holger (Gast)


Lesenswert?

>hm.. ich versteh nicht ganz was du damit meinst..

Wen meinst du jetzt ? Rotzgraf oder mich ?

von Aladin M. (djas020)


Lesenswert?

tut mir leid, hab deinen post übersehen..
ich meinte natürlich rotzgraf.

@holger: was sollte denn nicht stimmen? es gehen 4 auf und 4 zu?

von Klammerbeutel (Gast)


Lesenswert?

Ja, schon richtig. Vier gehen auf und vier gehen zu.
Nur stehen sie augenscheinlich an der falschen Stelle!

Wo ist denn die schließende Klammer zur folgenden Funktion?

uint16_t adc(uint8_t admux)

von holger (Gast)


Lesenswert?

@holger: was sollte denn nicht stimmen? es gehen 4 auf und 4 zu?

uint16_t adc(uint8_t admux)
{
 int main(void)
  {
  }
}

Was könnte da wohl falsch sein ?

von Aladin M. (djas020)


Lesenswert?

@holger
ja ja :) ich merke es auch grad..
danke für den tipp.

weisst du vielleicht wie ich das realisieren könnte was ich will?

von holger (Gast)


Lesenswert?

>ja ja :)

Dafür hätte man dir hier im hohen Norden glatt eins reingeh....

>weisst du vielleicht wie ich das realisieren könnte was ich will?

So im grobem schon, aber die Aufgabe wurde DIR gestellt !
Ich bin nur der Kammerjäger ;)

von Aladin M. (djas020)


Lesenswert?

bist mir eine große Hilfe..

Wäre schön wenn hier jemand ist, der sich ein bisschen Zeit nehmen 
könnte um mir zu helfen. Danke im vorhinein

von Jörg X. (Gast)


Lesenswert?

Du willst immer noch 'nur' die ADC-Werte an den PC schicken?
fang doch mal 'klein'an:

Erster schritt
 - initialisiere:
   - ADC (mit ADLAR=1, halte es einfach und lies nur ADCH!)
   - USART
 - Messe (oder miss?! :P)
 - schick das Ergebnis an den PC

Nächster Schritt (Nur wenn das Programm aus dem ersten Schritt 
einwandfrei funktioniert):
 - ADC mit ADLAR=0;
 - Messe
 - sende beide Bytes
   - bei Empfange entsteht ein Problem: welches der zwei Bytes  ist 
welches
   - simpelste Lösung, z.b. itoa() (aus <stdlib.h>)
   - sende eben einen string und kennzeichne Anfang und Ende

Dritter Schritt (optional)
 - überleg dir ein binäres Protokoll, ohne den string

und (NICHT optional) lies das AVR-GCC-Tutorial

hth. Jörg

von Aladin M. (djas020)


Lesenswert?

es funktioniert alles.. ich hab es ja schon getestet mit einer einzelnen 
spannung und die wird mir auch ausgegeben.

meine frage lautet wie könnte ich die 3 definieren soll ich es mit int 
oder char machen?
ich hab mir da was überlegt und zwar folgendes:

int wert1,wert2,wert3;
char daten[16];
sprinft(daten,"[%d|%d|%d]",wert1,wert2,wert3);

senden(daten);   //das hier is dann das senden auf die schnittstelle

_
könnte mir vielleicht jemand weiterhelfen? ob ich das so realisieren 
könnte? und wie ich das mit dem avr-studio machen könnte?
wobei wert1,wert2,wert3 immer der wert von dem jeweiligen adc-port ist.

danke euch

von Jörg X. (Gast)


Lesenswert?

der Weg sieht doch ganz gut aus
1
int wert1,wert2,wert3;// ein array nehmen?
2
char daten[16]; // 16 reicht bestimmt nicht: "[1023|1023|1024]\0" -> 17
3
sprinft(daten,"[%d|%d|%d]",wert1,wert2,wert3);
4
5
//Ich würde es eher so machen:
6
char adc_string[20]; // aber mindestens 17
7
int adc_werte[3]; 
8
starte_messung(); //das Array füllen lassen (ADC_interrupt?!)
9
sleep(); // weniger störung für den ADC
10
if(/*fertig?*/){
11
    sprintf(adc_string, "[%d|%d|%d]", adc_werte[0], adc_werte[1], adc_werte[2]);
12
uart_puts(adc_string);
13
}
Oder ohne sprintf() (wegen den Spatzen und den Kanonen etc.):
1
char adc_string[20]; // Laenge ist nicht so wichtig
2
int adc_werte[3]; 
3
starte_messung(); //das Array füllen lassen (ADC_interrupt?!)
4
sleep(); // weniger störung für den ADC
5
if(/*fertig?*/){
6
    uart_putc('[');
7
    for (i=0; i<3; i++){
8
        itoa(adc_werte[i], adc_string, 10);
9
        uart_puts(adc_string);
10
        (i<2)? uart_putc('|');//gemein, ich weiss ;)
11
    }
12
    uart_putc(']');
13
    
14
}
hth. Jörg

von Aladin M. (djas020)


Lesenswert?

probier das gleich morgen aus :) danke sehr sehr daweil..

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.