Hallo zusammen,
ich habe folgendes Problemchen.
Ich habe vier Byte Daten:
Bit7 6 5 4 3 2 1 Bit0
---------------------------------------
Byte1 ID28 ID27 ID26 ID25 ID24 ID23 ID22 ID21
Byte2 ID20 ID19 ID18 XXXX XXXX ID17 ID16 ID15
Byte3 ID14 ID13 ID12 ID11 ID10 ID09 ID08 ID07
Byte4 ID06 ID05 ID04 ID03 ID02 ID01 ID00 XXXX
Ich möchte diese Daten nun auslesen und speichern, aber dabei die XXXX
Bits auslassen. Die sollen dann später auf einem Display ausgegeben
werden.
Ich will Byte 1 + 2 und Byte 3 + 4 zusammen speichern: data1[15],
data2[16]
Das ganze soll dann wie folgt aussehen:
data1[0]..............data1[13]
ID28..................ID15
und
data2[0]..............data2[14]
ID14..................ID0
Das erste Byte verarbeite ich folgendermaßen:
1
for(i=7;i>=0;i--)
2
{
3
datatest=RXData[0];
4
if(datatest&0x80>>i)
5
data1[i]='1';
6
else
7
data1[i]='0';
8
}
Das zweite Byte verarbeite ich folgendermaßen
1
for(i=7;i>=0;i--)
2
{
3
datatest=RXData[1];
4
if(datatest&0x80>>i)
5
data1[i+8]='1';
6
else
7
data1[i+8]='0';
8
}
Das scheint auch zu funktionieren, aber leider nehme ich da ja die
beiden XXXX Bits mit, das soll ja nicht sein.
Die beiden anderen Byte verarbeite ich in gleicher Weise.
Kann mir vielleicht jemand helfen, das ganze eleganter zu lösen? Ich
denke mit den 4 for Schleifen ist das ganz schön umständlich, vielleicht
geht es ja auch noch kürzer und dabei dann Natürlich die
gekennzeichneten Bits auslassen.
Wäre klasse, wenn mir dabei jemand auf die Sprünge helfen könnte.
Grüße
Steffen
@ Steffen R.
Es wäre vielleicht hilfreich, wenn Du erklären könntest was genau Du Dir
gedacht hast, als Du das Programm genau so geschrieben hast.
Vor allem scheint mir, das es eigentlich nicht so funktionieren dürfte
wie Du es beschreibst.
In beiden Routinen geht der Index (i ist sicherlich signed) von 7 bis 0
geht. D.h. die Bits werden einzeln in datax gespeichert. Wozu soll das
gut sein? Du hast doch in RXData schon das komplette Byte.
Im übrigen: Wozu wird datatest= RXData[0]; bei jedem
Schleifendurchlauf ausgeführt. Das Ergebnis ist ja immer das selbe.
Mit dem "ignorieren" ist das so eine Sache. Je nachdem was Du mit den
Daten nachher anfangen willst, gibt es sicherlich wesentlich einfachere
Möglichkeiten.
Aber der Knackpunkt ist die Frage, warum und wozu Du die Bits einzeln
brauchst.
Klugscheisser wrote:
> Zu langsam... :-}
Oder zu schnell. Der OP will das Ganze offensichtlich als Array
speichern (jedes Bit einzeln, was in meinen Augen Speicherverschwendung
ist). Aber dann geht es so nicht. Deshalb habe ich meinen Beitrag auch
zurückgezogen.
Vielleicht noch ein Nachtrag. ich speichere die Bitweise, um sie binär
auf einem LCD auszugeben. Wenn ich sie zusammen speicher wird nicht
001101001 ausgegeben, sondern ein entsprechender Wert, wenn ich nicht
irre.
> ich speichere die Bitweise, um sie binär> auf einem LCD auszugeben. Wenn ich sie zusammen speicher wird nicht> 001101001 ausgegeben, sondern ein entsprechender Wert, wenn ich nicht> irre.
Du irrst, denn man kann bei der Umwandlung in (darstellbare)
ASCII-Zeichen auch eine Basis angeben, und wenn Du als Basis 2 angibst,
dann sollte auch eine Binärdarstellung herauskommen.
Ansonsten nochmal mein (anscheinend etwas voreilig gelöschter) Vorschlag
von vorhin:
>Du irrst, denn man kann bei der Umwandlung in (darstellbare)>ASCII-Zeichen auch eine Basis angeben, und wenn Du als Basis 2 angibst,>dann sollte auch eine Binärdarstellung herauskommen.
Das verstehe ich noch nicht so ganz. Ich habe folgend mal meinen Code,
mit dem ich die daten auf einem LCD ausgeben möchte:
1
voidLCDOutc(unsignedcharstr)
2
{
3
switch(str)Display
4
{
5
case'ä':
6
str=0xE1;
7
break;
8
case'ö':
9
str=0xEF;
10
break;
11
case'ü':
12
str=0xF5;
13
break;
14
case'ß':
15
str=0xE2;
16
break;
17
case'°':
18
str=0xDF;
19
break;
20
case'µ':
21
str=0xE4;
22
break;
23
}
24
PORTA=str;// str einfach an den Port schicken
25
PORTK|=0x05;// RS und E high
26
PORTK&=~0x02;// R/W low
27
LCDClock();// Befehl ausführen
28
chars++;
29
if(chars==20)
30
{
31
if(row==1)
32
{
33
SecondLine();// zweite Zeile
34
}
35
if(row==2)
36
{
37
ThirdLine();// dritte Zeile
38
}
39
if(row==3)
40
{
41
FourthLine();// vierte Zeile
42
}
43
if(row==4)
44
{
45
LCDHome();// erste Zeile
46
}
47
}/* if(chars==20) */
48
}
49
50
voidLCDOuts(unsignedchar*str)
51
{
52
while(*str!=0){LCDOutc(*str++);}
53
}/* void LCDOuts(char* str) */
Aber wie soll ich dann die Umwandlung anstellen, dass die Daten eben
schön in einsen und nullen ausgegeben werden?
Grüße
Steffen
Es gibt fertige Bibliotheksfunktionen zur Umwandlung von Zahlen in
ASCII-Strings. Wenn Du den AVR-GCC mit der AVR-libc benutzt, heißt die
gesuchte Funktion itoa, steht in der stdlib, und wie die funktioniert
(also was für Parameter sie erwartet), steht in der
Bibliotheksdokumentation:
1
char* itoa (int __val,
2
char* __s,
3
int __radix
4
)
Die Funktion erwartet drei Parameter, von denen der erste die Variable
ist, die in einen String konvertiert werden soll (ein unsigned int
bzw. ein uint16_t ist hier angebracht, wie z.B. oben in meinem
Beispiel). Der zweite (__s) ist ein Zeiger auf den Anfang des char
-Arrays (also hier die Adresse des ersten Elements des Strings), in dem
der String abgelegt werden soll, der dritte (__radix) ist die besagte
Basis.
Für die Ausgabe brauchst Du zwei char -Strings, und zwar mit jeweils
mindestens 17 Elementen, damit die 16 Bits plus Nullterminator
hieneinpassen. Jetzt musst Du nur noch die Funktion z.B. mit
1
charstring1[17];
2
//....
3
itoa(data1,string1,2);
aufgerufen werden, und den Rest macht die Funktion für Dich.
data1[i]=(data11%2)+'0';// Modulo rechnen, dann den ASCII-Code
7
// von '0' addieren
8
data11/=2;
9
}
10
data2[15]='\0';// String Terminator
11
for(i=14;i>=0;i--){
12
data2[i]=(data22%2)+'0';// Modulo rechnen, dann den ASCII-Code
13
// von '0' addieren
14
data22/=2;
15
}
Das scheint aber irgendwie noch nicht so ganz zu funktionieren. Bei
folgenden Werten:
RXData[0]=15
RXData[1]=255
RXData[2]=255
RXData[3]=254
sollten die 29 Bit alle eins sein, aber die Ausgabe auf dem Display
zeigt etwas anderes.
Nach:
betragen die Werte:
data11=252
data22=127
Das passt auch genau zu der Displayausgabe:
00000011111100
000000001111111
Ich finde den Fehler einfach nicht. Die Umwandlung itoa scheint richtig
zu sein, da die 252 ja zu den 11111100 passt und die 127 zu der 1111111.
Da scheint doch noch was bei data110 (RXData[0]...usw. nicht ganz zu
stimmen....
Jemand eine Idee, woran es liegen könnte?
Hallo zusammen,
niemand eine Idee? Ich komme da einfach nicht weiter.
Es scheint so, als wenn das ( RXData[0] << 8) und ( RXData[1] << 8)
nicht
gefressen wird.
Grüße
Steffen R. wrote:
> Es scheint so, als wenn das ( RXData[0] << 8) und ( RXData[1] << 8)> nicht> gefressen wird.
Was glaubst Du wohl, weshalb ich die Ausgangsvariablen in meinem
Beispiel erst nach unsigned int konvertiert habe? Wenn die Variablen
nur 8 Bit haben, kannst Du doch wohl durch ein wenig Überlegen drauf
kommen, was passiert, wenn man die um 8 Stellen nach links schiebt, oder
nicht? Allerdings fehlt die Definition der Ausgangsvariablen in Deinem
obigen Post, weshalb man nicht mit Gewissheit sagen kann, ob es daran
liegt.
Abgesehen davon habe ich keine Ahnung, was Du da mit den Array-Elementen
rechnen willst. Was soll der Krempel?
Du hast nach der Umwandlung mit der Schieberei zwei 16-Bit-Werte, in
denen schön sortiert die interessanten Bits stehen. Damit kann man auch
rechnen. Wenn der ganze Rotz dann ausgegeben werden soll, werden eben
diese beiden 16-Bit-Werte mit itoa in jeweils einen ASCII-String
umgewandelt, den auch das Display oder ein Terminalprogramm versteht.
Mit dem String selber wird nix gerechnet, kein Modulo oder sonst
irgendwelche Sachen.
Oder soll das da oben eine selbst geschriebene
Binär-ASCII-Konvertierungsfunktion werden?
Sieht schon besser aus, aber irgendwas stimmt noch nicht.
Als Ergebnis habe ich nun 11111111111100(data1) und
111111101111111(data2)!?
Irgendwo hängts :(
Steffen R. wrote:
> Sieht schon besser aus, aber irgendwas stimmt noch nicht.>> Als Ergebnis habe ich nun 11111111111100(data1) und> 111111101111111(data2)!?
Klar, was soll denn auch das da:
> > data22 = ( (unsigned int)RXData[2] << 8) | (RXData[3] & 0xFE) >> 1;
^^^^
||||
Steffen R. wrote:
>>Oder soll das da oben eine selbst geschriebene>>Binär-ASCII-Konvertierungsfunktion werden?>> itoa Nutzung umgehen. Sollte doch das gleiche sein!
Du schriebst aber in Deinem Post weiter unten noch was von itoa, weshalb
ich davon ausging, dass da zusätzlich noch irgendwas mit itoa gemacht
werden sollte!
So,
das >> 1 war mal um das letzte Bit rauszuschieben.....
Jetzt funktioniert es, vielen Dank, war ne schwere Geburt. Hab bei den
Bitschieberein auch was verwechselt.
Gibt es noch eine Möglichkeit bei data1 die beiden Nullen am Ende und
bei data1 die Null am ende zu entfernen. Die entstehen ja durch die
Umrechnerrei zu binär.
Steffen R. wrote:
> Gibt es noch eine Möglichkeit bei data1 die beiden Nullen am Ende und> bei data1 die Null am ende zu entfernen. Die entstehen ja durch die> Umrechnerrei zu binär.
Was heißt "entfernen"? Wenn Du weißt, dass in den beiden Stellen nichts
Verwertbares steht, brauchst Du sie ja nicht auszugeben. Es steht Dir
auch frei, die beiden Ausgangswerte vor der Konvertierung nach ASCII
"rechtsbündig" auszurichten. Entweder direkt beim Einlesen (also bei dem
Zweizeiler mit den Schiebeoperationen) oder direkt vor der Wandlung.
Wenn Du alle 16 Bits gewandelt hast, kannst Du auch einfach den
Nullterminator an die entsprechende Stelle setzen. Die meisten
Standard-Ausgabefunktionen nehmen den schließlich als
String-Ende-Markierung. Wenn Du also Dein Array mit 17 Elementen hast
(16 plus '\0'), Du aber nur die ersten 14 Stellen ausgeben willst, dann
setze einfach das 15. Element des Arrays zu '\0'.
Hallo,
vielen Dnak, ich habe jetzt erst einmal den Nullterminator an die
entsprechende Stelle gesetzt. Das funktioniert erst einmal. Die anderen
Varianten werde ich nach und nach mal versuchen umzusetzen.
Beste Grüße
Steffen