Ausgabe mittels sprintf im Binärformat nicht möglich?

Hi,

kann man in C keine sprintf-Formatierung im Binärformat machen?
Also so:

   void printIrString () {
     char tmp[20];
     for (int s = 0; s < 19; s++) {
         sprintf(tmp, "Byte %02d:  %02X  %08b" , s , irString[s], irString[s]);
         Serial.println (tmp);
     }
     Serial.println ();
   }

Soll ein Bytearray sowohl als Hexzahl, und neben dran als Binärzahl darstellen. Hexzahl geht, Binärzahl nicht.
Ja ich weiss, es ginge auch mit: Serial.println (irString[s], BIN); Aber da fehlen halt die führenden Nullen.

Nein. Das geht nicht.

printf() Doku für den Arduino:
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#gaa3b98c0d17b35642c0f3e4649092b9f1
Hier allgemein, aber das ist etwas umfangreicher als was auf dem Arduino möglich ist:
http://www.cplusplus.com/reference/cstdio/printf/

Du kannst erst mal berechnen wie viele Stellen deine Zahl als Binär braucht. Und dann vorher so viele Nullen ausgeben. Danach dann print() mit BIN machen.

Wenn du eher eine C Funktion willst, geht das hiermit:
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#gad50d835af7e358518fd100179732e948
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga34f41757388f40e340f31e370ac009b5
Da musst du dir aber auch die führenden Nullen danach per Hand erzeugen. Anders als bei print(..., BIN), könntest du aber einfach mit strlen() feststellen wie lange der String ist der rauskommt. Und dann einfach durch Subtraktion wissen wie viele Nullen du brauchst. Also keine große Sache.

So z.B.:

void setup()
{
  Serial.begin(115200);
}

void loop() 
{	
  printBinary(20, false);
  printBinary(2569, false);
  printBinary(32768, false);
  Serial.println();

  printBinary(20, true);
  printBinary(2569, true);
  printBinary(32768, true); 
  Serial.println();

  delay(3000);
}

void printBinary(unsigned int value, bool leadingZeroes)
{
  char buffer[20];
  utoa(value, buffer, 2);

  if(leadingZeroes)
  {
	int length = strlen(buffer);
	for(int i = length; i < 16; i++)
		Serial.print('0');
  }

  Serial.println(buffer);
}

Lässt sich auch noch weiter anpassen. Du kannst einen Parameter übergeben und festzulegen auf welche Breite formatiert wird.

Die Ausgabe auf Hex geht auch so, mit 16 als 3. Parameter für utoa(). Da könnte man erst mal Hex ausgeben und danach Binär.

Hi Serenifly, mein persönlicher Forumsjoker :stuck_out_tongue:

So variabel brauch ichs gar nicht. Will ja nur immer ein Byte ausgeben.
Hab daher nur das wesentliche aus deinem Beispiel gezogen.
Aber irgendwie bringt der neue Code den UNO zum abkacken:

   void printIrString () {
     char tmp[10];
     for (int s = 0; s < 19; s++) {
         sprintf(tmp, "Byte %02d: %02X " , s , irString[s]);
         Serial.print (tmp);
         utoa(irString[s], tmp, 2); 
         int length = strlen(tmp);
	 for(int i = length; i < 8; i++)
		Serial.print('0');
         Serial.println (irString[s], BIN);
      }
     Serial.println ();
   }

EDIT:

Aaaaahhhh:

     char tmp[10];

Was hat mich da geritten...... dachte für die Binärzahl ist das array groß genug. Aber für den sprintf hats dann nicht mehr gereicht.
Schäm

BTW: Danke dass du gleich immer ein Codebeispiel hinterherschickst. Das machts für mich dann doch leichter. 8)

10 Bytes sind für den String zu wenig

Ich mal etwas rumgespielt. Du kannst auf das aufwendige printf() komplett verzichten (die Funktion braucht sehr viel Flash):

void loop() 
{	
	for(int i = 0; i < 19; i++)
		formatNumber(i, 2, 2, 8);

	Serial.println();

	delay(5000);
}

void formatNumber(unsigned int value, int decimalWidth, int hexWidth, int binaryWidth)
{
	char buffer[20];
	Serial.print(F("Byte "));
	utoa(value, buffer, 10);
	printLeadingZeroes(buffer, decimalWidth);
	Serial.print(buffer);
	Serial.print(F(": "));
	utoa(value, buffer, 16);
	printLeadingZeroes(buffer, hexWidth);
	Serial.print(buffer);
	Serial.print(' ');
	utoa(value, buffer, 2);
	printLeadingZeroes(buffer, binaryWidth);
	Serial.print(buffer);
	Serial.println();
}

void printLeadingZeroes(char* str, int count)
{
	int length = strlen(str);
	for(int i = length; i < count; i++)
		Serial.print('0');
}

Wenn du jetzt noch Hex in Großbuchstaben willst tut es ein strupr(buffer):
http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html#gaa50fa5cd42285f7c3980a3b0eafe77b5

Serenifly:
Ich mal etwas rumgespielt. Du kannst auf das aufwendige printf() komplett verzichten (die Funktion braucht sehr viel Flash):

Yep, haste recht. Sind ~1,6k
Morgen bau ich um. Jetzt fallen mir schon die Deckel runter.

Danke und gute N8