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_tbuffer[10];
2
3
voidscale(uint32_tvol){
4
5
uint8_ti;
6
uint8_ta;
7
uint8_tb;
8
uint8_tc;
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
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
Das ist doch normaler Dreisatz:
X Bit (ADC Messwert)
max Zählerwert (100%) 4095 Bit (12-Bit Auflösung)
V_max = 3.3V
gesucht:
V_mess
V_mess X
------ = ----
V_max 4095
nach umformen gilt:
V_mess = X * V_max /4095
man muss nur einen passenden Zahlentyp wählen.
Schau dir bitte mal 32Bit float an.
Irgendwer schrieb:> uint8_t i = vol 100 0.0008056640;> ...und wie ist der Wertebereich von uint8_t und welcher Typ von Zahlen> wird damit dargestellt?LOL hab ich überlesen.
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.
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.
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.
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);
Gebe die Werte a, b und c auf meinem LCD-Display aus. Die Umrechnung des
Dezimalwertes in die Spannung und in die Dezimalstellen passt also. Habe
gedacht dass es an dem sprintf liegt.
Tausche deinen GCC mal durch GCC8 aus und mach -Wall -Werror an.
Dann lässt er dich das nicht kompilieren, weil du sprintf deinen Buffer
überlaufen kann.
MaWin schrieb:>> 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);
Mhm. Reicht eigentlich für die kleine Anwendung. Werde dann wohl noch
etwas den Code verbessern.Danke
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.