Forum: Compiler & IDEs Variable aus dem PC in uc speichern


von Leandro L. (tetef)


Lesenswert?

hallo zusammen,

ich habe ein kleines Problemchen und zwar, ich moechte zwei Zahlen (z.B. 
200000;300000) zum uC uebertragen und dort berechnen. Mit kleinen Zahlen 
hat es geklappt, aber solbald ich grosse Zahlen uebertrage, dann lassen 
sie sich nicht richtig zum Zahlen konvertieren.
Ich uebertrage die Daten per RS232 als String. Ich kann sie als String 
lesen, aber ich brauche sie als Zahlen.

hat jemand eine Idee

von Peter (Gast)


Lesenswert?

> hat jemand eine Idee
ja, aber zeig mal lieber den Quellcode man sehen kann wo der Fehler ist.

von Joachim (Gast)


Lesenswert?

Hallo

<Pseudocode an>

Zahl = 0

rotiere bis endezeichen empfangen
   zahl = zahl * 10
   zahl = zahl + empfangenes digit
beginne wieder bei rotiere

<pseudocode aus>

zahl sollte groß genug sein, um deine übertragene Zahl zu speichern.

Gruß
Joachim

von Leandro L. (tetef)


Lesenswert?

hi Peter,

hier mein code:



main()
{
...

  while(1)
  {
       uart_gets(tmp, sizeof(tmp) );
       split(tmp, sizeof(tmp) );
  }
}
unsigned char Getch1(void)    // Waits for and returns incoming char
{
  unsigned char rxchar;

  for(;;)
  {
    while(SSR1_RDRF == 0)     // Wait for data received
    {
      __wait_nop();
    }

    rxchar = RDR1;            // Save receive register

    if ((SSR1 & 0xE0) != 0)   // Check for errors PE, ORE, FRE
    {
      SCR1_CRE = 1;           // Clear error flags
    }
    else
    {
      return (rxchar);        // Return received character
    }
  }
}
void uart_gets( char* Buffer, int MaxLen )
{
  int NextChar;
  int StringLen = 0;

  NextChar = Getch1();         // Warte auf und empfange das nächste 
Zeichen

                                  // Sammle solange Zeichen, bis:
                                  // * entweder das String Ende Zeichen 
kam
                                  // * oder das aufnehmende Array voll 
ist
  while( NextChar != '\n' && StringLen < MaxLen - 1 ) {
    *Buffer++ = NextChar;
    StringLen++;
    NextChar = Getch1();
  }
                                   // Noch ein '\0' anhängen um einen 
Standard
                                   // C-String daraus zu machen
  *Buffer = '\0';
}
void split(char* Buffer, int MaxLen )
{
    int i = 0;
    int m =0;
    int j =0;
    char Data[2][256];
    int a=0,b=0;
    while( i < MaxLen - 1 )
    {
       if(Buffer[i] == ';' || i == MaxLen -1)
       {
         Data[m][j] = '\0';
         m++;
         j=0;
         i++;

       }
       Data[m][j] = Buffer[i];
       i++;
       j++;
    }
    #define fr atof(Data[0])
    #define bd atof(Data[1])
    sprintf(a,Data[0]);
    sprintf(b,Data[1]);
    Putch1(13);
    Puts1("Your Frequency is: ");
    Puti(a);
    Putch1(13);
    Puts1("Your baudrate is: ");
    Puti(b);
    Putch1(13);
}

von Karl H. (kbuchegg)


Lesenswert?

Die Split Funktion benötigt MaxLen gar nicht.
Du baust deine String Splitterei momentan auf der Array Größe auf. Aber 
das darfst du nicht. Du hast den String bereits. Das \0 Byte am Ende des 
Strings zeigt dir, wo der String aufhört. Und das muss nicht 
notwendigerweise das Array-Ende sein.


    #define fr atof(Data[0])
    #define bd atof(Data[1])
    sprintf(a,Data[0]);
    sprintf(b,Data[1]);

Du trickst dich wohl gerne selber aus?

Welchen Datentyp hat a? Welchen hat b? Was will sprintf als ersten 
Parameter haben? Hat dein Compiler dazu gar nichts zu sagen?


Die ganze Funktion ist .... nicht gut geschrieben.
Sieh erst mal zu, dass du deinen String sauber in die beiden Teilstrings 
zerlegen kannst. Lass dir die Teilstrings ausgeben und ehe die nicht 
stimmen hat es keinen Sinn, da weiter zu machen.
Wenn die Strings korrekt sind, benutzt du atoi zur Umwandlung der 
Textrepräsentierung in richtige Zahlen (oder atol wenn die Zahlen größer 
sind)

Und räum den Code auf! Es hat keinen Sinn da Variablen und Makros 
rumlungern zu lassen, die nirgends benutzt werden. Du trickst dich damit 
nur selber aus und verlierst die Übersicht.

von Leandro L. (tetef)


Lesenswert?

hi,

ich habe schon so probiert, aber sobald ich die Werte 200000;200000 
eingebe,
dann stimmen sie nicht mehr:

    long a,b;
    a = strtol (Data[0], p, 10);
    b = strtol (Data[1], p, 10);
    Putch1(13);
    Puts1("Your Frequency is: ");
    Puti(a);
    Putch1(13);
    Puts1("Your baudrate is: ");
    Puti(b);
    Putch1(13);

von Karl H. (kbuchegg)


Lesenswert?

Tetef El schrieb:
> hi,
>
> ich habe schon so probiert, aber sobald ich die Werte 200000;200000
> eingebe,
> dann stimmen sie nicht mehr:
>
>     long a,b;
>     a = strtol (Data[0], p, 10);
>     b = strtol (Data[1], p, 10);

Du kannst anstelle von p auch einfach NULL benutzen, wenn dich der 
Endpointer nicht interessiert. Das ist auch sicherer, denn im Moment 
stehen die Chancen nicht schlecht, dass dir strtol irgendwo im Speicher 
etwas niederbügelt, was du gar nicht haben willst.

      a = strtol (Data[0], NULL, 10);
      b = strtol (Data[1], NULL, 10);


>     Putch1(13);
>     Puts1("Your Frequency is: ");
>     Puti(a);

a ist ein long.
Wofür wohl das i in Puti steht?

von Leandro L. (tetef)


Lesenswert?

Puti ueberytraegt Int oder long.

von Karl H. (kbuchegg)


Lesenswert?

Tetef El schrieb:
> Puti ueberytraegt Int oder long.

Zeigen.
Das glaub ich nämlich erst, wenn ich es sehe :-)
Normalerweise hat es einen Grund, warum man die Funktion Puti nennt und 
nicht Putl (l wie long). Ein Putl könnte int und long bearbeiten, weil 
ein int auch in einen long passt. Aber umgekehrt gehts nicht.

von Leandro L. (tetef)


Lesenswert?

"Ein Putl könnte int und long bearbeiten, weil
ein int auch in einen long passt. Aber umgekehrt gehts nicht."

Hier ist die Funktion: ich habe sie umbennant, aber das Problem ist 
immer das gleiche.

void Putl(long val)
{
  long val2;

  val2 = val / 1000000;
  Putch1(val2 + 0x30);

  val = val - (val2 * 1000000);
  val2 = val / 100000;
  Putch1(val2 + 0x30);

  val = val - (val2 * 100000);
  val2 = val / 10000;
  Putch1(val2 + 0x30);

  val = val - (val2 * 10000);
  val2 = val / 1000;
  Putch1(val2 + 0x30);

  val = val - (val2 * 1000);
  val2 = val / 100;
  Putch1(val2 + 0x30);

  val = val - (val2 * 100);
  val2 = val / 10;
  Putch1(val2 + 0x30);

  val = val - (val2 * 10);
  Putch1(val + 0x30);
}

von Karl H. (kbuchegg)


Lesenswert?

Wow.
Du machst dir viel Arbeit :-)
Aber ok. Die Funktion ist so ok.


Hast du dir schon die Teilstrings angesehen? Und btw. deine Aufteilerei 
ist nicht in Ordnung. Du darfst die while Schleife nicht bis MaxLen - 1 
laufen lassen, sondern nur solange du noch im String bist.

Ausserdem solltest du noch sicher stellen, dass der 2-te Teilstring mit 
einem '\0' abgeschlossen wird. Selbst dann, wenn in der Übertragung kein 
zweiter ; auftaucht.
1
    while( Buffer[i] != '\0' )
2
    {
3
       if(Buffer[i] == ';' || i == MaxLen -1)
4
       {
5
...

Schritte:
zuerst den empfangenen String ausgeben lassen um zu sehen, ob da 
überhaupt das drinnen steht, was du denkst das drinnen stehen sollte
dann die Teilstrings nach der Zerlegung.
und erst dann die umgewandelten Ergebnisse.


Ach was solls. Ich würds so machen
1
void split(char* Buffer, int MaxLen )
2
{
3
  long a = 0;
4
  long b = 0;
5
  char* end;
6
7
  Puts1( "\nParsing String: &");
8
  Puts1( Buffer );
9
  Puts1( '&');
10
11
  a = strtol( buffer, &end, 10 );
12
  if( *end == ';' ) {
13
    buffer = end + 1;
14
    b = strtol( buffer, &end, 10 );
15
  }
16
17
  Puts1( "\nYour Frequency is: ");
18
  Putl( a );
19
20
  Puts1( "\nYour baudrate is: " );
21
  Putl( b );
22
23
  Putch1( '\n' );
24
}

von Leandro L. (tetef)


Lesenswert?

Als Ergebnis fuer diese Funktion:

Input:
200000;30000
Output
Parsing String: &200000;30000

Your Frequency is: 0003392
Your baudrate is: 0030000,

wie Du siehst, wenn ein Zahl mehr als 5 Stellig dann funktioniert nicht.

von Leandro L. (tetef)


Lesenswert?

hat das nicht mit dem Complir zu tun?
ich gehe davon aus, dass mein Complire ist 16 bit. daher kann er nur:

ul: 0 65535
l: -32768 32767

von Leandro L. (tetef)


Lesenswert?

sorry
ich meinte Compiler

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Tetef El schrieb:
> Als Ergebnis fuer diese Funktion:
>
> Input:
> 200000;30000
> Output
> Parsing String: &200000;30000
>
> Your Frequency is: 0003392
                        ^^^^ siehe unten
> Your baudrate is: 0030000,

200000 - 3 * 65536 = 3392

Irgendwo gehen Dir die Bits oberhalb von 16 flöten.

Gruß,

Frank

von Leandro L. (tetef)


Lesenswert?

wie kann ich es beheben?

von Karl H. (kbuchegg)


Lesenswert?

Tetef El schrieb:
> wie kann ich es beheben?

Nochmal den kompletten Code.
Irgendwo ist höchst wahrscheinlich eine Umrechnung nach int 
(möglicherweise auch implizit) die nicht sein soll.

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.