Forum: Mikrocontroller und Digitale Elektronik rs232 Variable übergeben


von odin (Gast)


Lesenswert?

Hi,

bastel gerade ein wenig mit RS232 herum. Ich habe eine bidirektionale 
Verbindung zwischen PC und µc.

Der PC sendet bspl. eine "10"

Die "10" wird in der Variablen "c" gespeichert und an den PC zurück 
gegeben.

Soweit so gut.

In einer ISR habe ich die Variable "tempo"

Wie kann ich die "10" aus "c" nun an "tempo" übergeben ?

Gruß
odin

von Peter II (Gast)


Lesenswert?

tempo = c;

von B. S. (bestucki)


Lesenswert?

Er erhält "10" und das ist ein string. Daher:
strcpy(tempo,c);

:D

Du musst darauf achten, dass c eine globale Variable ist, da du 
ansonsten aus der ISR keinen Zugriff darauf hast.

EDIT: In der Annahme, dass du C verwendest...

von amateur (Gast)


Lesenswert?

Vorsicht bissiger Hund!

Werden über die serielle Schnittstelle die Zeichen "1" und "0" 
übertragen, so kann der Zugriff via. strcpy () Probleme bereiten.
strcpy steht auf das Abschließende "\0" - so war‘s wenigstens früher 
mal.

von odin (Gast)


Lesenswert?

Also ich verwende die lib von Peter Fleury.

Mit c = uart_getc(); --> weise ich den Inhalt der variablen c zu.
C wird außerhalb der Funktion mit unsigned int c; --> global

ebso die variable tempo mit unsigned int

von B. S. (bestucki)


Lesenswert?

Dann genügt
> tempo = c;

von odin (Gast)


Lesenswert?

Hier mal der Code. Es haut so aber nicht hin:

#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <string.h>
#include "uart.h"

#ifndef F_CPU
  #define F_CPU  16000000
#endif

#define UART_BAUD_RATE      9600

#define LED_DDR    DDRA
#define LED_PORT  PORTA
#define LED_PORTPIN1  PA2
#define LED_PORTPIN2  PA1

volatile uint8_t zaehler;
unsigned int tempo;
unsigned int c;

// Timer0(8-bit) init

void initTimer0(void) {
  TCCR0 |= (1<<CS00) | (1<<CS02);  // Prescale von 1024
  TIMSK |= (1<<TOIE0);            // Interrupts aktivieren
  TCNT0 = 0x00;
  sei();
}

ISR(TIMER0_OVF_vect)
{
  if (zaehler <=tempo)
  {
    zaehler ++;
  }
  else
  {
    LED_PORT ^= LED_PORTPIN1;
    LED_PORT ^= LED_PORTPIN2;
    zaehler = 0;
  }
}

int main (void)
{

  LED_DDR = 0xFF;    // Port als Ausgang
  LED_PORT = 0x02;  // Anfangszustand der LED

  initTimer0();

    char buffer[7];
    int  num=134;

    uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

    sei();

    uart_puts("String stored in SRAM\n");

  for(;;)
    {
        c = uart_getc();

  tempo = c;

        if ( c & UART_NO_DATA )
        {
        }
        else
        {
            if ( c & UART_FRAME_ERROR )
            {
                uart_puts_P("UART Frame Error: ");
            }
            if ( c & UART_OVERRUN_ERROR )
            {
                uart_puts_P("UART Overrun Error: ");
            }
            if ( c & UART_BUFFER_OVERFLOW )
            {
                uart_puts_P("Buffer overflow error: ");
            }
            uart_putc( (unsigned char)c );

        }

  }


}

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

odin schrieb:
> volatile uint8_t zaehler;
> unsigned int tempo;
> unsigned int c;

Mach erstmal aus tempo und c auch ein volatile uint8_t, sonst gibts 
casting Probleme. c muss allerdings nicht volatile sein.
Ausserdem musst du entweder ein einzelnes Byte übertragen (also z.B. ein 
grosses 'A' hätte dann 0x41 als Wert), oder du brauchst eine 
Empfangsroutine, die dir eine Zahl, gefolgt von einem 'Ende' Zeichen 
umwandelt in ein Byte.

von Peter D. (peda)


Lesenswert?

odin schrieb:
> Mit c = uart_getc(); --> weise ich den Inhalt der variablen c zu.

Quatsch.
Damit steht in c nur das letzte empfangene Zeichen, z.B. '0' = 48.

Du willst aber eine Zeichenkette empfangen und dann in eine Zahl 
umwandeln.
Dazu mußt Du Dir erstmal ein Protokoll überlegen, wie der Anfang und das 
Ende der Zeichenkette markiert und erkannt werden kann.

von amateur (Gast)


Lesenswert?

Vielleicht kann "Odin" ja mal aus seinem Götterhimmel herauskrabbeln und 
seinen Anhängern erklären ob er so etwas simples wie ein binäres Zeichen 
z.B. 0xA=10=ein Zeichen, oder eine ASCII-Zeichenkette wie z.B. "1" + "0" 
= zwei Zeichen, durch die Lande schaukelt.

von odin (Gast)


Lesenswert?

Hey amatuer, keine Spässe über meinen Name, ich heisse wirkich so !

Also ich wollte einfach nur den ordinären Wert 10 vom PC übertragen, der 
die Blinkgeschwindigkeit änder soll

von amateur (Gast)


Lesenswert?

... was nichts daran ändert, das eine Klarstellung nötig war.

Also nix mit strcpy () sondern einfach warten bis ein Zeichen im Puffer 
vorhanden ist und dieses dann holen/kopieren (=).

von Karl H. (kbuchegg)


Lesenswert?

odin schrieb:


>   for(;;)
>     {
>         c = uart_getc();
>
>   tempo = c;
>
>         if ( c & UART_NO_DATA )
>         {
>         }


So so.
Du verwendest also das c bereits, noch ehe klar ist, ob uart_getc() 
überhaupt ein Zeichen für dich hatte, oder ob es mangels Daten 
UART_NO_DATA geliefert hat, um anzuzeigen, dass vom Sender nichts 
gekommen ist.


Liest heute eigentlich noch irgendwer Democode und überlegt sich, was er 
da gelesen hat oder wird heutzutage in Demos nur noch gedankenlos und 
dämlich das reingeschrieben, was man sich irgendwie denkt?
Mann ihr wärt aber sowas von aufgeschmissen gewesen, wenn ihr in einer 
Zeit angefangen hättet, in der es kaum Demos gab und man sich aus 500 
Seiten Manuals alles zusammensuchen musste und dann stundenlang das 
Gelesene versucht hat, in Code zu giessen.

von odin (Gast)


Lesenswert?

Ja was sol ich da sagen , Gnade der späten Geburt !

Ich nehme aber einmal an, du wolltest mir auch damit weiter helfen.
Vielen Dank

von Karl H. (kbuchegg)


Lesenswert?

odin schrieb:
> Ja was sol ich da sagen , Gnade der späten Geburt !
>
> Ich nehme aber einmal an, du wolltest mir auch damit weiter helfen.

Ich will dich aufrütteln, dass du Democode auch STUDIEREN musst.
Das was du in einer Demo siehst, das steht da nicht von ungefähr! P. 
Fleury het den nicht geschrieben, weil ihm fad war, sondern weil er 
damit etwas demonstrieren will. Nämlich: wie verwendet man die Funktion 
korrekt und wie wertet man den Returncode korrekt aus.
Und wenn ich seinen Code studiere, dann sehe ich dass er von der 
Funktion einen Wert bekommt, den er in c speichert. Und dann gehts 
weiter! Was macht er mit diesem c? Wie wertet er die Variable aus. 
Bereits in der nächsten Zeile steht

   if( c & UART_NO_DATA )

UART NO DATA?
Da muss es doch sofort zum Klingeln anfangen. NO DATA - keine Daten. Was 
macht seine Demo in diesem Fall? Nichts - sie macht buchstäblich nichts. 
Wie denn auch, wenn die Funktion liefert "Ich hab nichts", dann ist da 
auch nichts, mit dem man etwas tun könnte (etwa ausgeben).

von odin (Gast)


Lesenswert?

Ok, die Funktion hahe ich ja auch soweit verstanden. Mein "tempo = c;" 
steht da nur aus lauter Verzweifelung.

Aus meiner bescheidenen Sicht müsste der Code hier stehen :

for(;;)
    {
        c = uart_getc();

        if ( c & UART_NO_DATA )
        {
        }
        else
        {
            if ( c & UART_FRAME_ERROR )
            {
                uart_puts_P("UART Frame Error: ");
            }
            if ( c & UART_OVERRUN_ERROR )
            {
                uart_puts_P("UART Overrun Error: ");
            }
            if ( c & UART_BUFFER_OVERFLOW )
            {
                uart_puts_P("Buffer overflow error: ");
            }
            uart_putc( (unsigned char)c );
      tempo = c;
        }

  }

Denn nur wenn alle DANN Möglichkeiten NICHT zutreffen, ist erfolgreich 
etwas übertragen worden.

Es klappt aber leider auch so nicht

von amateur (Gast)


Lesenswert?

Ich habe nie mit der Bibliothek von Peter Fleury gearbeitet, aber 
vielleicht wäre es hilfreich statt mit:

tempo = c;

mit

tempo = c & 0xff;

zu arbeiten.

Irgendwie sieht euer Code so aus als ob da mehr als char zurückgeliefert 
wird, euer Interesse aber auf char beschränkt ist.

von amateur (Gast)


Lesenswert?

Sorry, wenn euer char im Obergeschoss (Bit 8 bis 15) herumhängt.
Dann könnte:

tempo = c >> 8;

recht hilfreich sein.

von Karl H. (kbuchegg)


Lesenswert?

amateur schrieb:

> tempo = c;
>
> mit
>
> tempo = c & 0xff;
>
> zu arbeiten.

Das passt schon.
Wenn alle Fehler ausgeschlossen sind, dann bleibt in c nur mehr das 
LowByte übrig. Das High-Byte ist definitiv 0.


"Funktioniert nicht"
ist nun mal keine ordentliche Fehlerbeschreibung.

Der COde sendet ja das Byte, welches dann an temp zugewiesen wird über 
die UART zurück. D.h. da hat man ja die Bestätigung beim Sender, was der 
AVR eigentlich erhalten hat, und welche Werte dann auch tatsächlich an 
tempo zugewiesen werden.

Aber noch bin ich mir nicht sicher, ob er überhaupt den UNterschied 
zwischen einer ASCII Übertragung und einer binären Übertragung versteht. 
Mal genauer nachfragen.

von Karl H. (kbuchegg)


Lesenswert?

> Also ich wollte einfach nur den ordinären Wert 10 vom PC übertragen,
> der die Blinkgeschwindigkeit änder soll

Und wie machst du das auf PC-Seite?

Und wurde die UART eigentlich schon mal prinzipiell getestet?
Wenn du vom AVR was zum PC schickst (zb indem dort ein Terminalprogramm 
läuft), erscheint dann dort das Gesendete korrekt?

von amateur (Gast)


Lesenswert?

Ich weis nicht wie Fehlerträchtig (hängt wohl vom Quarz ab) die 
Übertragung ist, aber bei einem UART_FRAME_ERROR, UART_OVERRUN_ERROR 
oder UART_BUFFER_OVERFLOW erfolgt trotzdem ein:
tempo = c;

von Karl H. (kbuchegg)


Lesenswert?

amateur schrieb:
> Ich weis nicht wie Fehlerträchtig (hängt wohl vom Quarz ab) die
> Übertragung ist, aber bei einem UART_FRAME_ERROR, UART_OVERRUN_ERROR
> oder UART_BUFFER_OVERFLOW erfolgt trotzdem ein:
> tempo = c;


Yep,
Das ist nicht schön. Aber wenn die UART prinzipiell korrekt funktioniert 
(was man erst mal testen müsste), dann kommen diese Fehler praktisch 
nicht vor. In einem Profiprogramm werden sie selbstverständlich 
behandelt, aber für die ersten Schritte ist es schon ok.

Die ganze Problematik wird ja auch im Tutorial komplett ignoriert. Ein
1
uint8_t uart_getc(void)
2
{
3
    while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
4
        ;
5
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
6
}

ist ja so gesehen auch nur die halbe Miete, weil ja die ganze 
Fehlerbehandlung komplett ignoriert wird. Irgendwo muss man nun mal 
anfangen und Fehlerbehandlung hat die Tendenz, die Dinge mal schnell 
kompliziert und unübersichtlich zu machen.

Aber wie gesagt: Wenn die UART prinzipiell funktioniert, dann treten 
diese Fehler nicht auf und können so gesehen fürs erste ignoriert 
werden.

von amateur (Gast)


Lesenswert?

@odin

Mit welchem Prozessor redest Du eigentlich?

Habe es wahrscheinlich 5 mal überlesen aber ...

von odin (Gast)


Lesenswert?

Also die uart funktioniet. Ich kann etwas senden und ich kann etwas 
empfangen.

Den Rest muss ich gleich mal test

von odin (Gast)


Lesenswert?

So vielen Dank für die Unterstützung ! Es funktioniert  !!

Natürlich muss ich auch binär etwas senden, wenn ich binär etwas erwarte 
:-)

Und ich habe sogar verstanden warum

tempo = c & 0xff;

zum Ziel führte !

Danke an alle !

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.