Forum: Mikrocontroller und Digitale Elektronik Senden und Empfangen


von uz (Gast)


Lesenswert?

Tag Zusammen

Ich hab folgendes Problem ich will mit einem Atmega 32 und dem Max232 
über einen seriale zu usb adapter Daten mit hilfe des AVR Terminal 
Senden und Empfangen. Der Atmega 32 wird extern mit 7372800 herz 
getaktet. Hier der Code.


1
#include <avr/io.h>
2
#include <string.h> // Für "strcmp"
3
#include <stdlib.h> // Für "itoa"
4
#ifndef F_CPU
5
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 7372800"
6
#define F_CPU 7372800UL  // Systemtakt in Hz - Definition als unsigned long beachten 
7
                         // Ohne ergeben sich unten Fehler in der Berechnung
8
#endif
9
 
10
#define BAUD 9600UL      // Baudrate
11
 
12
// Berechnungen
13
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
14
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
15
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
16
 
17
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
18
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
19
#endif
20
21
/* UART-Init  */
22
 
23
24
void uart_init(void)
25
{
26
  UCSRB |= (1<<TXEN);  // UART TX einschalten
27
  UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1 
28
 
29
  UBRRH = UBRR_VAL >> 8;
30
  UBRRL = UBRR_VAL & 0xFF;
31
}
32
33
void uart_putchar(char c)
34
{
35
  // Warten bis Buffer bereit ...
36
  while (!(UCSRA & (1 << UDRE)))
37
    ;
38
39
  // Senden...
40
  UDR = c;
41
}
42
43
void uart_putstring(char *str)
44
{
45
  unsigned char i;
46
47
  for (i=0;i<255;i++) /* Maximal 255 Zeichen ausgeben ... */
48
  {
49
    if (str[i] != 0)
50
      uart_putchar(str[i]);
51
    else
52
      break; // Ende des Strings erreicht
53
  }
54
}
55
56
char uart_getchar()
57
{
58
  // Ist schon ein Zeichen im Buffer?
59
  if (bit_is_set(UCSRA, RXC))
60
    return UDR;
61
  else 
62
    return -1;
63
}
64
65
void uart_readline(char *str)
66
{
67
  char c;
68
  unsigned char index;
69
  
70
  index = 0;
71
72
  while (1)
73
  {
74
    c = uart_getchar();
75
    if (c != -1)
76
    {
77
      if (c == 13) /* ASCII: NewLine */
78
      {
79
        /* Ende der Zeile erreicht,
80
           also String abschließen */
81
        str[index] = 0;
82
83
        /* Funktion beenden */
84
        return;
85
      }
86
      else /* Normales Zeichen, anhängen an die Zeichenkette */
87
      {
88
        str[index] = c;
89
        index++;
90
      }
91
    }
92
  }
93
}
94
95
int main(void)
96
{
97
  char kommando[255];
98
  char temp[10];
99
  unsigned char zahl=0;
100
101
  /* RS232 einschalten ... */
102
  uart_init();
103
104
  /* Willkommensnachricht senden ... */
105
  uart_putstring("Serielle Kommunikation gestartet ...\r\n\r\n");
106
107
  while (1)
108
  {
109
    /* Auf komplettes Kommando warten ... */
110
    uart_readline(kommando);
111
112
    /* Welcher Befehl wurde geschickt? ============ */
113
114
    /* ==== BEFEHL: "version" */
115
    if (strcmp(kommando, "version")==0)
116
    {
117
      uart_putstring("OK: Version 1.00\r\n");
118
    }
119
120
    /* ==== BEFEHL: "up" */
121
    else if (strcmp(kommando, "up")==0)
122
    {
123
      if (zahl<255)
124
      {
125
        zahl++;
126
        uart_putstring("OK: Zahl wurde erhoeht\r\n");
127
      }
128
      else
129
        uart_putstring("ERROR: Maximum erreicht (Zahl=255)\r\n");
130
    }
131
132
    /* ==== BEFEHL: "down" */
133
    else if (strcmp(kommando, "down")==0)
134
    {
135
      if (zahl>0)
136
      {
137
        zahl--;
138
        uart_putstring("OK: Zahl wurde verringert\r\n");
139
      }
140
      else
141
        uart_putstring("ERROR: Minimum erreicht (Zahl=0)\r\n");
142
    }
143
144
    /* ==== BEFEHL: "show" */
145
    else if (strcmp(kommando, "show")==0)
146
    {
147
      itoa(zahl, temp, 10);
148
      uart_putstring("OK: Zahl = ");
149
      uart_putstring(temp);
150
      uart_putstring("\r\n");
151
    }
152
  }
153
154
  return 0;
155
}

Ich bekomme die Rückmeldung "Serielle Kommunikation gestartet ..." am 
AVR Terminal .Also funst RX. Das TX Singnal Kommt am Microcontroller an 
siehe Oszi Bild

Gelb Eingang R1IN
Grün Nach Max232 R2OUT
Magenta am uC an bin 14

(Befehl version)

Nur der  pin 15 am TXD vom uC bleibt still.
An was könnte das liegen ich denk mal das ist ne Software Geschichte 
verzweiflung

von ... .. (docean) Benutzerseite


Lesenswert?

if (c == 13) /* ASCII: NewLine */

Sendet dein Programm auf dem PC wirklich eine 13? oder kommt vlt was 
anderes an?

von Lord Z. (lordziu)


Lesenswert?

Tx sendet vom Controller.
Rx empfängt.

Zeig mal deinen Schaltplan und vielleicht das Oszi-Bild.

von Karl H. (kbuchegg)


Lesenswert?

uz schrieb:

> Ich bekomme die Rückmeldung "Serielle Kommunikation gestartet ..."

also geht, aus µC Sicht, schon mal das Senden

> AVR Terminal .Also funst RX. Das TX Singnal Kommt am Microcontroller an
> siehe Oszi Bild

Also am Pin 14

> Nur der  pin 15 am TXD vom uC bleibt still.

Auf dem Pin sendet der µC


Ich denke du hast da einen Haufen Mischmasch was Rx und Tx angeht.

Wir sprechen bei Rx und Tx immer aus Sicht des µC.

Rx, Pin 14.     Auf dem Pin gehts in den µC rein
Tx, Pin 15.     Auf dem Pin gehts aus dem µC raus


Und dein erstes Testprogramm sollte deutlich einfach sein.
1
int main(void)
2
{
3
  char c;
4
5
  /* RS232 einschalten ... */
6
  uart_init();
7
8
  /* Willkommensnachricht senden ... */
9
  uart_putstring("Serielle Kommunikation gestartet ...\r\n\r\n");
10
11
  while (1)
12
  {
13
    c = uart_getchar();
14
    if( c != -1 )
15
      uart_putchar( c );
16
  }
17
}

mehr nicht.
Alles was du am Terminal klimperst, wird vom µC sofort einfach nur 
zurückgeschickt. Auch den Gegentest machen: Kabel abziehen. Wenn du 
jetzt Tasten drückst, darf nichts mehr zurückgeschickt werden.

Ehe das nicht funktioniert hat es keinen Sinn, da noch 20 
fehleranfällige Softwareschichten drüberzustülpen

von Stefan B. (stefan) Benutzerseite


Lesenswert?

>   UCSRB |= (1<<TXEN);  // UART TX einschalten

Wo ist RXEN?

von uz (Gast)


Lesenswert?

Morgen
Das mit Rx und Tx hab ich wohl einwenig durcheinander gebracht.
Rxen hab ich wohl vergessen zu aktivieren was ich nach geholt hab. Das 
kleine Programm von  Karl heinz Buchegger läuft auch soweit. Jetzt ist 
noch die Frage warum läuft meins noch nicht richtig Senden und Empfangen 
läuft ja soweit aber warum funktionieren die Befehle nicht ? Wie kann 
ich nachschauen ob meine PC 16 sendet?

Danke für die Hile ich hätte nicht gedacht das mir so schnell und gut 
geholfen wird!

p.s Ich hab kein Schaltplan zur Hand aber der Aufbau stimmt ja soweit

von Karl H. (kbuchegg)


Lesenswert?

uz schrieb:

> Rxen hab ich wohl vergessen zu aktivieren was ich nach geholt hab. Das
> kleine Programm von  Karl heinz Buchegger läuft auch soweit.

Das heisst du kannst prinzipiell senden und empfangen?

> Jetzt ist
> noch die Frage warum läuft meins noch nicht richtig Senden und Empfangen
> läuft ja soweit aber warum funktionieren die Befehle nicht ?

Jetzt schlägt für dich die Stunde. Das nennt sich debugging und du wirst 
noch viele Stunden/Tage damit zubringen. Debuggen ist das Finden von 
logischen Fehlern, Dingen die man vergessen hat etc.

Aber: Du hast ja jetzt eine UART, über die du dir Ausgaben auf ein 
Terminal machen lassen kannst. Wenn du wissen willst, ob dein Programm 
an einer gewissen Stelle vorbeikommt, dann lass dein Programm einfach 
eine Ausgabe machen, dann zeigt dir das Programm mit seiner Ausgabe an, 
wo es ist und was es tut. Wenn du wissen willst, welchen Wert bestimmte 
Variablen an eine bestimmten Stelle haben, dann bau dir dort eine 
entsprechende AUsgabe rein und dein Programm schreibt dir am Terminal 
das hin was du wissen willst.

Auf Deutsch: Du kannst deine Programme jetzt mit Ausgaben spicken, die 
dir alles erzählen, was du wissen musst um Fehler zu finden. Du musst es 
nur tun.

Zum Beispiel würde ich mir an deiner Stelle in die uart_getchar 
Funktion, gleich nachdem diese Funktion ein Zeichen erhalten hat, eine 
Ausgabe rein machen, die das Zeichen auf das Terminal zurückschickt. zb 
als ASCII Code und auch in Hexadezimal damit auch Sonderzeichen wie 
Carriage Return sichtbar gemacht werden können. Du kannst auch noch 
ander Ausgaben rein geben, die dir erzählen was gerade passiert
1
void uart_readline(char *str)
2
{
3
  char c;
4
  unsigned char index;
5
  
6
  index = 0;
7
8
  while (1)
9
  {
10
    c = uart_getchar();
11
12
    if (c != -1)
13
    {
14
15
      uart_putstring( "Empfangen : +" );
16
      uart_putchar( c );
17
      uart_putstring( "+ " );
18
19
      if (c == 13) /* ASCII: NewLine */
20
      {
21
        uart_putstring( "-> Zeilenende" );
22
23
        /* Ende der Zeile erreicht,
24
           also String abschließen */
25
        str[index] = 0;
26
27
        /* Funktion beenden */
28
        return;
29
      }
30
      else /* Normales Zeichen, anhängen an die Zeichenkette */
31
      {
32
33
        uart_putstring( "-> Zeichen an Zeile anhaengen" );
34
35
        str[index] = c;
36
        index++;
37
      }
38
39
      uart_putstring( "\r\n" );
40
    }
41
  }
42
}

Du kannst dir ausgeben lassen was du willst. Es sollte nur nicht 
allzulang sein und du musst natürlich mit der Ausgabe auch etwas 
anfangen können. Diese Ausgabe ist dein Fenster in das laufende 
Programm. Durch Analysieren dieser Ausgabe und logischem Folgern musst 
du damit die Fehler und Probleme finden können.

von STK500-Besitzer (Gast)


Lesenswert?

1
void uart_readline(char *str)
2
{
3
  char c;
4
  unsigned char index;
5
  
6
  index = 0;
7
8
  while (1)
9
  {
10
    c = uart_getchar();
11
    if (c != -1)
12
    { 
13
      uart_putchar(c);
14
      if (c == 13) /* ASCII: NewLine */
15
      {
16
        /* Ende der Zeile erreicht,
17
           also String abschließen */
18
        str[index] = 0;
19
20
        /* Funktion beenden */
21
        return;
22
      }
23
      else /* Normales Zeichen, anhängen an die Zeichenkette */
24
      {
25
        str[index] = c;
26
        index++;
27
      }
28
    }
29
  }
30
}

Als Modifikation, um zu sehen, was am µC so alles ankommt, schickst du 
einfach die empfangenen Zeichen wieder zurück an den Absender.
Du solltest dann noch ein Terminalprogramm wie HTerm benutzen, das 
verschiedene Zeichen-Darstellungsformen kennt.
Es kann auch sein, dass der PC nur ein Linefeed (ASCII(10)) oder ein 
Linefeed und ein CarriageReturn sendet.
Man kann im Terminal-Programm meist angeben, welche Zeichen(-folge) am 
Zeilenende übertragen wird.
Übrigens ist es sinnvoll, alle Zeichen <32 des ASCII auszublenden, da es 
sich dabei immer umm Steuerzeichen handelt.

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.