Forum: Mikrocontroller und Digitale Elektronik Aufbau einer Kommunikation zwischen pc und USART0


von Luffy M. (monkeydluffy)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche zur Zeit eine Kommunikation zwischen ein PC und ein 
Atmega644p aufzubauen.

Eigentlich möchte ich Charakter in form von Byte über eine serielle 
Schnittstelle RS232 vom PC zum Atmega644p senden. Ich habe ein Programm 
in c++ geschrieben, um die Charakter zum Mikrocontroller Atmega644p zu 
senden. Danach habe ich ein c-Code  für den Mikrocontroller geschrieben, 
um die Charakter im Puffer UDR0 von USART0 zu erhalten. Dann soll wieder 
die empfangenen Charakter von UDR0 in Richtung des PCs übertragen, um 
die Funktion ReadFile() von der c++-Programm zu testen.

Ich habe ein Test durchgeführt und habe festgestellt, dass der Puffer 
UDR0 ewig auf Charakter von PC wartet, obwohl ich der pin RXC0 manuell 
aktiviert habe. Eigentlich bekommt der Puffer UDR0 keine Charakter. Was 
kann das Problem sein ?

Stimmt zufällig was nicht in mein c- und c++ Code ? Wenn ja, dann würde 
ich mich freuen, wenn sie mir helfen.

Im Anhang liegt meine Datei.

MFG

monkeydluffy

von Stefan (Gast)


Lesenswert?

Du solltest nicht zwei Programm gleichzeitig schreiben und dann 
gegeneinander testen.

Tausche das PC Programm durch ein anderes aus, bei dem Du weisst, dass 
es funktioniert (z.B. Hyperterminal von WIndows XP, oder Cutecom oder 
Hammer Terminal).

Dann nimm erstmal den Mikrocontroller aus seinem Sockel heraus un 
verbinde die RxD und TxD Pins des Sockel mit einem Drahtstück.

Dann sendest Du irgendwelche Zeichen mit dem PC. Wenn die Hardware Ok 
ist, kommen die gesendeten Zeichen als Echo zurück zum PC (wegen der 
Drahtschleife).

Erst dann würde ich mich an die Programmierung des Mikrocontrollers 
wagen. Und wenn der dann mit dem Terminalprogramm zusammen arbeitet, 
dann tausche das Terminalprogramm durch dein selbst geschriebenes aus.

von Luffy M. (monkeydluffy)


Lesenswert?

Hallo,

ich habe deine Tipps befolgen und habe  versucht, ein Charakter 'X' von 
Hyperterminal in die Variable c zu schreiben und dann der Wert von c 
wieder über die Schnittstelle  zum Hyperterminal zu senden. Leider läuft 
mein Experiment nicht.
Als Einstellung für Hyperterminal habe ich folgende Daten übernommen:

- Bits pro Sekunde : 112500
- Datenbits:           8
- Parität:            Keine
- Stoppbits:            2
- Flusssteuerung:      Keine

Die Implementierung des Mikrocontrollers lautet:
1
#include <avr/io.h>
2
#include <avr/interrupt.h> 
3
#include <stdio.h>
4
#include <stdlib.h>
5
#include <string.h>
6
// #include "uart.h"
7
#include <avr/pgmspace.h>
8
9
#define FOSC 8000000 // Clock Speed
10
#define BAUD 115200UL
11
12
// Berechnungen zur Baudrate:
13
14
#define UBRR_VAL ((FOSC+BAUD*8)/(BAUD*16)-1)   // clever runden
15
16
/****************************************************/
17
void USART_Init (unsigned int ubrr)
18
{
19
  UBRR0H = (unsigned char)(ubrr>>8);
20
  UBRR0L = (unsigned char) ubrr;
21
  UBRR1H = (unsigned char)(ubrr>>8);
22
  UBRR1L = (unsigned char) ubrr;
23
  
24
  UCSR0B = (1<<RXEN1) | (1<<TXEN0) |(0<<RXCIE0)|(0<<TXCIE0);
25
  UCSR0C = (1<<USBS0) | (0<<UCSZ02)|(1<<UCSZ01)|(1<<UCSZ00);
26
  
27
} 
28
29
/**********************************************************/
30
31
/*-- function receive USART0 --*/
32
33
  unsigned char USART0_Receive (void)
34
{
35
    while(!(UCSR0A & (1<<RXC0)) ) // warten bis Zeichen verfuegbar
36
    ;
37
  return UDR0; // Zeichen aus UDR an Aufrufer zurueckgeben
38
}
39
40
41
/*-- function transmit USART0 --*/
42
43
void USART0_Transmit (unsigned char data0)
44
{
45
  while ( !(UCSR0A & (1<<UDRE0)) )// warten bis Senden moeglich 
46
 
47
  UDR0 = data0;
48
} 
49
50
/**********************************************************/
51
52
/*-Aktivierung der Datenübertragung über RS485 von USART1-*/
53
54
 void RS485_Init (void)
55
{
56
  DDRD = (1<<PD4)|(1<<PD3)|(1<<PD5);//Steuer- und Datenausgang aktivieren
57
  PORTD = (1<<PD4);  //auf Senden stellen (Aktivierung Datensendung)
58
} 
59
60
61
int main (void)
62
63
{ 
64
  unsigned char c ;
65
66
  USART_Init(UBRR_VAL) ;  // USART Initialisierung
67
  RS485_Init (); // serielle Schnittstelle USART1
68
69
  while(1)
70
71
  {
72
 
73
/*-- Test USART0 (Receive and Transmit) --*/
74
    
75
//     USART0_Transmit('X');
76
77
    c = USART0_Receive();
78
79
    USART0_Transmit(c);
80
}
81
82
}

Hat jemand Lösungsvorschläge, damit ich der Test mit Erfolgreich 
durchführen kann.

Danke im Voraus.

von Luffy M. (monkeydluffy)


Lesenswert?

Hi,

>> ich habe deine Tipps befolgen und habe  versucht, ein Charakter 'X' von
>> Hyperterminal in die Variable c zu schreiben und dann der Wert von c
>> wieder über die Schnittstelle  zum Hyperterminal zu senden.

Als ich mein Programm debuggt, stelle ich fest, dass der Mikrocontroller 
der Charakter 'X' empfängt, der vom Hyperterminal gesendet wurde.

Allerdings soll wieder der empfangene Charakter 'X'  zum Hyperterminal 
über die serielle Schnittstelle übertragen. Leider läuft dieser Schritt 
meines Programm nicht. Im laufe des Debuggings wird die Funktion 
USART0_Transmit nicht vollständig ausgeführt. Irgendwie landet wieder 
der Charakter 'X' nicht in Hyperterminal.

Bitte, was stimmt eigentlich nicht in meinem Programm ?

Danke im Voraus.

von Karl H. (kbuchegg)


Lesenswert?

Nimm hier mal den Kommentar weg
1
void USART0_Transmit (unsigned char data0)
2
{
3
  while ( !(UCSR0A & (1<<UDRE0)) )// warten bis Senden moeglich 
4
 
5
  UDR0 = data0;
6
}

dann steht da
1
void USART0_Transmit (unsigned char data0)
2
{
3
  while ( !(UCSR0A & (1<<UDRE0)) )
4
  UDR0 = data0;
5
}

und jetzt rückst du auch noch den Code richtig ein und zwar so, wie der 
COMpiler das ganze sieht
1
void USART0_Transmit (unsigned char data0)
2
{
3
  while ( !(UCSR0A & (1<<UDRE0)) )
4
    UDR0 = data0;
5
}

dann steht da:
Solange Senden nicht möglich ist, füttere das UDR0 Register.
Sobald Senden wieder möglich ist, mache nichts mehr.


Da fehlt ein ; der der while Schleife die richtige Bedeutung verpasst.

von Luffy M. (monkeydluffy)


Lesenswert?

Hallo,

Karl Heinz Buchegger, danke schön für dein Feedback.

Karl schrieb:

>> Da fehlt ein ; der der while Schleife die richtige Bedeutung verpasst.

Was meinst du da bitte ? Ich verstehe dein Hinweis nicht.

Danke im Voraus.

von Karl H. (kbuchegg)


Lesenswert?

Luffy Monkey schrieb:
> Hallo,
>
> Karl Heinz Buchegger, danke schön für dein Feedback.
>
> Karl schrieb:
>
>>> Da fehlt ein ; der der while Schleife die richtige Bedeutung verpasst.
>
> Was meinst du da bitte ? Ich verstehe dein Hinweis nicht.

Dabei hab ich so sehr versucht, herauszuarbeiten, was da passiert ohne 
den Fehler konkret zu benennen. (Am meisten lernt man immer noch, wenn 
man seine Fehler selbst findet.)


Wie soll die Logik in dieser Funktion sein?
( ===> Sollverhalten)


Wie ist die niedergeschriebene Logik tatsächlich?
( ===> Istverhalten)


OK. Ein Hinweis
Was ist der Unterschied zwischen (Pseudocode der sich an C anlehnt)
1
  Motor ein;
2
  while( ! Endschalter hat ausgelöst )
3
    ;
4
  Motor aus;
und
1
  Motor ein;
2
  while( ! Endschalter hat ausgelöst )
3
  Motor aus;

von Luffy M. (monkeydluffy)


Lesenswert?

Hallo nochmal,

>> OK. Ein Hinweis
>> Was ist der Unterschied zwischen (Pseudocode der sich an C anlehnt)

>>  Motor ein;
>>  while( ! Endschalter hat ausgelöst )
    ;
>>  Motor aus;

>>und

>>  Motor ein;
>>  while( ! Endschalter hat ausgelöst )
>>  Motor aus;

Ich vermute, die Anwesenheit in obere Block des Semikolons ';' allein in 
eine Zeile ohne Anweisung verursacht der Unterschied mit dem unteren 
Block.

von Uwe (Gast)


Lesenswert?

Nö. Falsch, setzen und C Buch lesen.

Guck doch mal im Debugger nach was passiert.

von Karl H. (kbuchegg)


Lesenswert?

Uwe schrieb:
> Nö. Falsch,

Jein.

> setzen und C Buch lesen.

Das allerdings.
Denn das sind wichtige Dinge. Wenn man das nicht erkennt, selbst wenn es 
einem auf einem Silbertablett serviert wird, dann lässt das tief über 
das Verständnis der Grundlagen des AUfbaus von Kontrollstrukturen 
blicken.

von Uwe (Gast)


Lesenswert?

Hätte man auch so schreiben könnnen. Ob das Semikolon alleine in einer 
Zeile steht ist egal.

main()
{
  int a=0;
  while( ! Endschalter hat ausgelöst );
  a=100;
}

und

main()
{
  int a=0;
  while( ! Endschalter hat ausgelöst )
  a=100;
}

von Luffy M. (monkeydluffy)


Lesenswert?

Hallo nochmal,

danke schön Uwe und Karl Heinz Buchegger für die ausführlichen 
Erklärungen. Ich habe jetzt der Unterschied zwischen die beide Blöcke 
verstanden.
1
main()
2
{
3
  int a=0;
4
  while( ! Endschalter hat ausgelöst );
5
  a=100;
6
}

Im oberen Fall gehört die Variable a  nicht zu der while-Schleife.
1
main()
2
{
3
  int a=0;
4
  while( ! Endschalter hat ausgelöst )
5
  a=100;
6
}

Im unteren Fall gehört die Variable a zu der while-Schleife.

Ich habe einfach  meine Fehler  übersehen, obwohl Karl mir alles  gut 
erklärt hat. Machmal bin ich wirklich dumm.

Vielen Dank noch für ihre Hilfe.

mfg

von Luffy M. (monkeydluffy)


Lesenswert?

Hallo,

ich wollte mich nochmal bei euch bedanken. Ich habe geschafft, die 
Kommunikation zwischen dem PC und dem Mikrocontroller Atmega644p 
aufzubauen. Meine c und C++ Code sind kompatibel und laufen einwandfrei, 
so dass der PC und der Mikrocontroller kommunizieren können.

Vielen für eure Hilfe

Monkey Luffy

von Luffy M. (monkeydluffy)


Angehängte Dateien:

Lesenswert?

Morgen,

mit eueren Hilfen habe ich geschafft, die Kommunikation zwischen dem PC 
und dem Mikrocontroller aufzubauen.

Mein Ziele war die Übertragung von Charakter 0,1,2,3,4 von PC zum 
Mikrocontroller über die Serielle Schnittstelle RS232. Dann sollte die 
Routine des Mikrocontrollers wieder die empfangenen Charakter in die 
gleiche serielle Schittstelle zurückschicken, so dass man folgende 
Ergebnisse auf einem Fenster bekommt:

0 : 0
1 : 1
2 : 2
3 : 3
4 : 4

Als ich meine beide Code debuggt habe, habe ich folgende Resultat 
erhalten:

0 :
1 : 0
2 : 1
3 : 2
4 : 3

Ich bekomme eine Byte-verschiebung und ich weiße nicht, wie ich dieser 
Fehler korrigieren kann.

Weiß jemand, wie ich mein problem lösen kann ?

Danke im Voraus.

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.