Array Probleme

Gast #519771
Lesenswert?

Hi,
ich brauche dringend eure Hilfe.
Ich habe ein C-Programm, welches mir Zeichenweise die empangenen Zeichen 
(RS232) in einen Array schriebt.

Jetzt möchte ich den Array komplett an eine andere Varible übergeben. 
Leider funktioniert var1 += array[i]; in einer schleife nicht, da so 
meine Werte addiert werden und nicht nebeneinander gespeichert werden.

Übersicht:
array[1] = 1
array[2] = 2
array[3] = 3

Struktur:
[var1 = array[1]array[2]array[3]]

Ausgabe:
var1 soll dann "123" sein.

Absicht:
Später sollen die empfangenen Zeichen komplett an eine Funktion übergben 
werden.
Gast #519798
Lesenswert?

du kannst keine Werte so konkatenieren. Du willst ein neues Array haben 
und die Werte mit strncpy kopieren.
Alternativ kannst du auch einfach die Werte ab array[1] per Pointer 
übergeben. Musst dann natürlich darauf achten dass der aufgerufenen 
Funktion auch bekannt ist wie lang das neue Array ist und es 
funktioniert dann auch nur wenn die Werte (also Indizes) fortlaufend 
sind.

Und nachdem du hier mit array[1] beginnst: dir ist klar dass Indizes in 
C bei 0 anfangen, oder?
Gast #519802
Lesenswert?

Ansonsten: Wenn aus "{1, 2, 3}" die Zahl 123 werden soll, dann musst Du 
einfach die jeweilige Ziffer mit dem Wert der entsprechenden 
Dezimalstelle multiplizieren, also z.B.
1
var1 = array[3];
2
var1 += array[2] * 10;
3
var1 += array[1] * 100;
Mit den obigen Werten steht dann die Zahl 123 in var1. Das ganze lässt 
sich natürlich viel eleganter in einer Schleife lösen
1
uint8_t i, mul;
2
var1 = 0;
3
for(i = 3, mul = 100; i; i--)
4
{
5
    var1 += array[i] * mul;
6
    mul /= 10;
7
}
(ohne Gewähr)
#519844
Lesenswert?

Jonas G. wrote:
> Ich werde mir jetzt mal den Link angucken und schreiben was bei
> rumgekommen ist.

Das Hauptproblem in deiner Fragestellung ist, dass nicht klar
ist worauf deine Frage abzielt. Es gibt da mehrere Interpretations-
möglichkeiten. Insbesondere ist nicht ganz klar, was dein
das Ergebnis sein soll.
Falls du noch Fragen hast, denke also daran die Fragestellung
zu präzisieren. Insbesondere hilft es meist, wenn du angibst
welche Datentypen involviert sind. Daraus kann man dann meist
dein eigentliches Problem erraten.
#519850
Lesenswert?

Okay,

ich habe jetzt mal gelesen und ausprobiert. Leider ohne wirklichen 
erfolg.
Ich möchte wissen, wie ich die Zeichen, die ich per UART bekomme und in 
"unsigned char c" speichere in den array "char temp_str[40]" speichern, 
sodass im arry später alle empangenen zeichen (Zahlen und Buchstaben) 
enthalten sind.

Leider gibt es Probleme, wenn ich c also UDR in den Array specihern 
möchte.
Meldung:
code.c:227: warning: passing argument 2 of 'strcat' makes pointer from 
integer without a cast
Das ist mein Code:
1
SIGNAL(SIG_UART_RECV)
2
{
3
  char temp_str[40];
4
        unsigned char c;
5
  c = UDR;
6
  strcat(temp_str,c);
7
  
8
  for(int i=0; i<40; i++){      //40 nur zum Test um den gesammten array auszulesen.
9
  uart_send_c(temp_str[i]);
10
  }
11
  
12
}

Wenn ich statt "c" einen String wie "TEST" einfüge, bekomme ich zwar 
keinen Fehler aber falsche Zeichen im Hyperterminal.

Jonas
Gast #519859
Lesenswert?

c ist eine Variable. strcat erwartet als Argument aber einen Zeiger auf 
einen String (also wenn überhaupt, dann "&c" anstatt "c", aber da c kein 
String ist, geht der Rest dann wegen des fehlenden Nullterminators in 
die Hose). Aber das, was Du da vorhast, kann aus mehreren anderen 
Gründen nicht funktionieren. strcat ist an der Stelle völig unsinnig. Du 
brauchst im Prinzip nur ein array (das aber entweder global deklariert 
oder zumindest static sein muss!) und einen Zählindex, der ebenfalls 
global oder zumindest static sein muss. Jedes Mal, wenn ein Zeichen 
ankommt, wird dieses in array[i] geschrieben und i anschließend um 1 
erhöht. Die Ausgabe gehört dann ins Hauptprogramm (und dazu müssen array 
und Zählindex global und volatile sein).
#519868
Lesenswert?

Das was du schriebts stimmt zwar und so hat es mit der ausgabe auch 
funktioniert. Doch ich brauche unbedingt alle empangenen Zeichen in 
einer Variable oder muss die zusammen an eine Funktion übergben.

Hier die Funktion:
1
void stepper(int drive, int steps, int dir, int mode){..}

So möchte ich dann übergeben:
1
stepper(1, [Alle Zeichen bzw. kompl. Array], 1, 0);

Hoffe ihr verliehrt nicht die gedult mit mir^^

Jonas
Gast #519869
Lesenswert?

BTW: Du solltest möglichst anstelle des veralteten SIGNAL-Makros das 
aktuelle ISR verwenden. SIGNAL wird zwar von der aktuellen 
AVR-libc-Version noch unterstützt, ich denke jedoch, dass es irgendwann 
in nicht allzu ferner Zukunft "abgekündigt" wird. Gewöhne Dir am besten 
gleich die aktuelle Schreibweise an, sonst musst Du demnächst alle alten 
Programme ändern.
#519870
Lesenswert?

Jonas G. wrote:
> Okay,
>
> ich habe jetzt mal gelesen und ausprobiert. Leider ohne wirklichen
> erfolg.
> Ich möchte wissen, wie ich die Zeichen, die ich per UART bekomme und in
> "unsigned char c" speichere in den array "char temp_str[40]" speichern,
> sodass im arry später alle empangenen zeichen (Zahlen und Buchstaben)
> enthalten sind.

Ganz einfach: Indem du sie ins Array zuweist:

  temp_str[naechstes_Zeichen] = UDR;

und natürlich danach naechstes_Zeichen um 1 erhöhen, sodass
das nächste Zeichen dann im Array an die nächste Position
kommt.

  naechstes_Zeichen++;

Also:
1
char temp_str[40];
2
int  nachstes_Zeichen;
3

4
SIGNAL(SIG_UART_RECV)
5
{
6
  temp_str[naechsts_Zeichen] = UDR;
7
  naechstes_Zeichen++;
8
}

Ein String wird in C in einem Array gespeichert. Die einzelnen
Elemente des Arrays sind die Zeichen die den String aufbauen.
Du kannst daher auf jedes einzelne Zeichen mit ganz normaler
Array Sytax zugreifen.
Erst dann wenn du das Array als Ganzes als String auffassen
möchtest, kommen die str... Funktionen ins Spiel.
#519873
Lesenswert?

johnny.m wrote:
> BTW: Du solltest möglichst anstelle des veralteten SIGNAL-Makros das
> aktuelle ISR verwenden.

Werde ich spätestens ändern, wenn die übergabe an die stepper funktion 
läuft. Eigendlcih mache ich das auch mit ISR. Keine Ahnung, warum ich es 
diesmal nciht gemacht haben xD
Gast #519877
Lesenswert?

> Hoffe ihr verliehrt nicht die gedult mit mir^^
Die Geduld vielleicht nicht, aber langsam die Übersicht, was Du 
eigentlich genau willst. Das, was Du oben geschrieben hast mit der 
UART-ISR, hat mit dem ursprünglichen Problem doch erstmal gar nichts 
mehr zu tun. Wie man ASCII-Zahlzeichen, die in der richtigen Reihenfolge 
ankommen, in einer Variablen aufaddiert, habe ich ganz oben schon 
beschrieben (zumindest prinzipiell). Dass Deine ISR so nicht 
funktionieren wird (unabhängig vom ersten Thema) steht auch fest. 
Deshalb jetzt die Aufforderung an Dich: Beschreibe einmal ausführlich, 
was Du genau willst, was Du bereits gemacht hast usw. Und versuche 
dabei, die oben u.a. von mir gestellten Fragen, die Du z.T. noch nicht 
wirklich beantwortet hast (z.B. "Wie sehen die Daten, die Du empfängst 
und an die Funktion weitergeben willst, überhaupt genau aus") zu 
beantworten.
#519880
Lesenswert?

Jonas G. wrote:
> Das was du schriebts stimmt zwar und so hat es mit der ausgabe auch
> funktioniert. Doch ich brauche unbedingt alle empangenen Zeichen in
> einer Variable

Nochmal. Das geht nicht.
Alle empfangenen Zeichen zusammengenommen bilden einen String.
Es gibt aber keinen Datentyp für Strings! Es gibt nur ein Array

> Hier die Funktion:
>
1
> void stepper(int drive, int steps, int dir, int mode){..}
2
>

Das ist aber was ganz anderes. Diese Funktion möchte
Zahlenwerte und keine Strings.

Du musst dich also damit beschäftigen, wie du aus einem
String "123" den Zahlenwert 123 bekommst.

>
1
> stepper(1, [Alle Zeichen bzw. kompl. Array], 1, 0);
2
>

Hier:
             ********************************

hier musst du aus dem String "123" den Zahlenwert 123 machen.

Wenn der String korrekt aufgebaut ist (das abschliessende '\0'
nicht vergessen!) dann geht das so

  int Zahl = atoi( temp_str );

atoi macht aus einem entsprechend geformten String den
entsprechenden Zahlenwert. Da steckt nichts
geheimnusvolles dahinter. Angenommen du mueestes das
machen und ich geb die die Zeichen einzeln. Fangen wir
an.
Zunächst mal ist deine Zahl eine 0
Dann geb ich dir eine '5' (Also den ASCII Code für 5)
Du ziehst davon den Code für '0' ab, nimmst die bisherige
Zahl mal 10 und addierst die 5

   Zahl = 10 * Zahl + ( '5' - '0' )

Da Zahl vorher 0 war, kriegt Zahl als neuen Wert 5

Jetzt geb ich dir '8'. Davon die '0' abgezogen gibt 8, also
den Zahlenwert, der dem Zeichen '8' entspricht.
Und wieder nimmst du die bisherige Zahl mal 10
(also 5 * 10 -> 50 ) und addierst diese 8. Macht 58

Das nächste Zeichen das ich dir gebe ist eine '3'

   '3' - '0'     ->  3
   58 * 10   -> 580  und dazu noch die 3 addiert -> 583

Dann geb ich dir '7'

   '7' - '0'     -> 7
   583 * 10 -> 5830 + 7 -> 5837

Jetzt solltest du das Prinzip schon gesehen haben. In C Code
gegossen ist das dann:
1
  int ToNumber( char* String )
2
  {
3
    int i = 0;
4
    int Zahl = 0;
5

6
    while( String[i] != '\0' ) {
7
      Zahl = 10 * Zahl + ( String[i] - '0' );
8
      i++;
9
    }
10

11
    return Zahl;
12
  }

Zusammengefasst: Von der UART kriegst du einen String.
In diesem String steckt die Zeichenmässige Repräsentierung
einer Zahl. Die kann man wieder als Zahl zurückgewinnen und
dann natürlich in die stepper-Funktion weitergeben
#519887
Lesenswert?

So dann starte ich mal:
Ich möchte eine Reihe von Zahlen und Buchstaben an den µC schicken und 
verarbeiten. Später soll mit diesem Daten die Funktion für die 
Schrittmoren "gefüttert" werden.
Dazu muss immer die ISR immer die empfangnen Zeichen speichern, was jezt 
auch funktioniert (hatte vorher irgendwie ein Brtee vorm Kopf). Code 
s.u.
Ich übergbe dann nach jedem Befehl ein Zeichen, was das Ende angibt. 
Dann muss der µC die Empfangenen Zeichen an die Funktion übergben hier 
ein Bsp.:
Gesendete Zeichen PC -> µC:
A;1;300;1;0;
Spätere Verarbeitung:
A=Stepper-Funktion
1=Motor 1
300 = 300 Schritte
1 = Linkslauf
0 = Vollschritt

So sieht mein Ziel aus. Doch das Eigendliche und oben besprochene 
Problem ist das, dass ich nicht weiß, wie ich die Zeichenkette aus 
mehreren Array-Einträgen übergbe. z.B.: die 300 wären ja 3 Einträge 
3-0-0 und wie übergbe ich die zusammen an die Funktion.

Hoffe es verwirrt nicht nochmehr...

Jonas

P.S.: Wie ich die Daten "auseinanderreiße" weiß ich und die 
Stepperfunktion ist auch fertig.

Hier die Codes:
1
//////////////////////UART-ISR zum Empfangen
2
SIGNAL(SIG_UART_RECV)
3
{
4
  temp_str[NextChar] = UDR;
5
  NextChar++;
6
  
7
  for(int i=0; i<40; i++){
8
  uart_send_c(temp_str[i]);
9
  }
10
  
11
}
12
//////////////////////Deklaration der Stepperfunktion
13
void stepper(int drive, int steps, int dir, int mode)...
#519896
Lesenswert?

> A;1;300;1;0;
> Spätere Verarbeitung:
> A=Stepper-Funktion
> 1=Motor 1
> 300 = 300 Schritte
> 1 = Linkslauf
> 0 = Vollschritt
>
> So sieht mein Ziel aus. Doch das Eigendliche und oben besprochene
> Problem ist das, dass ich nicht weiß, wie ich die Zeichenkette aus
> mehreren Array-Einträgen übergbe. z.B.: die 300 wären ja 3 Einträge
> 3-0-0 und wie übergbe ich die zusammen an die Funktion.
>
> Hoffe es verwirrt nicht nochmehr...

Ganz im Gegenteil: Jetzt ist alles klar.
Du entdeckst gerade das ein String etwas anderes als eine Zahl ist,
selbst wenn in dem String "123" drinnensteht.
Lösung: schon gepostet: Du musst die Zahl aus dem String wieder
zurückgewinnen.
#519904
Lesenswert?

ERFOLG:
1
SIGNAL(SIG_UART_RECV)
2
{
3
  temp_str[NextChar] = UDR;
4
  
5
  for(int i=0; i<40; i++){
6
  uart_send_c(temp_str[i]);
7
  }
8
  if (temp_str[NextChar] == 0x0D) {
9
  int zahl = atoi(temp_str);
10
  stepper(1,zahl,1,0);}
11
  NextChar++;
12
}

Wenn ich zB 400 sende und dann Enter drücke dreht sich der Motor 1 um 
genau 400 Schritte. (ist nen Motor mit 400 Stepps daher leicht zu 
erkennen)

Danke an alle und Sorry wenn ich euch verwirtt habe^^

Jonas
Gast #519908
Lesenswert?

@Jonas G.

Ich glaube du hasst da noch ein Verständnissproblem was Interrupts 
angeht. Im Interrupt wird beim UART immer nur ein Zeichen gelesen und 
gespeichert, die Verarbeitung erfolgt zu 99% ausserhalb des Interrupts.

SIGNAL(SIG_UART_RECV)
{
  int8_t tmp;

  tmp= UDR;
  temp_str[NextChar] = tmp;
  NextChar++;
  if (NextChar>=MaxChar) NextChar=0;  // Sicherung gegen Overflow
  if (tmp=10) RX_complete=1;      // 10 ist der ASCII für RETURN
}

//////////////////////Deklaration der Stepperfunktion
void stepper(int drive, int steps, int dir, int mode)...

#define MaxChar 20

char temp_str[MaxChar];
uint8_t RX_complete=0;
int NextChar=0;

Im Main musst du dann prüfen ob RX_complete =1 ist, dann kannst du auf 
temp_str zugreifen und die Daten verarbeiten.

MfG
Falk
#519915
Lesenswert?

Falk wrote:
> @Jonas G.
>
> Ich glaube du hasst da noch ein Verständnissproblem was Interrupts
> angeht. Im Interrupt wird beim UART immer nur ein Zeichen gelesen und
> gespeichert, die Verarbeitung erfolgt zu 99% ausserhalb des Interrupts.

Ne, den Code den ich da gepostet habe, der war nur zum Testen. Ich werde 
dass dans im Main-PRG machen.

Mir ging es dort nur um den Erfolg und den Test^^

Jonas
#519929
Lesenswert?

naja unbauchbar ist falsch, da es ja funktonier hat.
Jetzt wird rx_flag immer überprüft...
So muss ich natürlich jede Eingabe mit [Enter] abschließen.
1
SIGNAL(SIG_UART_RECV)
2
{
3
  temp_str[NextChar] = UDR;
4
  if (temp_str[NextChar] == 0x0D) {
5
  rx_flag=1;}
6
  else {
7
  NextChar++;
8
             }
9
}

  

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren