C binaeren string in dezimal umwandeln

AVRuser

Neues Mitglied
20. Apr. 2011
217
0
0
Niedersachsen
Sprachen
  1. BascomAVR
  2. ANSI C
Hallo Leute,

Wie Wandle ich am besten einen binaeren string, in Form von
bool name[12]; in eine dezimal zahl also integer um?
 
Hallo Leute,

Wie Wandle ich am besten einen binaeren string, in Form von
bool name[12]; in eine dezimal zahl also integer um?

Handelt es sich um ein boolean Array oder um einen char Array, weil du von einem string sprichst?

Wie ist denn das Array aufgebaut, vielleicht wird es dann klarer ...

name[0] =
name[1] =
name[2] =
...

"dezimal zahl also integer" ist wie "Obst und Farbe". (dezimal=Darstellung im Dezimalsystem, integer=ganzzahliger Datentyp)

Ich nehme an, du möchtest das Ergebnis einfach als uint16_t ?!
Oder noch etwas weiter als string mit Dezimalzahl?

Dirk :ciao:
 
Also, es handelt sich um ein bool array also:
bool name[12] = {0,1,0,1....};

Es handelt sich dabei um ausgelesene Daten-bits aus einem ADC...

Diese binaer im Bool-Array vorliegende Zahl möchte ich in einen uint16 wert umwandeln

Beispiel:

bool xyz[4] = {0,1,0,1};
uint16_t abc = xyz[]
abc = 5

Ich hoffe das ist nachvollziehbarer:D
 
Wie gelangen denn die Einzelbits in das Bit-Array? Im Speicher des AVR sind sie eh in irgendeiner Form in Bytes abgelegt. Wenn Du also die 12 Bits innerhalb zweier Bytes geschickt im SRAM anordnest, kannst Du einerseits die Einzelbits setzen/löschen, andererseits aber die bytes/das word direkt verwenden. Stell Dir einfach vor, wie Dein UINT16 im Speicher aussieht.
 
Ich hoffe das ist nachvollziehbarer:D

Ok, das ist jetzt klar :D

Es könnte prinzipiell folgendermaßen aussehen, du müsstest dir es halt noch ein bisschen zurechtbasteln.
Die Arraygröße ist hier einfachheitshalber konstant 4.

Dirk :ciao:

Code:
    uint8_t i;
    uint16_t result;    
    bool xyz[4] = {0,1,0,1};
        
    i = 4;
    result = 0;
    while (i)
    {
        i--;
        if (xyz[i]) result += 1<<(3-i);    
    }
    
    // result ist das Ergebnis
 
Wie gelangen denn die Einzelbits in das Bit-Array? Im Speicher des AVR sind sie eh in irgendeiner Form in Bytes abgelegt. Wenn Du also die 12 Bits innerhalb zweier Bytes geschickt im SRAM anordnest, kannst Du einerseits die Einzelbits setzen/löschen, andererseits aber die bytes/das word direkt verwenden. Stell Dir einfach vor, wie Dein UINT16 im Speicher aussieht.

Hallo LotadaC,

bei AVR GCC (stdbool.h) hat der Datentyp bool eine Größe von einem Byte :eek:, also nix mit Platz sparen ;) Es liegt am Compiler, wie er damit umgeht. Bei Assembler würden wir das sicherlich mit Bitadressierung machen ... wenns schnell oder einfach gehen soll, nehme ich aber da auch schon mal ein Byte :eek: ;)

Da es sich bei C um eine Hochsprache handelt, ist es erst mal nicht so wichtig/interessant, wie die Daten im SRAM abgelegt werden.

Dirk :ciao:
 
erstmal danke, für eure schnellen Antworten...

Vieleicht wäre es einfacher wenn ich den Wert gleich anders einlese:

Ich habe eine For schleife und mit jedem durchlauf kommt ein Bit vom 12bit ADC dazu

Momentan habe ich (vereinfacht):

for i {
...clkpulse etc...
boolarrey = ADCdataout
}

Wie könnte ich das besser lösen?

PS: Kein Hardware-SPI und kein Interrupt...
 
Ich habe eine For schleife und mit jedem durchlauf kommt ein Bit vom 12bit ADC dazu

Momentan habe ich (vereinfacht):

for i {
...clkpulse etc...
boolarrey = ADCdataout
}

Wie könnte ich das besser lösen?

PS: Kein Hardware-SPI und kein Interrupt...


Ach jetzt weiß ich was du machen möchtest. Du möchtest einfach nur seriell die Bits hinein shiften, also wie bei SPI nur ohne Datenbits zu senden.

Hier habe ich mal SoftwareSPI realisiert:

Im Beispiel werden 8Bits gelesen/geschrieben, das kann man an die benötigte Bitanzahl anpassen und auch den Sendebereich entfernen. Ansonsten ist es einfach eine ganz einfache Bitschiebereisache.

Schau dir mal das Projekt an: Atmel Studio 6 Library für Displaymodul-Familien XV-TFT2428T, XV-TFT50D und XV-TFT60D
genauer: Display_Interface_AVR8.h


(ich kann aber auch morgen mal was an deine Anwendung anpassen, wenn ich Zeit finde)

Dirk :ciao:


Code:
  /***
  Software SPI
  
  Note: Maximum SPI frequency is 2MHz. Typical frequency achived by function below
        is 1,5MHz with a Xmega AVR at 32MHz systemclock. If using other systems, possibly
        you have to insert delays, to slow down SPI frequency.
  ***/

  uint8_t _SPI_RW (uint8_t output)
  {
    uint8_t input=0;
    uint8_t i;
    
    for (i=0; i<8; i++)
    {
      DISPLAY_SPI_PORT &= ~(1<<DISPLAY_SPI_SCK);      // SCK low

      if (output & 0x80)
        DISPLAY_SPI_PORT |= 1<<DISPLAY_SPI_MOSI;      // MOSI high
      else
        DISPLAY_SPI_PORT &= ~(1<<DISPLAY_SPI_MOSI);   // MOSI low

      DISPLAY_SPI_PORT |= 1<<DISPLAY_SPI_SCK;         // SCK high

      input <<= 1;          // Input MISO

      if (DISPLAY_SPI_INPORT & (1<<DISPLAY_SPI_MISO))
          input |= 1;
      else
        input &= ~1;

      output <<= 1;

    }
    
    return input;                            //return the byte clocked in from SPI slave
  }






 
Danke, damit sollte ich das hinkriegen:)
 
Ok, das auslesen Funktioniert jetzt, für die Kanaleinstellung müsste ich allerdings noch wissen,
wie man zu nem uint16_t einen uint8_t bitweise zuadiieren kann, also Beispielsweise:

uint16_t abc = 0b010101;
uint8_t def = 0b111;

abc (bitweise dazuaddiert) def = 0b010101111

Ist hoffentlich einigermaßen verständlich:D
 
uint16_t abc = 0b010101;
uint8_t def = 0b111;

abc (bitweise dazuaddiert) def = 0b010101111

Ist hoffentlich einigermaßen verständlich:D

:D ich vermute du meinst mit "bitweise dazu addieren":

uint16_t abc um 3 bit nach links shiften und uint8_t def addieren. Das geht so:


Code:
uint16_t abc;
uint8_t def;
uint16_t ergebnis;


ergebnis = (abc << 3) | (def & 0x07);

Bei def werden nur die niederwertigsten drei Bits verwendet.

Dirk :ciao:
 
Danke, Dirk!:)
 
Hat sich gerade erledigt...
 
Gleich noch ne blöde Frage:

Um den 12bit-ADCwert in einen 0-99Wert umzurechnen verwende ich:


uint32_t ADCrout;

ADCrout = ADC(Vereinfacht);

ADCrout = ADCrout * 11 / 455;

return ADCrout; (uint16_t)

Allerdings scheint die Variable drei mal überzulaufen, innerhalb des Messberreichs...
Obwohl 4095*11 als höchste Vorkommender Wert ja nur 45045 sind und damit selbst in eine uint16_t
passen sollte. Sind die Nachkommastellen, die ich aber nicht brauche, das Problem?
 
Stimmt, uint16_t würde hier für ADC Werte 0..4095 reichen, wenn man mit 11 multipliziert.

Ich weiss jetzt aber nicht, was du mit "Nachkommastellen" meinst. Wenn hier weitere Stellen in dem uint16_t sind, dann funktioniert das so nicht.

Wie sieht denn das Ergebnis aus, was du vom ADC liest?
 
Vom ADC kommt ein Wert zwischen 0 und 4095,
dieser soll in einen Wert zwischen 0-99 umgewandelt werden...

Bei der Umrechnung etstehen natürlich Nachkommastellen- Bsp.:

2000 * 11 / 455 = 48,3616

Da ich die Nachkommastellen nicht brauche, dachte ich, das ich vieleicht einfach in
uint16_t rechnen kann...
 
Achso, diese Nachkommastellen. Die fallen einfach weg. Mit uint16_t muss es funktionieren, setze aber hier sicherheitshalber Klammern bei der Multiplikation:

Code:
uint8_t ConvertADCWert (uint16_t ADCWert)
{

  // uint16_t ADCWert; // 0..4095


  ADCWert = (ADCWert * 11) / 455;  // 0..99


  return (uint8_t)ADCWert;

}
 
mmh, der läuft leider immernoch drei mal über..:confused:
 
Ich lad gleich mal die ganze Funktion hoch, vieleicht muss ja noch einer mal nen
MCP3204/08 auslesen:

Code:
uint8_t extadc(uint8_t chnl){
	uint8_t ADCdata_f = 0b0000011;
	uint16_t ADCdata = (ADCdata_f << 3) | (chnl & 0x07);
	uint16_t ADCrout = 0;
	int i;
	PORTA &= ~(1 << ADcs);
	_delay_us(100);
	for (i = 0; i < 24; i ++){
		if ((ADCdata & 0x80) && (i <= 10)){
			PORTA |= (1 << ADdout);
		}else if (i <= 10){
			PORTA &= ~(1 << ADdout);
		}
		PORTA &= ~(1 << ADclk);
		_delay_us(250);
		PORTA |= (1 << ADclk);
		_delay_us(250);
		if ((PINA & (1<<ADdin)) && (i >= 12)){
			ADCrout <<= 1;
			ADCrout |= 1;
		}else if (i >= 12){
			ADCrout <<= 1;
			ADCrout &= ~1;
		}
		ADCdata <<= 1;
	}
	PORTA |= (1 << ADcs);
	ADCrout = (ADCrout * 11) / 455;
	return (uint8_t)ADCrout;
}

Aufruf sieht so aus:
Code:
poti3 = extadc(2);
lcd_puts("r:");
itoa(poti3, tmp2, 10);
lcd_puts(tmp2);
 
Funktioniert es immer noch nicht? Hast du direkt vor der Berechnung mal zum Beispiel ADCrout fest vorgegeben und kontrolliert?

Diese untere Zeile benötigst du nicht, da zuvor sowieso 0 nachgeschoben wurde.
Code:
}else if (i >= 12){
            ADCrout <<= 1;
            [B]ADCrout &= ~1;[/B]
        }
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)