Eine weitere Bitumrechnung

Gast #5761530
Lesenswert?

Guten Abend,

Komme bei der ganzen Bitumrechnung nicht mehr klar. Habe folgendes 
Problem: Möchte die Dezimalzahl meines AD Wandlers (12-Bit Auflösung, 
3.3V Ref) in die Spannung umrechnen und per UART übertragen. Fordert 
mich mehr als ich dachte.
1
uint8_t buffer[10];
2

3
void scale(uint32_t vol){
4

5
  uint8_t i;
6
  uint8_t a;
7
  uint8_t b;
8
  uint8_t c;
9

10
  i = vol*100*0.0008056640;
11
  a = i/100;
12
  b = (i- (a*100))/10;
13
  c = (i- (a*100 + b*10));
14

15
  sprintf(buffer, "%hd.%hd%hdV\n",a,b,c);
16
  HAL_UART_Transmit(&huart2, buffer, 9, 1000);
17
}

Im Anhang sieht man was ich empfange. Wahrscheinlich ein kleiner dummer 
Fehler aber finde ihn nicht. Vllt hat jemand langeweile und hilft mir. 
Danke
Angehängte Dateien:
Gast #5761540
Lesenswert?

STm32 schrieb:
> Im Anhang sieht man was ich empfange. Wahrscheinlich ein kleiner dummer
> Fehler aber finde ihn nicht. Vllt hat jemand langeweile und hilft mir.
> Danke

Wenn du sowieso schon sprintf verwendest, kannst du auch gleich %f oder 
in deinem Fall %.2f verwenden.
Einfach mal sprintf googlen.
%hd geh;rt da eh nicht rein. Das gehört zu scanf
Gast #5761581
Lesenswert?

my2ct schrieb:
> Karl M. schrieb:
>> Schau dir bitte mal 32Bit float an.
>
> Warum braucht man zur Darstellung von 12-Bit Werten eine 32Bit float
> Zahl.
>
> Nur um bei der Ausgabe einen Dezimalpunkt zu erzeugen?
> Dafür reicht es, an passender Stelle ein 0x2E zum UART zu schicken.

Ja mir klar, aber der TO muss erst mal einen Fuß auf den Boden bekommen.

Sonst hätte ich auch schon eine Optimierung vorgestellt.
Gast #5761589
Lesenswert?

STm32,

wenn man anstatt V_max = 3,3V eine anderen Wertebereich nutzen möchte,
z.B. !!!!! 1mV,
dann wäre V_max = 3300mV und schon passt das in Ergebnis mit 
Nachkommastellen in eine 16Bit Variable.

Bei Berechnungen müssen dann auch Bereichsüberläufe beachtet werden.
D.h. eine Multiplikation von: 16Bit * 16Bit passt in 32Bit.
Gast #5761590
Lesenswert?

STm32 schrieb:
> Wahrscheinlich ein kleiner dummer Fehler a

In i, a, etc. passe  nur Werte von 0 bis 255 ohne Nacbkommastellen.

Deine mathematischen Formeln erzeugen aber weit mehr.

Ein sprintf zu verwenden ist Wahnsinn, das ist eine der aufwändigsten 
Funktionen die es gibt.

Rechne deine vol in eine 10Millivoltzahl um.

int i=(vol x 100L)/1241;

und schreibe selber die Ziffern mit Komma

char buffer[6];
buffer[5]='\0';
buffer[4]='V';
buffer[3]='0'+(i%10);
i/=10;
buffer[2]='0'+(i%10);
i/=10;
buffer[1]='.';
buffer[0]='0'+(i%10);
Gast #5761608
Lesenswert?

Variante 1, einfach Millivolt ausgeben:
1
void send_millivolt(uint16_t val)
2
{
3
  char buf[16];
4
  uint16_t x = (val * 3300ul + 2048) / 4095;
5

6
  HAL_UART_Transmit(&huart2, buf, sprintf(buf, "%umV\n", x), 1000);
7
}
Oder etwas anders, diesmal mit Nachkommastellen:
1
void uart_puts(char *buf)
2
{
3
  HAL_UART_Transmit(&huart2, buf, strlen(buf), 1000);
4
}
5

6
void send_volt(uint16_t val)
7
{
8
  char buf[16];
9
  uint16_t x = (val * 330ul + 2048) / 4095;
10

11
  sprintf(buf, "%u.%02uV\n", x/100, x%100);
12
  uart_puts(buf);
13
}

Das "ul" in "* 3300ul" damit eine 32-bit-Multiplikation gemacht wird. 
Das "+ 2048" zum Runden.  Zerlegung der Zahl mittels "/" und "%".
#5761758
Lesenswert?

Karl M. schrieb:
> Bei Berechnungen müssen dann auch Bereichsüberläufe beachtet werden.

Das hat mich früher auch genervt bzw. Fehler verursacht. Daher mache ich 
solche Rechnungen nur noch in float. So schlecht sind die Libs von 
AVR/8051 ja nicht.
Wenn "?" angezeigt werden, muß man noch den float Teil von sprintf dazu 
linken.
Die ersten AVRs litten noch unter Flash-Geiz (nur 1..2kB), aber das ist 
lange her.

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