Forum: Mikrocontroller und Digitale Elektronik Übertragung von String (DX,Y,F)


von Luffy M. (monkeydluffy)


Lesenswert?

Guten Tag,

ich versuche gerade ab dem PC Daten zum Atmega644p zu senden. Die Daten, 
die vom PC gesendet sind, sehen folgendermaße aus: "D X,Y F". Dh, der 
Atmega644p empfämgt nacheinander Befehle in Form von "D X,Y F".
D ---> Anfang der Daten
X----> X Position
Y----> Y Position
F----> Ende der Daten.

Der Atmega664p bekommt die Daten von PC über USART0 und leitet über 
USART1 die empfangenen Daten an zwei anderen Enheiten  weiter.

Wenn ich schritt für schritt der C-Code von Mikrocontroller  debugge, 
läuft die Datenübertragung in Atmega644p perfekt. Dh, der Atmega644p 
führt komplett aus, was er als Daten empfangen hat.

Aber wenn ich auf ein Mal mein  C-code von Atmega644p debugge, führt der 
Atmega644p nicht komplett aus, was er als Daten  empfangen hat.

Ich wäre sehr dankbar, wenn jemand mich unterstützt.

Mit besten Grüßen.

Mein C-Programm 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 <stdint.h> 
7
#include <util/delay.h>
8
9
#define F_CPU 9.6e6
10
#define FOSC 8000000 // Clock Speed
11
#define BAUD 115200UL
12
13
#define UBRR_VAL ((FOSC+BAUD*8)/(BAUD*16)-1)   // clever runden
14
///////////////////////////////////////////////////////////////////
15
#define usart_buffer_max_size 64u
16
#define usart_command_max_size 10
17
18
char usart_command[usart_command_max_size + 1] = {0};
19
char usart0_tx_buffer[usart_buffer_max_size];
20
char usart1_tx_buffer[usart_buffer_max_size];
21
volatile uint8_t usart_command_size = 0;
22
volatile uint8_t usart0_tx_buffer_size = 0;
23
volatile uint8_t usart0_tx_buffer_start = 0;
24
volatile uint8_t usart1_tx_buffer_size = 0;
25
volatile uint8_t usart1_tx_buffer_start = 0;
26
27
// Configuration USART0, USART1 and setting Baudrate 
28
29
void USART_Init(unsigned int ubrr)
30
{
31
  UBRR0H = (unsigned char)(ubrr>>8);
32
  UBRR0L = (unsigned char) ubrr;
33
  UBRR1H = (unsigned char)(ubrr>>8);
34
  UBRR1L = (unsigned char) ubrr;
35
  UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0) | (0<<TXCIE0) | (0<<UDRIE0);
36
  UCSR0C = (1<<USBS0) | (1<<UCSZ01) | (1<<UCSZ00);
37
  UCSR1B = (1<<RXEN1) | (1<<TXEN1) | (0<<RXCIE1) | (0<<TXCIE1) | (0<<UDRIE1);
38
  UCSR1C = (1<<USBS1) | (1<<UCSZ11) | (1<<UCSZ10);
39
} 
40
41
// Eingang vom Ringpuffer 
42
void USART0_QueueIn(char c)
43
{
44
  int i;
45
46
  if (usart0_tx_buffer_size < usart_buffer_max_size)
47
  {
48
    i = (usart0_tx_buffer_size + usart0_tx_buffer_start) % usart_buffer_max_size;
49
    usart0_tx_buffer[i] = c;
50
    ++usart0_tx_buffer_size;
51
  }
52
}
53
54
// Ausgang vom Ringpuffer 
55
char USART0_QueueOut(void)
56
{
57
  char c;
58
59
  if (usart0_tx_buffer_size == 0)
60
    return 0;
61
  c = usart0_tx_buffer[usart0_tx_buffer_start];
62
  --usart0_tx_buffer_size;
63
  usart0_tx_buffer_start = (usart0_tx_buffer_start + 1) % usart_buffer_max_size;
64
  return c;
65
}
66
67
// Eingang vom Ringpuffer 
68
void USART1_QueueIn(char c)
69
{
70
  int i;
71
72
  if (usart1_tx_buffer_size < usart_buffer_max_size)
73
  {
74
    i = (usart1_tx_buffer_size + usart1_tx_buffer_start) % usart_buffer_max_size;
75
    usart1_tx_buffer[i] = c;
76
    ++usart1_tx_buffer_size;
77
  }
78
}
79
80
// Ausgang vom Ringpuffer 
81
char USART1_QueueOut(void)
82
{
83
  char c;
84
85
  if (usart1_tx_buffer_size == 0)
86
    return 0;
87
  c = usart1_tx_buffer[usart1_tx_buffer_start];
88
  --usart1_tx_buffer_size;
89
  usart1_tx_buffer_start = (usart1_tx_buffer_start + 1) % usart_buffer_max_size;
90
  return c;
91
}
92
93
// Sendung einer Antwort über der Ringpuffer zum USART0 
94
static void USART0_Send(const char *s)
95
{
96
  int i;
97
  
98
  for (i = 0; s[i] != 0; ++i)
99
    USART0_QueueIn(s[i]);
100
  if (usart0_tx_buffer_size > 0)
101
    UCSR0B |= 1 << UDRIE0;
102
}
103
104
// Sendung eines Befehls über der Ringpuffer zum USART1 
105
static void USART1_Send(const char *s)
106
{
107
  int i;
108
  
109
  for (i = 0; s[i] != 0; ++i)
110
    USART1_QueueIn(s[i]);
111
  if (usart1_tx_buffer_size > 0)
112
    UCSR1B |= 1 << UDRIE1;
113
}
114
115
// Verarbeitung eines Befehls
116
static void ProcessCommand(void)
117
{
118
  int i;
119
  int x;
120
  int y;
121
  char x_moteur[12];
122
  char y_moteur[12];
123
124
  
125
  for (i = 0; i < usart_command_size; ++i)
126
    if (usart_command[i] == ',')
127
      break;
128
129
  if (i <= 0 || i >= usart_command_size - 1)
130
  {
131
    // Man hat kein Kommazeichen in Mitte des Strings gefunden -> Fehler 
132
    USART0_Send("\x15");  // NAK, Sendung von Data hat nicht geklappt. 
133
    usart_command_size = 0;
134
    return;
135
  }
136
  // Ich wandle x und y in Integer um, um Berechnung durchzuführen, wenn es nötig ist
137
  // Extraktion von X und Y   
138
    usart_command[i] = 0;
139
    usart_command[usart_command_size] = 0;
140
    x = atoi(usart_command);
141
    y = atoi(usart_command + i + 1);
142
    usart_command_size = 0;
143
  itoa(x, x_moteur, 10);
144
    itoa(y, y_moteur, 10);
145
146
      // Sendung position x_moteur 
147
   USART1_Send("#1s");
148
   USART1_Send(x_moteur);
149
   USART1_Send("\r");
150
151
   USART1_Send("#1A\r"); // Losfahren der Platine auf die x-Achse
152
  
153
       // Sendung position y_moteur 
154
   USART1_Send("#2s");
155
   USART1_Send(y_moteur);
156
   USART1_Send("\r");
157
158
   USART1_Send("#2A\r"); // Losfahren der Platine auf die y-Achse
159
   USART0_Send("\x06"); // ACK ---> Freigabe: PC kann der nächste Data senden
160
  
161
  
162
  }
163
164
// La fonction d´interruption de reception du byte 
165
// Cette fonction est active lorsque RXCIE0 = 1  
166
ISR(USART0_RX_vect)
167
{
168
  char data;
169
  data = UDR0;
170
171
 // Verarbeitung des Befehls -->("D X,Y F") 
172
  // X = x_moteur und Y = y_moteur 
173
  if (data == 'F')
174
  {    
175
    ProcessCommand();
176
     
177
   }
178
179
  else if (data == 'D')
180
  {
181
    /* Erzeugung eines neuen Befehls */
182
    usart_command_size = 0;
183
  }
184
185
  else
186
  {
187
    // Als man weder F, noch D empfängt, speichert man 
188
  //die Koordinatenposition(X,Y) in einem Befehl 
189
    if (usart_command_size < usart_command_max_size)
190
    {
191
      usart_command[usart_command_size] = data;
192
      ++usart_command_size;
193
    }
194
  }
195
}
196
197
// Interruptsfunktion für Byte-Übertragung 
198
// Diese Funktion ist an, wenn UDRIE1 = 1 
199
ISR(USART0_UDRE_vect)
200
{
201
  UDR0 = USART0_QueueOut();
202
  // Sendung stoppen, wenn es keine Daten mehr gibt zu senden 
203
  if (usart0_tx_buffer_size == 0)
204
    UCSR0B &= ~(1 << UDRIE0);
205
}
206
207
// Interruptsfunktion für Byte-Übertragung 
208
// Diese Funktion ist an, wenn UDRIE1 = 1 
209
ISR(USART1_UDRE_vect)
210
{
211
  UDR1 = USART1_QueueOut();
212
  // Sendung stoppen, wenn es keine Daten mehr gibt zu senden 
213
  if (usart1_tx_buffer_size == 0)
214
    UCSR1B &= ~(1 << UDRIE1);
215
}
216
217
void VorEinstellungMotor(void)
218
 { 
219
   USART1_Send("#1|0\r"); // Deaktivierung von Antwort der Motorsteuerung Nr 1
220
   USART1_Send("#2|0\r"); // Deaktivierung von Antwort der Motorsteuerung Nr 2
221
   USART1_Send("#1D0\r"); // Festlegen der Position der Platine als Ursprung auf die x-Achse 
222
   USART1_Send("#2D0\r"); // Festlegen der Position der Platine als Ursprung auf die y-Achse
223
   USART1_Send("#1p2\r"); // Modus: Absolut Positionierung --> p=2 
224
   USART1_Send("#2p2\r"); // Modus: Absolut Positionierung --> p=2
225
           
226
 }
227
228
int main (void)
229
{ 
230
  USART_Init(UBRR_VAL); // Initialisierung von USART0 and USART1
231
  VorEinstellungMotor(); // Initialisierung Motorsteuerung
232
  sei(); // Aktierung Interruptsfunktion
233
234
  while (1) // Endlosschleife
235
  {
236
      
237
  }
238
  
239
}

von Daniel V. (danvet)


Lesenswert?

Vielleicht liegt es daran, dass du in der Receive-Interruptroutine schon 
anfängst zu senden.
Besser: in der Mainloop schauen, ob was im Puffer steht und dann senden.
In der Interrupt-Routine so wenig machen wie möglich. Da solltest du 
schnell wieder raus kommen.

von Luffy M. (monkeydluffy)


Lesenswert?

Danke  Daniel V. für deine schnelle Antwort.

>Besser: in der Mainloop schauen, ob was im Puffer steht und dann senden.
>In der Interrupt-Routine so wenig machen wie möglich. Da solltest du
>schnell wieder raus kommen.

Kannst du mir bitte ein Beispiel vorschlagen ??

Danke im Voraus.

von Daniel V. (danvet)


Lesenswert?

Luffy Monkey schrieb:
> Danke  Daniel V. für deine schnelle Antwort.
>
>>Besser: in der Mainloop schauen, ob was im Puffer steht und dann senden.
>>In der Interrupt-Routine so wenig machen wie möglich. Da solltest du
>>schnell wieder raus kommen.
>
> Kannst du mir bitte ein Beispiel vorschlagen ??
>
> Danke im Voraus.

Echt jetzt? Ich hätte aus deinem Code vermutet, dass du diese 
Kleinigkeit auch noch hinbekommst.
1
volatile uint8_t command_ready = 0;
2
3
4
5
// La fonction d´interruption de reception du byte 
6
// Cette fonction est active lorsque RXCIE0 = 1  
7
ISR(USART0_RX_vect)
8
{
9
  char data;
10
  data = UDR0;
11
12
 // Verarbeitung des Befehls -->("D X,Y F") 
13
  // X = x_moteur und Y = y_moteur 
14
  if (data == 'F')
15
  {    
16
    command_ready = 1;
17
     
18
   }
19
20
  else if (data == 'D')
21
  {
22
    /* Erzeugung eines neuen Befehls */
23
    usart_command_size = 0;
24
  }
25
26
  else
27
  {
28
    // Als man weder F, noch D empfängt, speichert man 
29
  //die Koordinatenposition(X,Y) in einem Befehl 
30
    if (usart_command_size < usart_command_max_size)
31
    {
32
      usart_command[usart_command_size] = data;
33
      ++usart_command_size;
34
    }
35
  }
36
}
37
38
39
int main (void)
40
{ 
41
  USART_Init(UBRR_VAL); // Initialisierung von USART0 and USART1
42
  VorEinstellungMotor(); // Initialisierung Motorsteuerung
43
  sei(); // Aktierung Interruptsfunktion
44
45
  while (1) // Endlosschleife
46
  {
47
    if(command_ready)
48
    {
49
      ProcessCommand();
50
      command_ready = 0;
51
    }      
52
  }
53
  
54
}

nur so auf die Schnelle

von Luffy M. (monkeydluffy)


Lesenswert?

Vielen Dank Daniel V. .

Ich probiere mal dein Vorschlag.

Danke noch mal.

von иммэр эин нэуёр намэ (Gast)


Lesenswert?

Es gibt Verschiedenes zu bemaengeln.
- QueueIn() geht davon aus, dass die Queue eh genug Platz hat. Wenn 
voll, geht's in den Dreck.

von Karl H. (kbuchegg)


Lesenswert?

Jungs - hatten wir alles schon

Beitrag "Empfangen und Übertragung von Daten über USART"

Ich will niemanden abhalten ihm zu helfen, aber wenn wir ehrlich sind, 
läuft es darauf hinaus, dass ihm das wer schreiben muss.

von Luffy M. (monkeydluffy)


Lesenswert?

иммэр эин нэуёр намэ schrieb:

> Es gibt Verschiedenes zu bemaengeln.
> - QueueIn() geht davon aus, dass die Queue eh genug Platz hat. Wenn
> voll, geht's in den Dreck.

 Bei mir hat QueueIn() genug Platz, um Daten zu bekommen.
Dataform: "DX,YF"
X ----> Höchsten 5 Zeichen in ASCii
Y ----> Höchsten 5 Zeichen in ASCii

Die Übertragung von Daten erfolgt nacheinander, so dass die QueueIn() 
immer genug Platz hat, um Zeichen zu empfangen.

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.