Forum: Mikrocontroller und Digitale Elektronik Usart (XMega) gesendeten String mit empfagenem String vergleichen


von Anemali (Gast)


Lesenswert?

Hallo,

Ich will ein Testprogramm schreiben, welches den empfangenen String mit 
dem gesendeten vergleichen soll. Der Mikrocontroller ist ein AT XMega 
128 A1 und RX und TX sind miteinander verbunden (Er sendet also an sich 
selbst). Habe USART schon initialisiert und senden und empfangen 
funktioniert auch einwandfrei.
Jetzt weiß ich leider nicht weiter. Hatte die Idee das was gesendet und 
empfangen wird in Arrays zu schreiben und diese miteinander zu 
vergleichen aber das funktioniert bis jetzt nicht.
anbei noch mein bisheriger code:
1
#include <avr/io.h>
2
#include <stdint.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5
#include <avr/interrupt.h>
6
7
/*******************FUNKTIONEN********************/
8
9
void usart_sendstring(char *s) //zum Senden von Strings
10
{
11
  while (*s)
12
  {  
13
    USARTE0.DATA = *s ;
14
  while(!(USARTE0.STATUS & 0x40));
15
  s++;
16
  _delay_ms(500);
17
  }
18
}
19
20
ISR(USARTE0_RXC_vect)//Empfangen mit Interrupt
21
{
22
  int c = 0;
23
  c = USARTE0.DATA;
24
}
25
26
/*******************MAIN*************************/
27
28
int main(void)
29
{
30
  PORTD.DIR = 0b11111110;
31
  PORTD.OUT = 0b00000000;
32
  PORTE.DIR = 0b00001010;
33
  PORTE.OUT = 0b00001000;
34
35
  /************external clock (8 MHz)**************/
36
  OSC.CTRL |= 0x08;
37
  CCP = 0xD8;
38
     CLK.CTRL = 0x03;
39
40
  /***************USARTC initialisieren*****************/
41
  USARTE0.BAUDCTRLA = 52; // Formel siehe Skript AVR-GCC-Tutorial
42
  USARTE0.BAUDCTRLB = 0;
43
44
  USARTE0.CTRLC = 0x03; // 8-Bit-Character-Size
45
  USARTE0.CTRLB = 0x18; // enable Receiver & Transmitter
46
  USARTE0.CTRLA = 0x30; // enable Empfangsinterrupt (auf HI Level) 
47
48
49
PMIC.CTRL |= PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm; //Interrupts (high-, medium- und lowlevel freigeben)
50
51
  sei(); // allegemeine interruptfreigabe
52
53
  while(1)//Endlosschleife
54
  {
55
    usart_sendstring("Hallo"); //Senden des Wortes Hallo
56
         }
57
}

Danke schon mal!!!

von Ulrich P. (uprinz)


Lesenswert?

Also es gibt jede Menge fertige U(S)ART Routinen für den AVR.

Aber im grunde musst Du nur ein Array definieren, in das Du Deine Daten 
empfängst. Du musst ein Ende-Zeichen definieren, damit Du weißt, wann 
der String zuende ist, so dass er weiter verarbeitet werden kann. 
Normalerweise ist das \n (Newline). Du musst natürlich Deinen 
Sende-String dann ebenfalls als "Hallo\n" senden.

Wenn Du dieses Zeichen empfängst, machst Du einen ordentlichen C String 
daraus, in dem Du es durch 0x00 ersetzt.

Also etwas im Sinne von:
1
char rxbuffer[64]; /* Puffer für Empfang */
2
int rxpos = 0;     /* Zeiger auf nächstes Zeichen im Puffer */
3
bool rxvalid = 0;  /* 1= String vollständig */
4
...
5
6
ISR(USARTE0_RXC_vect)//Empfangen mit Interrupt
7
{
8
  int c = 0;
9
  c = USARTE0.DATA;
10
  if (c=='\n') 
11
  { 
12
    c = 0x00; 
13
    rxvalid = 1; 
14
    rxbuffer[rxpos] = c;
15
    rxpos = 0;
16
  }
17
  if (c=='\r') {
18
    /* Windows Kompatibilität:
19
       c Verwerfen. */
20
  }
21
  else {
22
    /* Zeichen speichern */
23
    rxbuffer[rxpos++] = c;
24
  }
25
}

Damit sammelt der RX Interrupt die empfangenen Zeichen in xrbuffer ein.
Natürlich sind da jetzt noch einige Dinge nicht berücksichtigt. So 
müsstest Du beachten, dass nichts mehr empfangen wird, wenn \n 
eingegangen ist, sonst wird der rxbuffer wieder überschrieben.
Du musst 'manuell' in der Software rxvalid nach der Verarbeitung wieder 
zurück setzen. rxvalid kannst Du aber auch abfragen und wenn es 1 ist 
erst mal keine weiteren Zeichen zum rxbuffer hinzufügen.

Den empfangenen String kannst Du dann per
1
if (!strcmp(mystring, rxbuffer))
2
  { /* passt */ }
3
else
4
  { /* passt nicht */ }
verarbeiten.

Ist jetzt aus dem Kopf zusammen geschrieben, ich hoffe ich habe nix 
vergessen. Ist aber mehr ein Weg um Dir zu zeigen, wonach Du suchen 
musst, oder wie es im Grunde funktioniert.

Gruß, Ulrich

von xmega (Gast)


Lesenswert?

Hallo,


Anemali schrieb:
> Jetzt weiß ich leider nicht weiter.

das wast du brauchst ist hier als Software zu bekommen.

Atmel USART Demo "TXT raus, RX rein, dann verglaichen"

http://www.atmel.com/dyn/resources/prod_documents/AVR1307.zip


Gruß XMEGA

von Anemali (Gast)


Lesenswert?

Ok ich probiers gleich mal aus und lass euch wissen obs geklappt hat!
Danke für eure Hilfe.

von xcdark (Gast)


Lesenswert?

Ulrich P. schrieb:
> Den empfangenen String kannst Du dann perif (!strcmp(mystring, rxbuffer))
>   { /* passt */ }
> else
>   { /* passt nicht */ }
> verarbeiten.
>
> Ist jetzt aus dem Kopf zusammen geschrieben, ich hoffe ich habe nix
> vergessen. Ist aber mehr ein Weg um Dir zu zeigen, wonach Du suchen
> musst, oder wie es im Grunde funktioniert.

Warum string.h mitkompilieren, wenn es ein paar Zeilen Code auch tun?

[c]char mystrcmp (unsigned char *s1, unsigned char *s2){
    while (*s1&&*s2){
        if (*s1!=*s2) return 1;
        s1++;
        s2++;
    }
    return 0;
}[c]

von Karl H. (kbuchegg)


Lesenswert?

xcdark schrieb:

> Warum string.h mitkompilieren,

Weil string.h schon fertig ist und beim Linken sowieso nur die 
Funktionen in den Code kommen, die du auch benutzt. Es gibt keinen 
Grund, die bereits vorhandenen Funktionen zu ignorieren. Zumal der 
Compilerhersteller gewisse Freiheiten in der Implementierung hat, die du 
selber nicht hast. Soll heißen: Wenn es eine Möglichkeit gibt, 
schnelleren Code zu erhalten, dann kriegst du den eher indem du strcmp 
aus string.h benutzt als wie wenn du deine eigene Implementierung 
schreibst.

von Anemali (Gast)


Lesenswert?

Guten Morgen,

also ich habe den Code jetzt mal etwas umgeschrieben, angelehnt an das 
Muster von Atmel. Habe wohl irgendwo eine endlosschleife drinnen, weil 
er nur das erste Byte von meinem Array sendet bzw. empfängt. Ich 
vermute, dass mein Fehler beim Empfangen liegt aber ich komm nicht drauf 
wie ich das umschreiben könnte.
1
#include <avr/io.h>
2
#include <stdint.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5
#include <avr/interrupt.h>
6
#include <stdbool.h>
7
8
#define K1_ON    (PORTD.OUT |= 0x80)
9
#define K1_OFF    (PORTD.OUT &= ~0x80)
10
#define K2_ON    (PORTD.OUT |= 0x40)
11
#define K2_OFF    (PORTD.OUT &= ~0x40)
12
#define K3_ON    (PORTD.OUT |= 0x20)
13
#define K3_OFF    (PORTD.OUT &= ~0x20)
14
#define ON_ON    (PORTD.OUT |= 0x08)
15
#define ON_OFF    (PORTD.OUT &= ~0x08)
16
#define RXEN_ON    (PORTD.OUT |= 0x04)
17
#define RXEN_OFF  (PORTD.OUT &= ~0x04)
18
#define DXEN_ON    (PORTD.OUT |= 0x10)
19
#define DXEN_OFF  (PORTD.OUT &= ~0x10)
20
#define DE_ON    (PORTD.OUT |= 0x02)
21
#define DE_OFF    (PORTD.OUT &= ~0x02)
22
#define DZ_ON    (PORTE.OUT |= 0x02)
23
#define DZ_OFF    (PORTE.OUT &= ~0x02)
24
25
#define RS232    1
26
#define DS102    2
27
#define DS101    3
28
29
#define NUM_BYTES   51 //Anzahl der Bytes 
30
31
int i = 0;
32
int c = 0;
33
// Array: the quick brown fox jumps over the lazy dog's back 
34
int sendArray[NUM_BYTES] = {0x74,0x68,0x65,0x20,0x71,0x75,0x69,0x63,0x6B,0x20,0x62,0x72,0x6F,0x77,0x6E,0x20,0x66,0x6F,0x78,0x20,0x6A,0x75,0x6D,0x70,0x73,0x20,0x6F,0x76,0x65,0x72,0x20,0x74,0x68,0x65,0x20,0x6C,0x61,0x7A,0x79,0x20,0x64,0x6F,0x67,0x60,0x73,0x20,0x62,0x61,0x63,0x6B,0x20};
35
int receiveArray[NUM_BYTES];
36
bool success;
37
38
ISR(USARTE0_RXC_vect)  //Interruptroutine zum Empfangen
39
{
40
  receiveArray[i] = USARTE0.DATA;   // empfangene Zeichen in ein Array schreiben
41
  i++;
42
}
43
44
/*******************MAIN*************************/
45
46
int main(void)
47
{
48
  PORTD.DIR = 0b11111110; //definieren von Ein- und Ausgängen
49
  PORTD.OUT = 0b00000000;
50
  PORTE.DIR = 0b00001010; //definieren von Ein- und Ausgängen
51
  PORTE.OUT = 0b00001000;
52
53
  int mode = RS232 ; //Einstellen der Kommunikationsart (RS232, DS101, DS102)
54
55
  /************external clock (8 MHz)**************/
56
  OSC.CTRL |= 0x08;
57
  CCP = 0xD8;
58
     CLK.CTRL = 0x03;
59
60
  /***************USARTC initialisieren*****************/
61
  USARTE0.BAUDCTRLB = 0;
62
63
  USARTE0.CTRLB = 0x18; // enable Receiver & Transmitter
64
  USARTE0.CTRLA = 0x30; // enable Empfangsinterrupt (auf HI Level) 
65
66
67
  PMIC.CTRL |= PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm; //Interrupts (high-, medium- und lowlevel freigeben)
68
69
70
  sei(); // allegemeine interruptfreigabe
71
72
73
  while(1)
74
  {
75
    switch(mode)
76
    {
77
78
/*****************************RS232******************************/ 
79
//funktioniert, bis auf das Vergleichen des gesendeten und empfangenen Wertes (mit Hilfe von Arrays)
80
81
      case RS232: 
82
83
        USARTE0.BAUDCTRLA = 52; // Formel siehe Skript AVR-GCC-Tutorial, bei 9600bps
84
        USARTE0.CTRLC = 0x03; // 8-Bit-Character-Size, asynchron
85
86
        K1_ON;
87
        K2_OFF;
88
        K3_OFF;
89
        ON_ON;
90
        RXEN_ON;
91
        DXEN_ON;
92
        DE_OFF;
93
        DZ_OFF;  
94
95
         if(i>=NUM_BYTES) //wenn das letzte Zeichen gesendet ist, soll wieder bei 0 angefangen werden
96
        {
97
          i = 0;
98
        }    
99
          
100
        USARTE0.DATA = sendArray[i];
101
        while(!(USARTE0.STATUS & 0x40));
102
          i++;
103
104
        _delay_ms(200);
105
106
        /*********Test zum Vergleichen von Gesendetem und Empfangenem*****/
107
        //funktioniert noch nicht!!!
108
109
        PORTA.DIR = 0xFF;
110
111
        success = true; 
112
        for(i=0; i<NUM_BYTES; i++)
113
        {
114
          if (sendArray[i] != receiveArray[i])
115
          { 
116
            success = false;
117
          }
118
        }
119
120
        if(success)
121
        {
122
          PORTA.OUT = 0b00000100;
123
        }
124
        else
125
        {
126
          PORTA.OUT = 0b00000001;
127
        }
128
                  
129
      break; 
130
131
/*************************noch unbearbeiteter Teil (nicht wichtig)***************/
132
133
/*****************************DS102******************************/ 
134
135
      case DS102:
136
137
        K1_OFF;
138
        K2_ON;
139
        K3_OFF;
140
        ON_ON;
141
        RXEN_ON;
142
        DXEN_ON;
143
        DE_OFF;
144
        DZ_ON; // Takt???
145
146
      break;
147
148
/*****************************DS101******************************/ 
149
150
      case DS101:
151
152
        K1_OFF;
153
        K2_OFF;
154
        K3_ON;
155
        ON_OFF;
156
        RXEN_OFF;
157
        DXEN_OFF;
158
        DE_ON; // RTS???
159
        DZ_OFF;
160
161
      break; 
162
      
163
      default: 
164
165
      break;
166
    }  
167
  }  
168
}

von Karl H. (kbuchegg)


Lesenswert?

1
// Array: the quick brown fox jumps over the lazy dog's back 
2
int sendArray[NUM_BYTES] = {0x74,0x68,0x65,0x20,0x71,0x75,0x69,0x63,0x6B,0x20,0x62,0x72,0x6F,0x77,0x6E,0x20,0x66,0x6F,0x78,0x20,0x6A,0x75,0x6D,0x70,0x73,0x20,0x6F,0x76,0x65,0x72,0x20,0x74,0x68,0x65,0x20,0x6C,0x61,0x7A,0x79,0x20,0x64,0x6F,0x67,0x60,0x73,0x20,0x62,0x61,0x63,0x6B,0x20};

Bitte besorg dir ein C Buch und lies dir zumindest das erste Drittel 
durch.
UNd das das alles den Datentyp int benötigt, halte ich auch für ein 
Gerücht
1
char sendArray[] = "the quick brown fox jumps over the lazy dog's back";
1
 ...
2
         if(i>=NUM_BYTES) //wenn das letzte Zeichen gesendet ist, soll wieder bei 0 angefangen werden
3
        {
4
          i = 0;
5
        }    
6
....

du verwendest in deinem restlichen Code wie ein wilder i. D.h. diese 
Abfrage wird alles mögliche machen. Aber sicher nicht funktionieren. Für 
wichtige Variablen, wie zb die Anzahl der bereits gesendeten Zeichen 
benutzt man eine Variable mit sprechendem Namen, wie zb nrCharSent. Aber 
sicher nicht i. Einbuchstabige Variablennamen reserviert man 
ausschliesslich für Einsatzzwecke wie zb in kurzen for-schleifen, deren 
Inhalt man überblicken kann. Innerhalb der Schleife wird i benutzt und 
welchen Wert i danach hat interessiert keinen mehr, weil dieses i in der 
nächsten for-Schleife sowieso wieder auf einen neuen Wert initialisiert 
wird. Kurz und gut: Das ist eine Variable, deren Inhalt man zerstören 
kann, weil davon nichts anderes abhängt. Was man von einer Variablen 
namens nrCharSent nicht sagen kann.

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.