Forum: PC-Programmierung Problem mit (einfachem?) cast..


von Phoenix89 (Gast)


Lesenswert?

Hi Leute..kleines Problem.

Ich sende von einem uC über UART den Wert des ADC (10Bit) an den Rechner 
und lasse mir diesen ausgeben.

read_data ist ein ByteArray (von qt5) das 4. und 5. Byte dieses Arrays 
enthält die Daten von dem ADC. Byte 5 Bit 4 sagt ob überhaupt Daten 
vorliegen. Byte 4 und das 0. und 1. Bit von Byte 5 ist der Wert des 
ADC´s.
Die Anzeige erfolgt über die case-Schleife (Atmega32: 8 ADC-Eingänge). 
Mein Problem hierbei:
Es werden mir sinnvolle Daten angezeigt, solange das 7. Bit von Byte 4 
nicht gesetzt ist, wenn es gesetzt ist kommt Müll raus (z.B. 2*10^7). 
Jemand ne Idee bzw. nen Tipp?

Phoenix89
1
// AD-Wandler
2
        unsigned int iWert = 0;
3
        double fWert;
4
5
        if (read_data.at(5) & 1<<4){
6
            // Wert des AD-Wandlers
7
            iWert = read_data.at(5) << 8;
8
            iWert |= read_data.at(4);
9
            iWert &= ~((1<<10) |(1<<11) |(1<<12) |(1<<13) |(1<<14) |(1<<15));
10
            fWert = static_cast<double>(iWert);
11
            fWert = fWert*5/1024;
12
13
            switch (read_data.at(6)>>5){
14
            case 0:
15
                ui->LCD_PortA0->display(iWert);
16
                break;

von Karl H. (kbuchegg)


Lesenswert?

Phoenix89 schrieb:

> nicht gesetzt ist, wenn es gesetzt ist kommt Müll raus (z.B. 2*10^7).

lass den Quatsch da am PC mit Bitpfriemeleien rumzumachen!
ein unsigned int ist auf einem PC sicher keine 16 Bit mehr.
1
            iWert = ( read_data.at(5) & 0x03 ) * 256 + read_data.at(4);
und gut ists.
Und den Cast von unsigned int auf double kannst du dir auch sparen.
1
        if (read_data.at(5) & 1<<4) {
2
            // Wert des AD-Wandlers
3
            iwert = ( read_data.at(5) & 0x03 ) * 256 + read_data.at(4);
4
            fWert = iwert * 5.0 / 1024.0;
5
6
            ....

: Bearbeitet durch User
von Phönix89 (Gast)


Lesenswert?

Danke schonmal für die Antwort. Sieht auf jedenfall schonmal angenehmer 
aus.

Allerdings löst das mein Problem nicht.. wenn ich beim uC

0b00010011 und 0b01111111 sende kommen 4,37 raus (stimmt so), bei
0b00010011 und 0b11111111 kommen 3,745 raus statt ~5 (?).

von Jay (Gast)


Lesenswert?

Hallo,

(ich gehe einfach mal davon aus, dass du eine Spannung messen willst)

folgendes:
Welchen Wert hat dieses Bit?
Es ist das achte Bit:
2^8 = 256
256 * 5 / 1024 = 1,25V

Du erwartest ca. 5V bekommst aber nur 3,745V:
5V - 3,745V = 1,255V
Das entspricht in etwa dem fehlenden Bit.

Da war doch irgendwas mit dem MSB...
Ach ja Zweierkomplement:
http://de.wikipedia.org/wiki/Zweierkomplement

Laut der Tabelle rechts auf der Seite:
Bitwert  | Dezimal | Spannungswert
01111111 | 127     | 4,37V
11111111 |  -1     | 3,745V
---------+---------+---------------
Differenz| 128     | 0,625V

Wieder in die obige Formel eingesetzt:
128 * 5 / 1024 = 0,625V

Das gleiche Ergebnis. Ich glaube nicht an Zufälle.

Sind deine Bytes vielleicht vorzeichenbehaftet?

CU,
Jay

von Bastler (Gast)


Lesenswert?

Vielleicht sind Binärdaten über serielle Schnittstelle nicht so der Hit. 
Ich würde die in Textform als "1.234" oder notfalls den μC Hexwert als 
"01A7" übertragen.
Was machst du denn, wenn ein Steuerzeichen im Binärstrom ist, das der 
Seriell-Treiber ganz speziell verarbeiten will. Z.B. 0x11 (XoN), 0x13 
(Xoff)

von Yalu X. (yalu) (Moderator)


Lesenswert?

QByteArray ist verwirrenderweise ein Array von char und sollte deswegen
eigentlich QCharArray heißen. Ein char kann in C++ signed oder unsigned
sein, bei dem von dir verwendeten Compiler ist es offensichtlich signed.
Du möchtest aber die gelesenen Bytes mit Unsigned-Arithmetik
weiterverarbeiten. Das tust du am besten dadurch, dass du sie gleich
beim Lesen mit at() in ein unsigned char castest:
1
  static_cast<unsigned char>read_data.at(...)

Dann funktionieren sowohl dein als auch Karl Heinz' Code.

Und schick den Qt-lern gleich einen Bug-Report: 99% aller Programmierer
denken bei "Byte" an eine vorzeichenlose Zahl oder zumindest an eine
Zahl, die definiert vorzeichenlos oder vorzeichenbehaftet ist. Zudem
sollte der Typ char nur für Textzeichen bzw. in unicode-fähiger Software
überhaupt nicht verwendet werden. Und für Arrays von Unicode-Zeichen
gibt es in Qt die Klasse QString, weswegen QByteArray nie für Texte
verwendet werden sollte. Richtig wäre es somit, QByteArray auf Basis von
unsigned char anstelle von char zu deklarieren.

: Bearbeitet durch Moderator
von Phönix89 (Gast)


Lesenswert?

Viele Dank Leute (vor allem yalu). Funktioniert jetzt :D

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.