www.mikrocontroller.net

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


Autor: Aladin Mujovic (djas020)
Datum:

Bewertung
0 lesenswert
nicht 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:
#include <avr/io.h>

#define BAUD      9600L
#define F_CPU     12000000L
#define UBRR_BAUD   ((F_CPU/(16L*BAUD))-1)

int main(void)
{

UBRRH = (uint8_t) (UBRR_BAUD>>8);
UBRRL = (uint8_t) (UBRR_BAUD & 0xFF);

UCSRB =(1<<TXEN);
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);

while(1){
while(!(UCSRA & (1<<UDRE)))
{
}

UDR='x';
}
return 0;
} 

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:
inline void uart_init(uint8_t tx, uint8_t rx)
{
    uint16_t baudrate;
    baudrate = UART_BAUD_RATE/2;
    UBRRH    = (uint8_t) (UART_UBRR_CALC(baudrate,F_CPU)>>8);
    UBRRL    = (uint8_t) UART_UBRR_CALC(baudrate,F_CPU);
    UCSRA |= (1<<U2X);
    UCSRB |= (1<<RXCIE);
    if(tx) UCSRB |= (1<<TXEN);
    if(rx) UCSRB |= (1<<RXEN);
    sei();
    pause(1);
}
void uart_putc(uint8_t c)
{
    while (!(UCSRA & (1<<UDRE)));
    UDR = c;
}
void uart_puti(uint16_t data)
{
    uint8_t buffer[7];
    uart_puts(utoa(data, buffer, 10));
}
uint16_t adc(uint8_t admux)
{
    ADCSRA  =  (1<<ADEN)  | (1<<ADPS1) | (1<<ADPS0);
    ADMUX   =  admux;
    ADMUX  |=  (1<<REFS1) | (1<<REFS0);
    ADCSRA |=  (1<<ADSC);
    while      (ADCSRA    & (1<<ADSC));
    uint16_t val     = ADCW;
    ADCSRA &= ~(1<<ADEN);
    return val;
int main(void)
{
    uint8_t i;
    uart_init(1, 1);
    while(1) // Unendlich lang wiederholen
    {
        for(i=0;i<6;i++)
        {
            uart_puti(adc(i));
            uart_putc(' ');
        }
        uart_putc('\n');
        _delay_ms(200);
    }
}
} 

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.

Autor: Michael (Gast)
Datum:

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

gruß michael

Autor: Aladin Mujovic (djas020)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Rotzgraf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein Beispielprogramm oben kann sich unmöglich
kompilieren lassen.

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

uint16_t adc(uint8_t admux)

Autor: Aladin Mujovic (djas020)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>hm.. ich versteh nicht ganz was du damit meinst..

Wen meinst du jetzt ? Rotzgraf oder mich ?

Autor: Aladin Mujovic (djas020)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Klammerbeutel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: Aladin Mujovic (djas020)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ;)

Autor: Aladin Mujovic (djas020)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Aladin Mujovic (djas020)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
der Weg sieht doch ganz gut aus
int wert1,wert2,wert3;// ein array nehmen?
char daten[16]; // 16 reicht bestimmt nicht: "[1023|1023|1024]\0" -> 17
sprinft(daten,"[%d|%d|%d]",wert1,wert2,wert3);

//Ich würde es eher so machen:
char adc_string[20]; // aber mindestens 17
int adc_werte[3]; 
starte_messung(); //das Array füllen lassen (ADC_interrupt?!)
sleep(); // weniger störung für den ADC
if(/*fertig?*/){
    sprintf(adc_string, "[%d|%d|%d]", adc_werte[0], adc_werte[1], adc_werte[2]);
uart_puts(adc_string);
}
Oder ohne sprintf() (wegen den Spatzen und den Kanonen etc.):
char adc_string[20]; // Laenge ist nicht so wichtig
int adc_werte[3]; 
starte_messung(); //das Array füllen lassen (ADC_interrupt?!)
sleep(); // weniger störung für den ADC
if(/*fertig?*/){
    uart_putc('[');
    for (i=0; i<3; i++){
        itoa(adc_werte[i], adc_string, 10);
        uart_puts(adc_string);
        (i<2)? uart_putc('|');//gemein, ich weiss ;)
    }
    uart_putc(']');
    
}
hth. Jörg

Autor: Aladin Mujovic (djas020)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
probier das gleich morgen aus :) danke sehr sehr daweil..

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.