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.
Also Du empfängst Zahlenwerte und keine ASCII-Zeichen? Sind die Zahlen
immer dreistellig? Welchen Wertebereich können die überhaupt haben? Wo
hast Du array[0]?
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?
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
so jetzt bin ich registriert^^
Also ich empfange auch ASCII Zeichen, und das ist mein größtes Problem.
Ich werde mir jetzt mal den Link angucken und schreiben was bei
rumgekommen ist.
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.
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
chartemp_str[40];
4
unsignedcharc;
5
c=UDR;
6
strcat(temp_str,c);
7
8
for(inti=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
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).
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
voidstepper(intdrive,intsteps,intdir,intmode){..}
So möchte ich dann übergeben:
1
stepper(1,[AlleZeichenbzw.kompl.Array],1,0);
Hoffe ihr verliehrt nicht die gedult mit mir^^
Jonas
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.
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
chartemp_str[40];
2
intnachstes_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.
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
> 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.
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:>
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,[AlleZeichenbzw.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
intToNumber(char*String)
2
{
3
inti=0;
4
intZahl=0;
5
6
while(String[i]!='\0'){
7
Zahl=10*Zahl+(String[i]-'0');
8
i++;
9
}
10
11
returnZahl;
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
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(inti=0;i<40;i++){
8
uart_send_c(temp_str[i]);
9
}
10
11
}
12
//////////////////////Deklaration der Stepperfunktion
> 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.
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
@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
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
@Jonas G.
>Ne, den Code den ich da gepostet habe, der war nur zum Testen. Ich werde>dass dans im Main-PRG machen.
Auch zum Testen war der vollkommen unbrauchbar.
MFG
Falk