Forum: Compiler & IDEs Zeichenketten ueber UART


von Owen S. (senmeis)


Lesenswert?

Hi,

ich nutze IAR zur Entwicklung des AVR. Mit dem folgenden Code möchte ich 
einfach eine Zeichenkette über UART senden lassen. Es kommt aber vor, 
dass mit dem nachstehenden Code
1
 temp = Usart_Rx();
 die UART Übertragung verfälscht wird (0x31, 0x32, 0x01, 0x01, 0x35 
statt 0x31, 0x32, 0x33, 0x34, 0x35), mit
1
 while(1);
 danach ist alles OK.

Der Code ist hier. Hat das mit dem Timing zu tun?
1
unsigned char temp;
2
static char enter = 1;
3
unsigned char str[] = "12345";
4
5
if (enter)
6
{
7
  enter = 0;
8
  uart_put_string(str);
9
}
10
else
11
{        
12
    temp = Usart_Rx();
13
//while(1);
14
}
15
16
char Usart_Rx(void)
17
{
18
    while (!(UCSR0A & (1<<RXC0)));
19
    return UDR0;
20
}
21
22
void uart_put_string (unsigned char *data_string)
23
{
24
    while(*data_string) Usart_Tx(*data_string++);
25
}

Gruss
Owen

von Michael D. (etzen_michi)


Lesenswert?

Was mir erstmal auffällt:
1
if (enter)
2
{
3
  enter = 0;
4
  uart_put_string(str);
5
}
6
else
7
{        
8
  temp = Usart_Rx();   // enter = Usart_Rx();
9
  //while(1);
10
}

von Owen S. (senmeis)


Lesenswert?

Sorry, habe for Schleife vergessen zu posten.
1
for(;;) // main loop
2
{
3
  if (enter)
4
  {
5
    enter = 0;
6
    uart_put_string(str);
7
  }
8
  else
9
  {        
10
    temp = Usart_Rx();
11
    //while(1);
12
    if (temp == '\n') // Endzeichen
13
    {
14
    enter = 1;
15
    }
16
  }
17
}

Owen

von Karl H. (kbuchegg)


Lesenswert?

Und wo ist deine Usart_Tx?

von Owen S. (senmeis)


Lesenswert?

Sorry, Usart_Tx() hier.
1
void Usart_Tx(char data)
2
{
3
    while (!(UCSR0A & (1<<UDRE0)));
4
    UDR0 = data;
5
}

Owen

von Krapao (Gast)


Lesenswert?

Mit dem Code aus Beitrag "Re: Zeichenketten ueber UART" ist 
mir unklar, wie du den Fehler aus 
Beitrag "Zeichenketten ueber UART" feststellen kannst. 
Du hast doch nirgends eine Ausgabe des enpfangenen temp. Gehst du mit 
einem ICD im Einzelschritt in das laufende System und verlierst dabei 
eventuell Zeichen?

von Stefan (Gast)


Lesenswert?

Owen Senmeis schrieb:

> while(*data_string) Usart_Tx(*data_string++);
                               ^

du musst klammern

  while(*data_string) Usart_Tx(*(data_string++));

von Krapao (Gast)


Lesenswert?

Die Klammern erhöhen die Lesbarkeit, sind aber nach den C Operatoren 
Vorrangregeln nicht nötig.
1
*a++ entspricht *(a++)

von Owen S. (senmeis)


Lesenswert?

Ich poste den ganzen Code hier. Es geht um ein Ablesen aus einem CO2 
Sensor.
1
int main( void )
2
{
3
  unsigned char i = 0, temp;
4
  unsigned char buffer[STRLENGTH];
5
  unsigned char co2_value[STRLENGTH], temp_index = 0;
6
  volatile static char enter = 1;  
7
  unsigned char str[] = "12345";
8
  
9
  clock_init_8MHz();
10
  USART_Init(103); // 9600bps by 8MHz
11
   
12
  __enable_interrupt();
13
14
  for(;;) // main loop
15
  {
16
      if (enter)
17
      {
18
        enter = 0;   
19
        //uart_put_string(str);   // data request
20
        uart_send();
21
      }
22
      else
23
      {        
24
          temp = Usart_Rx();
25
          
26
          if (temp == '\n')   // end character
27
          {
28
            if ((buffer[0] == 'Z') && (buffer[i-1] == '\r'))  // if the format is correct
29
            { 
30
              for (temp_index = 2; temp_index < (i-1); temp_index++)
31
              {
32
                co2_value[temp_index-2] = buffer[temp_index]; // delete format character
33
              }
34
              co2_value[temp_index-1] = '\0';   // add null character
35
                           
36
              uart_put_string(co2_value);   // output co2 value
37
            }
38
            enter = 1;  // trigger request
39
          }
40
          else 
41
          {
42
            if (temp == 'Z')  // start character
43
            {  
44
              i = 0;
45
            }
46
            buffer[i] = temp;   // save data
47
            i++;  
48
          }
49
      }
50
  }
51
}
Die Arbeitsweise sieht so aus:

1. Eine Zeichenkette ausgeben (z.B. „12345“), um Messwerte anzufordern.

2. Wenn der Messwert kommt wird dieser entpackt und zurückgeschickt.
Z.B. Empfangsbytes: 0x5a 0x20 0x34 0x35 0x30 0x0D 0x0A
Nach dem Entpacken: 0x34 0x35 0x30, also 450

Es gibt engentlich zwei Probleme mit dem Code.

Problem 1: Wie erwähnt wird die Zeichenkette nicht richtig ausgegeben. 
Vermutlich liegt das an uart_put_string(), denn mit der folgenden 
Methode geht es.
1
void uart_send(void)
2
{
3
  Usart_Tx('1');
4
  Usart_Tx('2');
5
  Usart_Tx('3');
6
  Usart_Tx('4');
7
  Usart_Tx('5');
8
}

Problem 2: Der Messwert wird nicht zurückgeschickt.
Man gibt im Terminal ein: 0x5a 0x20 0x34 0x35 0x30 0x0D 0x0A und 
erwartet 0x34 0x35 0x30 als Rückmeldung, aber nichts kommt.

Ich bin sehr dankbar für jeden Vorschlag.
Gruss
Owen

von Karl H. (kbuchegg)


Lesenswert?

Deine Hilfsfunktionen sehen erst mal korrekt aus.

Aber nur um sicher zu gehen, sollte man die erst mal für sich alleine 
testen. Aber nicht mit deinem umfangreichen Code, sondern mit einem 
einfachen Testprogramm!
1
int main()
2
{
3
  unsigned char str[] = "12345\r\n";
4
5
  clock_init_8MHz();
6
  USART_Init(103); // 9600bps by 8MHz  
7
8
  while( 1 ) {
9
    uart_put_string( str );
10
  }
11
}

das muss eine saubere Ausgabe auf dein Terminal zaubern. Wenn es das 
nicht tut, dann hast du höchst wahrscheinlich irgendein Taktproblem.

von Krapao (Gast)


Lesenswert?

1
int main( void )
2
{
3
  unsigned char buffer[STRLENGTH];
4
  unsigned char co2_value[STRLENGTH];
5
  unsigned char i = 0;
6
  
7
  clock_init_8MHz();
8
  USART_Init(103); // 9600bps by 8MHz
9
   
10
  __enable_interrupt();
11
12
  // prepare rx line
13
  i = 0; 
14
  buffer[0] = 0; 
15
 
16
  for(;;) // main loop
17
  {
18
    unsigned char temp;
19
    temp = Usart_Rx();
20
    if ( temp == '\n' )   // end character
21
    {
22
      // format correct? then output result
23
      if ( buffer[0] == 'Z' && buffer[1] == ' ' && buffer[i-1] == '\r' )
24
      { 
25
        buffer[i-1] = 0; // delete \r
26
        strncpy(co2_value, &buffer[2], STRLENGTH); // skip "Z "
27
        uart_put_string("co2_value: [");
28
        uart_put_string(co2_value);
29
        uart_put_string("]\r\n");
30
      } 
31
      // prepare rx line
32
      i = 0; 
33
      buffer[0] = 0; 
34
    }
35
    else 
36
    {
37
      if ( i+1<STRLENGTH )
38
      {
39
        buffer[i++] = temp;
40
        buffer[i] = 0;  
41
        uart_put_string("buffer: [");
42
        uart_put_string(buffer);
43
        uart_put_string("]\r\n");
44
      }
45
    }
46
  }
47
}

von Karl H. (kbuchegg)


Lesenswert?

Der zuletzt gepostete Code, ist das jetzt auch wirklich alles? Kommt da 
noch irgendeine Funktionalität dazu?
(Der sieht nämlich für die bisher bekannte Aufgabenstellung ziemlich 
umständlich aus. Auch hast du dir keinerlei Hilfen in den Code 
eingebaut, bei denen dir das Programm selbst mitteilen würde, was es 
wann und warum macht. Das einfachste ist erst mal, dass das Programm 
jedes Zeichen, das es empfängt auch gleich mal zurückschickt. Auch wäre 
interessant, was sich an Zeichen im Buffer nach jedem empfangenen 
Zeichen angesammelt hat. Du hast eine UART, die hoffentlich 
funktioniert. Benutze sie, damit dir das Programm selber hilft, es zu 
debuggen!)

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.