www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Daten vom PC über RS232 zum MC schicken


Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich hätte da mal eine Verständnisfrage:

Ich schicke über ein C# Programm 4 Bytes, verpackt in einem Array zum MC 
über die Serielle Schnittstelle:

byte[] buffer0 = new byte[4];
buffer0[0] = 30;
buffer0[1] = 100;
buffer0[2] = 200;
buffer0[3] = 210;

serialPort.Write(buffer0,0,4);


Der MC empfängt diese und schreibt sie in eine Variabel, die als

volatile uint8_t s1;
s1=uart_getc();

declariert ist.

Anschließend schicke ich diese wieder zurück:

uart_putc(s1);

Das C# Programm liest dann diesen Wert in ein byte Array ein
und gibt ihn in Textfeldern aus:

byte[] inbuffer = new byte[4];

serialPort.Read(inbuffer,0,4);

label1.Text = Convert.ToString(inbuffer[0]);
label2.Text = Convert.ToString(inbuffer[1]);
label3.Text = Convert.ToString(inbuffer[2]);
label4.Text = Convert.ToString(inbuffer[3]);

Alle 4 Bytes kommen an ??

Das wundert mich, da doch der MC den UART nur in ein uint8_t s1
einliest. Nach meinem Verständnis dürfte nur das letzte Byte 
zurückgeschickt werden, also buffer0[3] = 210.

Vielleicht kann mir das hier mal jemand erklären ?

Schon  mal Danke für die Antworten :-)

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bitte gib das komplette µC Programm an.

Deine Beobachtung wäre erklärbar, wenn das Programm in etwa so aussieht, 
d.h. das Empfangen und Senden in einer Schleife passiert.

#include <avr/io.h>
#include <inttypes.h>

volatile uint8_t s1;

// Funktionsdefinition von uart_getc()
// ...

// Funktionsdefinition von uart_putc()
// ...

int main(void)
{
   // UART initialisieren
   // ...

   while(1)
   {
      s1 = uart_getc(); // Empfangen
      uart_putc(s1);    // Senden
   }
}

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
C# Programm:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace rs232
{
    public partial class Form1 : Form
    {


        public Form1()
        {
            InitializeComponent();
            serialPort.Open();
        }

        private void button2_Click(object sender, EventArgs e)
        {


            byte[] buffer0 = new byte[4];

            buffer0[0] = 30;
            buffer0[1] = 100;
            buffer0[2] = 200;
            buffer0[3] = 210;

            serialPort.Write(buffer0,0,4);

        }

        private void button1_Click(object sender, EventArgs e)
        {


            byte[] inbuffer = new byte[4];

            serialPort.Read(inbuffer,0,4);

            label1.Text = Convert.ToString(inbuffer[0]);
            label2.Text = Convert.ToString(inbuffer[1]);
            label3.Text = Convert.ToString(inbuffer[2]);
            label4.Text = Convert.ToString(inbuffer[3]);

            inbuffer[0] = 0;
            inbuffer[1] = 0;
            inbuffer[2] = 0;
            inbuffer[3] = 0;

        }

        private void button3_Click(object sender, EventArgs e)
        {
            label1.Text = Convert.ToString(0);
            label2.Text = Convert.ToString(0);
            label3.Text = Convert.ToString(0);
            label4.Text = Convert.ToString(0);
        }


    }
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas wrote:
> C# Programm:

Das C# Programm interessiert hier nicht weiter.

Du wunderst dich doch, dass der µC 4 Byte zurückschickt
und wo er die her hat.
Also ist dann wohl auch die Programmierung des µC ineterssant.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
C Programm auf ATMega8

#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <uart.h>
#include <uart.c>
#include <util/delay.h>
#define UART_BAUD_RATE      9600

volatile uint8_t s1;
volatile uint8_t update=0;

ISR (TIMER1_COMPA_vect)
{
  TCNT1=0;
  update++;
}

int main(void)
{
DDRD=0xff;
//PORTD=0b01100000;

  TCCR0|=(1<<CS00)|(1<<CS02);    // Timer 0 Initialisierung
  TIMSK|=(1<<TOIE0);

  TCCR1B|=(1<<CS12);TIMSK|=(1<<OCIE1A);        //Timer1
   OCR1A=15000;

    uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU));

  sei();

  while(1)
{

  if (update==1)
  {

    s1=uart_getc();

                  if (s1==0)
    PORTD &= ~(1<<PD6);

    if (s1>0)
    {
    PORTD |= (1<<PD6);
    s1++;
    s3++;
    uart_putc(s1);
    uart_putc(s2);
    uart_putc(s3);
    uart_putc(s4);
    }



  update=0;
  }


}}

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
s1=uart_getc();
    ...
    uart_putc(s1);
    uart_putc(s2);
    uart_putc(s3);
    uart_putc(s4);

Sind für mich vier Bytes die gesendet werden ;-)

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht noch eine kurze Erklärung:

PORTD &= ~(1<<PD6); und PORTD &= ~(1<<PD6);

sind LEDs.

Und nach der UART Library, die ich benutzt, kann ich mit

s1=uart_getc();
if (s1==0)

abfragen, ob daten gekommen sind.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh...sorry,

ich habe mittlerweile weiter rumexperimentiert:

Das hier war der Originalcode:

#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <uart.h>
#include <uart.c>
#include <util/delay.h>
#define UART_BAUD_RATE      9600

volatile uint8_t s1;
volatile uint8_t update=0;

ISR (TIMER1_COMPA_vect)
{
  TCNT1=0;
  update++;
}

int main(void)
{
DDRD=0xff;
//PORTD=0b01100000;

  TCCR0|=(1<<CS00)|(1<<CS02);    // Timer 0 Initialisierung
  TIMSK|=(1<<TOIE0);

  TCCR1B|=(1<<CS12);TIMSK|=(1<<OCIE1A);        //Timer1
  OCR1A=15000;

  uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU));

  sei();

  while(1)
{

  if (update==1)
  {

    s1=uart_getc();

    if (s1==0)
    PORTD &= ~(1<<PD6);

    if (s1>0)
    {
    PORTD |= (1<<PD6);
    uart_putc(s1);
    }

  update=0;
  }


}}

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn das tatsächlich so gemacht wird, ist die Library nicht so toll:

Wie willst du jemals das Byte 0 übertragen, ohne es mit der 
Funktionsrückgabe "Keine Daten empfangen" (uart_getc()==0)
zu verwechseln?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit dem neuen Code hast du die Struktur, die ich oben skizziert habe. In 
einer Schleife Empfangen, was machen, dann Senden und zurück zum 
Schleifenanfang und das für ewig. Passt.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das hier wäre mal die Beschreibung für die Funktion.
Vielleicht habe ich etwas falsch verstanden:

unsigned int uart_getc  (  void    )

   Get received byte from ringbuffer.

Returns in the lower byte the received character and in the higher byte 
the last receive error. UART_NO_DATA is returned when no data is 
available.


Parameters:
 void

Returns:
lower byte: received byte from ringbuffer
higher byte: last receive status

0 successfully received data from UART
UART_NO_DATA
no receive data available
UART_BUFFER_OVERFLOW
Receive ringbuffer overflow. We are not reading the receive buffer fast 
enough, one or more received character have been dropped
UART_OVERRUN_ERROR
Overrun condition by UART. A character already present in the UART UDR 
register was not read by the interrupt handler before the next character 
arrived, one or more received characters have been dropped.
UART_FRAME_ERROR
Framing Error by UART

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas wrote:
> Das hier wäre mal die Beschreibung für die Funktion.
> Vielleicht habe ich etwas falsch verstanden:

Ja, das hast du gründlich missverstanden.

> unsigned int uart_getc  (  void    )

zunächst mal liefert uart_getc kein Zeichen sondern
einen Integer (also 2 Bytes) in dem sowohl das empfangene
Zeichen als auch ein möglicher Fehlerzustand kodiert
sind. Wenn du das in einem uint8_t auffängst, schmeisst du
schon mal das High Byte weg, welches die Fehlerinformation
trägt.

> Returns in the lower byte the received character and in the higher byte
> the last receive error. UART_NO_DATA is returned when no data is
> available.

Dann solltest du das auch so abfragen.
Aber zunächst mal den Returnwert von der Funktion korrekt
auffangen.
Die Funktion liefert einen unsigned int, also solltest du
den Wert von uart_getc auch in einem unsigned int speichern.

unsigned int s1;

.....


     s1 = uart_getc();

     if( s1 == UART_NO_DATA ) {   // es wurde kein Zeichen empfangen
       ....
     }

     if( ( s1 & 0xFF00 ) == 0 ) {   // Wenn das High Byte vom Ergebnis
                                    // 0 ist, dann gibt es ein gültiges
                                    // Zeichen.
        ...
     }

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok,

vielen Dank soweit für deine Hilfe.

Autor: Verwirrter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich das richtige verstehe, wurden Daten empfangen, wenn der 
Rückgabewert kleiner 256 ist...

Theoretisch müsste da auch eine Warnung vom Compiler bei der Zuweisung 
von uart_getc (16 bit) an s1 (8 bit) kommen. Womit auch die wertvollen 
Statusinformationen hopps gehen.

Diese Timer-Geschichte ist der grösste Mist und wahrscheinlich ein 
Workaround für die vernichteten Informationen.

Ich würde es mal so versuchen:

#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <uart.h>
#include <uart.c>
#include <util/delay.h>
#define UART_BAUD_RATE      9600

int main(void)
{
  uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU));
  sei();
  while(1)
  {
    uint16_t s1 = uart_getc();
    if (s1 < 256)
      uart_putc(s1);
  }
}

Autor: Verwirrter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm. Zu langsam. Müsst Ihr nicht in Bett :-)

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also schon mal danke für die Antworten !

Aber nochmal zurück auf meine eigentliche Frage:

Wie kann es sein, dass bei der Zuweisung von 2 Bytes in ein uint8_t s 
nicht eines von beiden unterschlagen wird ?

Ich werde das ganze die Tage mal Debuggen, vielleicht kann mir aber 
solange jemand auf die Sprünge helfen.

Grüße

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe jetzt auch mal 20 Bytes in die 8Bit Variabel s geschickt und 
die gibt diese auch ohne Verlust zurück ???

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Worden da ZWEI Bytes zugewiesen?
Wenn ein Byte empfangen wurde schickst du es sofort zurück. Erst im 
nächsten Durchlauf der While-Schleife wird wieder abgefragt ob ein neues 
Byte da ist, das dann gleich wieder zurückgeschickt wird. Du kannst auch 
1000000000 Bytes schicken und wirds genau 1000000000 Bytes 
zurückbekommen. Jedes Zeichen wird immer sofort wieder zurückgeschickt.

Chris

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich will ja letztendlich die übertagenen Bytes in mehrere Variabeln 
gezielt einspeichern, um eben an die Schaltung Parameter zu übergeben, 
die dort weiterverarbetet werden.
Wie könnte ich das dann realisieren ?

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#define Anzahl 16
uint8_t s[Anzahl]
uint8_t z


main
{
.
.
.
z=0;

While(1);
{
.
.
.
s[z] = uart_getc();
z += 1;
.
.
.


Zugriff dann z.B. mit bla = s[4] für das 5. empfangene Zeichen (wenn du 
normal zählen willst, am Anfang z=1 setzen).

Autor: Verwirrter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, das ist doch alles ganz anders: Die 4 Bytes werden ja nicht 
gleichzeitig gesendet sondern nacheinander. Daher wird zunächst das 
erste Byte empfangen und gleich versendet, dann das zweite usw. Deswegen 
können auch viele Bytes erfolgreiche "geechot" werden. Warum der 
ursprüngliche Code funktioniert, kann man vermuten: Das ursprüngliche 
Programm kann alle Zeichen echon ausser 0. Wenn >kein< Zeichen empfangen 
wurde, liefert uart_getc aber auch eine 0. Insofern wird von hinten 
durch die Brust ins Auge doch heraus gefunden, wann ein Zeichen 
empfangen wurde, aber eben nicht für 0-Bytes.

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.