Forum: PC-Programmierung C#:Wie Nachricht vom Mikrocontroller über dem Com-Port empfangen


von André K. (staind)


Lesenswert?

Hallo,

Bin leider noch blutiger Anfänger im programmieren von uC.
(Bin vor 2 Wochen angefangen mit dem assembler Programmieren, sitze aber 
teilweise Nachmittags 6-8 Stunden vor mein mC und versuche assembler zu 
verstehen, was auch eigentlich ganz gut klappt :-) )
also ich bin momentan voll im rausch zu lernen wie man uC programmiert 
und wie man sie benutzt.

Habe das einsteiger set von Myavr. Dort geht es im aktuellen Kapitel um 
das Senden über den Com Port.

Das assembler Programm funktioniert so weit. Also der uC sendet das wort 
"Hallo " über das UART Datenregister. Dieses kann ich auch mit der 
beigefügten Software myAVR Controlcenter Build 698 am Pc empfangen.

Hier mal das mC Programm
1
;+-----------------------------------------------------------------------------
2
;| Title      : Assembler Grundgerüst für ATmega8
3
;+-----------------------------------------------------------------------------
4
;| Funktion   : ...
5
;| Schaltung  : ...
6
;+-----------------------------------------------------------------------------
7
;| Prozessor  : ATmega8
8
;| Takt       : 3,6864 MHz
9
;| Sprache    : Assembler
10
;| Datum      : ...
11
;| Version    : ...
12
;| Autor      : ...
13
;+-----------------------------------------------------------------------------
14
.include        "AVR.H"
15
;------------------------------------------------------------------------------
16
begin:
17
    rjmp    main                        ; RESET External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset
18
    reti                                ; INT0 External Interrupt Request 0
19
    reti                                ; INT1 External Interrupt Request 1
20
    reti                                ; TIMER2 COMP Timer/Counter2 Compare Match
21
    reti                                ; TIMER2 OVF Timer/Counter2 Overflow
22
    reti                                ; TIMER1 CAPT Timer/Counter1 Capture Event
23
    reti                                ; TIMER1 COMPA Timer/Counter1 Compare Match A
24
    reti                                ; TIMER1 COMPB Timer/Counter1 Compare Match B
25
    reti                                ; TIMER1 OVF Timer/Counter1 Overflow
26
    reti                                ; TIMER0 OVF Timer/Counter0 Overflow
27
    reti                                ; SPI, STC Serial Transfer Complete
28
    reti                                ; USART, RXC USART, Rx Complete
29
    reti                                ; USART, UDRE USART Data Register Empty
30
    reti                                ; USART, TXC USART, Tx Complete
31
    reti                                ; ADC ADC Conversion Complete
32
    reti                                ; EE_RDY EEPROM Ready
33
    reti                                ; ANA_COMP Analog Comparator
34
    reti                                ; TWI 2-wire Serial Interface
35
    reti                                ; SPM_RDY Store Program Memory Ready
36
;------------------------------------------------------------------------------
37
main:
38
    ldi r16,hi8(RAMEND)                ; Main program start
39
    out SPH,r16                        ; Set Stack Pointer to top of RAM
40
    ldi r16,lo8(RAMEND)
41
    out SPL,r16
42
    sbi UCSRB,3
43
    ldi r16, 23
44
    out UBRRL,r16
45
;------------------------------------------------------------------------------
46
mainloop:  wdr
47
  ldi r16,'H'
48
  rcall putChar
49
  ldi r16,'a'
50
  rcall putChar 
51
  ldi r16,'l'
52
  rcall putChar
53
  ldi r16,'l'
54
  rcall putChar
55
  ldi r16,'o'
56
  rcall putChar 
57
  ldi r16,' '
58
  rcall putChar                        
59
  rjmp  mainloop
60
;------------------------------------------------------------------------------
61
putChar:   sbis UCSRA,5
62
  rjmp putChar
63
  out UDR,r16
64
  ret
65
------------------------------------------------------------------------



Jetzt möchte ich allerdings dieses über mein C# Programm Empfangen.
Dort weiß ich aber noch nicht wie ich dieses realisieren kann.
Das Wort "Hallo" soll einfach nur zusammengesetzt, und in einer TextBox 
ausgegeben werden sobald ich den button1 drücke.
Der Port an dem mein uC sitzt ist der Com Port 3.

Hier mein aktuelles C# Programm (in C# kenne ich mich eingentlich gut 
aus)
1
using System;
2
using System.Collections.Generic;
3
using System.ComponentModel;
4
using System.Data;
5
using System.Drawing;
6
using System.Linq;
7
using System.Text;
8
using System.Windows.Forms;
9
using System.IO.Ports;
10
11
namespace WindowsFormsApplication1
12
{
13
    public partial class Form1 : Form
14
    {
15
        SerialPort port = new SerialPort("COM3",9600,Parity.None,8,StopBits.One);
16
17
        public Form1()
18
        {
19
            InitializeComponent();
20
        }
21
22
        private void button1_Click(object sender, EventArgs e)
23
        {
24
            textBox1.Text = "???";
25
        }
26
    }
27
}

Es wäre nett wenn mir einer das Programm zu ende programmieren würde. 
Vielleicht erkenne ich die funktionsweise so. Ansonsten würde ich noch 
1-2 fragen stellen :-)

mfg André

von Karl H. (kbuchegg)


Lesenswert?

André Klaus schrieb:

>         private void button1_Click(object sender, EventArgs e)
>         {
>             textBox1.Text = "???";


Da wirst du wohl das SerialPort Objekt befragen müssen, ob es etwas 
empfangen hat.

Aber der ganze Ansatz ist so erst mal verquert. Denn du hast vom PC aus 
keine Kontrolle darüber, was der µC macht. Der sendet ja ständig und 
nicht nur wenn du in deiner Form den Button klickst.

von Sven H. (dsb_sven)


Lesenswert?

Du musst "port" noch einen Eventhandler für das Empfangen von Daten 
hinzufügen. (Schau mal beim Intellisense nach den Funktionen mit dem 
Blitz.)

Wenn dir das zu kompliziert erscheint, kannst du auch eine serielle 
Schnittstelle im GUI Designer auf dein Form ziehen und die Eigenschaften 
im Properties-Fenster einstellen. Ein Doppelklick auf die Schnittstelle 
(für normal werden solche Controls, die nicht grafisch angezeigt werden, 
im unteren Bereich des Bildschirms dargestellt) erstellt dann 
automatisch den benötigten Eventhandler für das Empfangen von Daten. 
(Ist das Standardevent für die Serielle).


Dann musst du die Daten vom Port sammeln, bis du gültige Daten empfangen 
hast. (Der Eventhandler wird immer ausgeführt wenn Daten empfangen 
wurden, d.h. eventuell nach einem Byte oder nach mehreren.)

Ich schreibe im Eventhandler die Daten meistens nur in eine geeignete 
Datenstruktur (List<string> oder List<char> sind ganz cool. Queue<T> 
geht auch) um sie dann an anderer Stelle auszuwerten...

von Sam .. (sam1994)


Lesenswert?

Sven H. schrieb:
> Ich schreibe im Eventhandler die Daten meistens nur in eine geeignete
> Datenstruktur (List<string> oder List<char> sind ganz cool. Queue<T>
> geht auch) um sie dann an anderer Stelle auszuwerten...

Für was List<char> ? Das ist einfach ein string.

Wenn man etwas sendet und auf eine Antwort wartet sollte man lieber Read 
+ TimeOut nehmen.

von Sven H. (dsb_sven)


Lesenswert?

List<char> ist kein String.

List<T> stellt eine generische Liste dar. D.h. jenachdem, was ich in die 
<> schreibe, kann die Liste einen anderen Datentypen aufnehmen.

Ein Array in der Form char[] würde in c# am nächsten an einen String ran 
reichen. Obwohl der String in c# eine deutlich komplexere Strucktur ist 
als ein Array mit chars...


List<char> hat die nette Methote "Add(char)" mit der man nach belieben 
chars zur Liste hinzufügen kann. Kommt natürlich im Endeffekt das 
gleiche raus, wenn ich den char an nen String dran hänge... Klassicher 
Fall von Overengeneering.

von André W. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo André,
ich hab mal schnell mit SiSy AVR++ ein C#-Programm erstellt. Die 
Archivdatei heißt Terminal.sax (ist ein SiSy-Archiv). Zur Anmerkung: Ich 
habe eine RichTextBox verwendet, da nur ein Text-Feld schlecht 
ausgewertet werden kann.
Wie Karl-Heinz schon erwähnt hat sendet ja der Mikrocontroller ständig.
Kannst dir das ja mal anschauen.

Gruß André

von André W. (Gast)


Angehängte Dateien:

Lesenswert?

Hab das Ganze jetzt nochmal etwas übersichtlicher gestaltet. Allerdings 
gibt es noch etwas Probleme beim automatischen Umschalten in den 
Datenmodus. Das muss jetzt erstmal mit der Hand gemacht werden.
In der Zip-Datei ist der generierte Quellcode von SiSy.

von jonas biensack (Gast)


Lesenswert?

So nicht! Starte einen Thread im Hintergrund, dafür schreibst du eine 
eigene Klasse oder erweiterst die Klasse Thread, oder implementierst das 
Interface Runnable. Diese Klasse sammelt die Daten vom Port und wertet 
sie auch aus.
Über invokes werden dann dein Hauptthread mit den Daten gefüllt! So geht 
das, ansonsten blockiert dir deine GUI komplett wenn du viele Daten 
sendest oder empfängst! Wichtig ist noch, baue bei großen Datenmengen 
kleine Pausen zwischen den Senden von Daten ein, (alle 512 bytes eine 
Millisekunde), sonst verschluckt sich dein PC...

Wenn fragen?!...


gruß jonas

von Sam .. (sam1994)


Lesenswert?

Sven H. schrieb:
> List<char> ist kein String.
Kann aber genau das gleiche.

> List<T> stellt eine generische Liste dar. D.h. jenachdem, was ich in die
> <> schreibe, kann die Liste einen anderen Datentypen aufnehmen.
Das weiß ich, du sprachst allerdings von List<char> und der Type kann 
kein anderen Type aufnehmen.

> Ein Array in der Form char[] würde in c# am nächsten an einen String ran
> reichen. Obwohl der String in c# eine deutlich komplexere Strucktur ist
> als ein Array mit chars...
Das wäre schneller, allerdings nicht dynamisch.

> List<char> hat die nette Methote "Add(char)" mit der man nach belieben
> chars zur Liste hinzufügen kann. Kommt natürlich im Endeffekt das
> gleiche raus, wenn ich den char an nen String dran hänge... Klassicher
> Fall von Overengeneering.

Die Liste kann weniger ist aber dafür schneller als der String. Ich 
würde wenn es um Geschwindigkeit geht char[] nehmen, sonst string, da es 
komfortabler ist.

jonas biensack schrieb:
> Wichtig ist noch, baue bei großen Datenmengen
> kleine Pausen zwischen den Senden von Daten ein, (alle 512 bytes eine
> Millisekunde), sonst verschluckt sich dein PC...
Schaden kann es sicherlich nicht. Allerdings sende ich vom µC 16KB 
Blöcke (bei 38400Baud) und der PC hat sich noch nie "verschluckt".

von André W. (Gast)


Lesenswert?

Der Mikrocontroller sendet ja nur mit 9600 Baud. Es kommt ja alles an. 
Das Programm funktioniert auch ohne Probleme, solange der mySmartUSB MK2 
Programmer per Hand in den Datenmodus versetzt wird und später beendet 
wird.
Das Problem bei dem kleinen Beispiel ist, dass ein Thread-Event 
aufgerufen wird, solange wie Daten ankommen, schreibe die Daten in die 
Text-Box. Und da der Mikrocontroller ständig sendet, kommt man nicht in 
den Thread der GUI. Ich werde deshalb das Programm noch etwas umstellen.

von André W. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo, sorry das ich mich erst jetzt wieder melde. Ich hab das Programm 
nochmal etwas überarbeitet. Ihr könnt euch ja mal das Klassendiagramm 
dazu anschauen. In der zip-Datei ist der von SiSy generierte Quellcode 
zu finden. Das sollte jetzt in dem Sinne das darstellen, was André Klaus 
haben wollte.

von Jonas H. (Gast)


Lesenswert?

Hallo Andre,

was hast du für ein SiSy? Mit meinem kann ich nur C++ für den AVR aber 
kein C#. Ich kann dein projekt nicht übersetzen :( was muss ich tun?

Gruß´J.

von André W (Gast)


Lesenswert?

Hallo Jonas,
das ist ein aktuelles SiSy AVR++ in der Version 3.10. Mit dieser Ausgabe 
ist auch die Programmierung von Windows Programmen mit der UML möglich. 
Mit der normalen AVR Ausgabe wird das wohl bei dir gar nicht so einfach 
gehen.

Gruß André

von Jonas H. (Gast)


Lesenswert?

alles klar danke... hab da wohl noch ne ziemlich alte 2.18 und nur AVR 
... na schau ich mich mal um grins

Grüße J.

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.