atoi oder char zu integer - Anfängerfrage

#3699513
Lesenswert?

Hallo, ich habe folgenden Code auf einem Atmega8 (Ausschnitt):
1
unsigned int empfi;
2

3
empfi = uart_getc();
4
 if ( empfi & UART_NO_DATA )
5
  {
6
   // keine Daten erhalten
7
  }
8
 else
9
  {
10
   uart_putc( (unsigned char)empfi );

an meinem PC wird jetzt eine Zahl zwischen 0-255 ausgegeben.

jetzt möchte ich mit dem Wert "empfi" auf meinem Atmega8 Berechnungen
durchführen (z.B.: empfi=empfi-10).
Wie/oder Was muss ich mit "empfi" machen damit ich solche Berechnungen 
durchführen kann?

Danke.
Gast #3699695
Lesenswert?

Chris L. schrieb:
> Wenn uart_getc aber 16 bit zurück gibt, wobei die oberen 8 bit als
> Statusbits verwendet werden, dann reichen 8 bit nicht.

16 Bit oder mehr schrieb:
> Dann sollte man mit Wert nicht einfach rechnen.

Henri Großmann schrieb:
> Hallo,  das mit einfach rechnen wie z.b. empfi = empfi-10 funktioniert
> nicht.
> Kommt immer mist raus.
Statusbits loeschen...
1
uint16_t empfi;
2

3
empfi = uart_getc();
4

5
// statusbits loeschen
6
empfi = empfi & 0x00FF; // wenn die statusbits im oberen Byte stehen, sonst
7
                        // mit 0xFF00 verunden
8
empfi = empfi - 10;
#3699812
Lesenswert?

'Kaj' schrieb:

> empfi = empfi & 0x00FF; // wenn die statusbits im oberen Byte stehen,
> sonst

sie stehen im oberen Byte und man braucht sie nicht löschen, da sie 0 
sind, solange UART_NO_DATA nicht gesetzt ist. Abgesehen davon strippt 
uart_putc sowieso das High-Byte raus.

'16 Bit oder mehr' schrieb

> Pack den cast mit rein
Man braucht auch nichts casten. Du bellst den völlig falschen Baum an.

@Henri
> Kommt immer mist raus.

Definiere 'Mist'.

Was sendest du dem µC und was erwartest du?
Dir ist hoffentlich klar, dass du hier eine Binärübertragung hast. D.h. 
du sendest Bytes.
Wenn du vor einem Terminal sitzt und dort auf der Tastatur 173 tippst, 
dann wird nicht 1 Byte mit dem Wert 173 übertragen, sondern es werden 3 
Bytes übertragen: eines mit dem ASCII Code für '1', eines mit dem ASCII 
Code für '7' und eines mit dem ASCII Code für '3'. Und ein 4.tes Byte 
wirst du dann auch noch brauchen, denn der µC kann ja nicht riechen, 
dass du nach den Tasten 1 und 7 noch die 3 drücken wirst. Das 4.te Byte 
brauchst du also um anzuzeigen: jetzt ist alles übertragen.
Auf dem µC musst du die Bytes wieder zusammensetzen, daraus eine Zahl 
machen, davon 10 abziehen und dann aus der neuen Zahl wieder einen Text 
machen, den du dann zurück schickst, damit im Terminal die 'Zahl' (die 
eigentlich auch nur ein Text ist) aufleuchtet und dein Gehirn 163 liest.

Wenn das nicht das ist, was du machen willst, dann definiere 'Mist'; wie 
du feststellst, das Mist rauskommt und ob du eigentlich deine UART 
insofern schon getestet hast, dass die Übertragung (Taktfrequenz, 
Baudrate) überhaupt korrekt funktioniert.
#3700055
Lesenswert?

@Karl Heinz

Hallo, erst einmal Danke für deinen langen Text...
Hier nochmal eine etwas genauere Angabe von mir.

Ich sende von einem Visual Basic Programm auf meine PC einen Wert an den 
µC,
und zwar so...
1
Dim data As Integer
2
data = 128
3
SerialPort1.Write(data)

im µC Empfange ich die Daten (über USB -> UART) und gebe die Daten 
danach zurück...
1
while (1) 
2
{
3
empfi = uart_getc();   // Daten empfangen
4
if ( empfi & UART_NO_DATA )
5
{
6
// keine Daten erhalten
7
}
8
else
9
{
10
uart_putc( (unsigned char)empfi );   // Daten zurück senden
11
}

jetzt empfange ich die Daten wieder mit meinem Visual Basic Programm auf 
dem PC...
1
PufferString = SerialPort1.ReadExisting()
2
RichTextBox1.AppendText(PufferString)

Jetzt wird auf meinem PC GENAU die Zahl angezeigt welche ich vom PC zu 
µC gesendet habe.
Das sagt mir die Übertragung von PC zu µC und zurück Funktioniert.
Jetzt möchte ich jedoch auf dem µC mit dieser Zahl (z.B.: 128) 
verschieden Port's schalten...
1
if (empfi > 127)
2
{
3
PORTB |= (1<<PB5);  // Port B5 ein
4
empfi = empfi -128;   // rest von empfi
5
}
6
else
7
{
8
PORTB &= ~(1<<PB5);   // Port B5 aus
9
}

So wo ist nun mein Denkfehler, lass mich gerne belehren beschäftige mich 
ja
auch erst ca. 2 Wochen mit µC.

Danke an alle die mir weiterhelfen können, und dies auch machen...
#3700081
Lesenswert?

> RichTextBox1.AppendText(PufferString)

Text?

Sobald Text im Spiel ist, funktioniert alles ein wenig anders.

Du musst dir erst mal klar machen, dass es einen UNterschied zwischen 
binärer Übertragung und textueller Übertragung gibt.

Klar. Texte werden ebenfalls übertragen, in dem Bytes auf die Reise 
gehen. Der UNterschied ist dann eben der, dass bei einer rein binären 
Übertragung ein Byte-WErt von zb 32 für die Zahl 32 steht, während er 
bei einer Text-Übertragung nach ASCII für ein Leerzeichen steht (weil 
der ASCII COde für ein Leerzeichen nun mal 0x20 oder eben dezimal 32 
ist).

Sobald Texte im Spiel sind, gibt es keinen prinzipiellen UNterschied 
zwischen dem Text "168" und "Hugo". Beides sind auf der 
Übertragungsebene einfach nur Texte, die Buchstabe für Buchstabe 
übertragen werden.
Dass das Programm, welches am jeweils anderen Ende der Leitung mit 
diesem Text etwas spezielles macht, ist eine andere Sache - betrifft 
aber die reine Textübertragung nicht.

> Jetzt wird auf meinem PC GENAU die Zahl angezeigt welche ich vom PC zu µC 
gesendet habe.

Nein. Es wird nicht die Zahl angezeigt. Es wird der Text (bestehend aus 
mehreren 'Buchstaben') angezeigt. Das das mal eine Zahl war, das 
entsteht erst in deinem Gehirn, welches dem Text "168" eine besondere 
Bedeutung (nämlich den einer Zahl) zuweist. Aus Sicht der UART 
unterscheidet sich der Text "168" vom Text 
"Supercalifragilisticexpialidocious" nur in der Anzahl der Buchstaben 
und der Auswahl der verwendeten Buchstaben. Aber Text ist Text und der 
hat als solcher keine Bedeutung. Vor allen Dingen nicht den, eine Zahl 
zu sein, mit der man rechnen könnte. Man kann natürlich auf µC Seite aus 
dem Text "168" wieder eine Zahl machen und dann mit der rechnen. Kann 
man, aber erst mal ist das einfach nur Text und sonst nichts.
#3700167
Lesenswert?

Danke, aber hättest du eventuell noch einen kleinen Tipp wie ich
das am besten mache mit dem Text zu Zahl?

Habe schon viel mit atoi probiert will aber irgendwie nicht so wie 
ich...
Und wäre dann so eine Abfrage möglich/richtig?
1
if (empfi > 127)
2
{
3
PORTB |= (1<<PB5);
4
empfi = empfi -128;
5
}
6
else
7
{
8
PORTB &= ~(1<<PB5);
9
}

Danke.
#3700238
Lesenswert?

Henri Großmann schrieb:
> Danke, aber hättest du eventuell noch einen kleinen Tipp wie ich
> das am besten mache mit dem Text zu Zahl?

zuallererst brauchst du eine Kennung, mit der du feststellen kannst: 
hier ist der Text zu Ende.

D.h. der PC kann nicht einfach nur den Text "12" senden. Denn niemand 
kann (auch der µC nicht) wissen, ob nach den Zeichen '1' und '2' noch 
etwas kommt, oder ob das schon der ganze Text war. Kann ja sein, dass 
der PC den Text "12" wegschicken wollte. Kann aber auch sein, dass da 
noch eine 4 kommt, und der ganze Text in WIrklichkeit "124" darstellen 
soll.

Auf der anderen Seite des Kabels kann man nun mal nicht mehr 
unterscheiden, ob diesseits
1
  SerialPort1.Write( "123" );
stattgefunden hat, oder
1
  SerialPort1.Write( "1" );
2
  SerialPort1.Write( "2" );
3
  SerialPort1.Write( "3" );

In beiden Fällen wird dasselbe übertragen. Nämlich nacheinander die 
Zeichen '1', '2' und '3'.

Fazit: Ohne Zusatzinformation geht das nicht.
Dein VB Programm muss also nachdem es den
1
  SerialPort1.Write(data)
noch etwas nachschieben. Ein Zeichen, welches in den Daten selbst nicht 
vorkommt, woran aber der µC erkennen kann 'Huch: jetzt ist der Text zu 
Ende, da kommt nichts mehr'

zb könnte dein VB Programm irgendein Sonderzeichen nachschieben. Ich 
nehm man einen ';'
1
  SerialPort1.Write(data)
2
  SerialPort1.Write(";")

so. Damit ist klar, dass (in deinem Fall), die Zeichen '1', '2', '8' und 
dann eben noch ein ';' über die Leitung geschoben werden.

Und die musst du eben wieder zusammensetzen.
Das kann man jetzt natürlich machen, in dem man die Zeichen in einem 
char-Array sammelt. Kann man, muss man aber in deinem speziellen Fall 
nicht. Denn in deinem Fall wissen wir, das (abgesehen vom ';') das ganze 
eine Zahl darstellen soll. Und bei Zahlen geht das ganz einfach.
Ausgehend von zb 8, wie hängst du da die nächste Ziffer (sagen wir mal 
eine '3' ran), so dass aus den 8 die 83 entstehen? Na, ganz einfach: 
wenn du das nächste Zeichen hast, dann nimmst du die 8 einfach mal 10 
und addierst noch den Zahlenwert für 3. So werden aus den 8 durch 8 * 10 
+ 3 die 83. Und aus den 83 werden mit der nächsten Ziffern 4 die 834, 
indem du die 83 mal 10 nimmst und noch 4 addierst.

D.h. deine Strategie lautet:
Hole das nächste Zeichen von der UART, falls eines vorhanden ist
Ist dieses nächste Zeichen ein ';', dann bedeutet das, das die 'Zahl' 
(in Textform) komplett übertragen wurde. D.h. man kann die Zahl 
bearbeiten und damit irgendwas machen (zb 10 subtrahieren und zurück 
schicken)
Ist das nächste Zeichen kein ';' dann geht die Zahl weiter und dieses 
Zeichen muss in die Zahl eingerechnet werden.
1
int main()
2
{
3
  char buffer[10];
4

5
  .....
6

7
  zahl = 0;
8

9
  while( 1 )
10
  {
11
    empfi = uart_getc();
12

13
    if ( !( empfi & UART_NO_DATA ) )     // gibt es ein Zeichen?
14
    {
15
      char c = empfi;          // High Byte loswerden und nur den char übrig lassen
16
      if( c == ';' )
17
      {
18
        // mach was mit der Zahl
19
        zahl = zahl - 10
20
        itoa( zahl, buffer, 10 );
21
        uart_puts( buffer );
22
        uart_puts( ';' );
23
        zahl = 0;
24
      }
25
      else
26
      {
27
         // sicherheitshalber, auch wenn es nie vorkommen sollte
28
        if( isdigit( c ) )
29
          zahl = zahl * 10 + ( c - '0' );
30
      }
31
    }
32
  }


und teste das Ganze erst mal mit einem gewöhnlichen Termninalprogramm 
anstelle einem VB Programm. Du beginnst gerade einen 2-Fronten Krieg, in 
dem du nicht weißt ob deine Programmfehler auf µC-Seite oder auf 
VB-Seite zu suchen sind. Soweit bist du noch nicht, dass du das in einem 
Aufwasch handhaben könntest. In derartigen 2-Fronten Kriege sind schon 
ganz andere Kapazunder als von deinem Kaliber gnadenlos untergegangen.
Also. Entwickle erst mal so, dass du auf PC Seite ein Terminal-Programm 
hast und du deine Eingaben mit der Hand machst. Dann weißt du auch, was 
tatsächlich über die Schnittstelle rausgeht bzw. zurück kommt und musst 
nicht raten, ob dein VB Programm das alles tatsächlich so erzeugt, wie 
es das sollte, bzw. was tatsächlich über die Schnittstelle rausgeht 
(dafür wäre auch zb die Installation eines Serial Port Monitors eine 
ausgesprochen gute Idee)
#3700402
Lesenswert?

NEIN, NEIN, NEIN bin ich blöd....

Alles klar ich hab jetzt den Durchblick, alles funktioniert wie es soll.

Ich bedanke mich sehr bei

Karl Heinz

sowie

Rufus Τ. Firefly (für den letzten Tipp zum verstehen)

Danke, mein Problem ist gelöst.

P.S.: warum steht da "zahl * 10", versteh ich nicht

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