hi! ich habe hier ein kleines problem mit dem resultat einer ADC unter verwendung der differential gain stage. das eigentliche messen ist kein problem, nur die umwandlung des resultates in eine brauchbare form. der AVR spuckt dabei das resultat als "two's complement" aus. der bereich -512 bis null geht dabei von 0x200(-512) bis 0x3FF(0), +512 werden zu 0x1FF. in dieser form ist das ergebnis für mich unbrauchbar, zumal es sich noch über ADCH:ADCL verteilt. ich brauch es als 0..1023 bzw 0x000..0x3FF. aber irgendwie stell ich mich zu doof an um eine schnelle umwandlung hinzubekommen, ich würde mich freuen wenn jemand sowas schon mal gemacht hat und mir etwas auf die sprünge helfen kann. dezimal wäre es einfach (+1024 und erledigt), aber ich bekomm das mit den geteilten bereichen irgendwie nicht gebacken, weil der negative bereich "über" dem positiven liegt.
mach daraus erstmal ein signed short (bitshift nach links um 6, aritmetischer shift nach rechts um 6, das zieht dir das Vorzeichen in die oberen 6 bits) dann einfach +512 um -512 bis + 511 auf 0 bis 1023 zu bringen.
1 | signed short val = (((signed short)in << 6) >> 6) + 512 ; |
mist, zum zweiten mal vergessen... ja, assembler. entschuldigt bitte!
moin für 8 Bit hät ich was , war mal für nen Dallas Temp.sensor. +125 01111101 7Dh 0 00000000 00h -55 11001001 C9h das wären die Zahlen -55 bis +125 in einem Byte (8bit)
1 | ;*************************Two's complement in ASCII*********************************************** |
2 | ; Hexdezi used two highregister And 5 Low registers |
3 | ;aa = r16 , r6,r7,r8,r9,r10 |
4 | |
5 | ;r6-r7 Hex Bcd wandlung |
6 | |
7 | ; zu wandelnder Wert in aa |
8 | |
9 | |
10 | .include "2313def.inc" |
11 | |
12 | |
13 | .def aa = R16 ;input two's complement |
14 | .def temp = R17 ; scratch space |
15 | |
16 | ; Ergebnis in |
17 | .def dezv =R08 ;dezimal ausgabe in ascii |
18 | .def dezh =R09 ; |
19 | .def dezl =R10 ; |
20 | ;************************************************************************ |
21 | rjmp RESET ; Reset Handle |
22 | ;************************************************************************ |
23 | |
24 | |
25 | |
26 | RESET: |
27 | |
28 | ldi zl,Low(RAMEND) ;Stack setzen |
29 | out SPL,zl |
30 | rcall hexdezi |
31 | loop: |
32 | rjmp loop |
33 | |
34 | ;***************************************************************************** |
35 | ; aa = two's complement number |
36 | |
37 | hexdezi: |
38 | ;wenn negativ 2 zahlen + vorz. sonst 3 |
39 | sbrc aa,7 ;Bit 7 gesetzt dann neg. - test auf negative Zahl |
40 | rjmp negaz |
41 | ;test auf größer 99 |
42 | bin2bcdh: |
43 | clr temp ;Clear result msd |
44 | bBCD83: |
45 | subi aa,100 ;Input = Input -100 |
46 | brcs bBCD84 ;abort If carry Set |
47 | inc temp |
48 | rjmp bBCD83 |
49 | bBCD84: |
50 | subi aa,-100 |
51 | mov dezv,temp |
52 | rcall bin2bcd |
53 | rcall bcdasc |
54 | mov dezh,r6 |
55 | mov dezl,r7 |
56 | mov aa,dezv |
57 | rcall bcdasc |
58 | mov dezv,r7 |
59 | ret |
60 | ;************************************************************************** |
61 | negaz: |
62 | neg aa ; negative Zahl ist zweiercomplement |
63 | rcall bin2bcd |
64 | rcall bcdasc |
65 | ldi temp,'-' ; minus ascii |
66 | mov dezv,temp |
67 | mov dezh,r6 |
68 | mov dezl,r7 |
69 | ret |
70 | |
71 | ;************************************************************************** |
72 | ; 8Bit Binär in packed Bcd - wert in aa - ergebnis in aa ! |
73 | bin2bcd: |
74 | clr temp ;Clear result msd |
75 | bBCD81: |
76 | subi aa,10 ;Input = Input -10 |
77 | brcs bBCD82 ;abort If carry Set |
78 | subi temp,-$10 ;für packed Bcd |
79 | rjmp bBCD81 |
80 | bBCD82: |
81 | subi aa,-10 |
82 | add aa,temp |
83 | ret |
84 | ;*************************************************************************** |
85 | ; Bcd - zahlen in 2 ASCII char --- wert in aa - ergebnis in r6 und r7 h/l Byte |
86 | ; |
87 | bcdasc: |
88 | mov temp,aa ; aa aufheben |
89 | lsr temp |
90 | lsr temp |
91 | lsr temp |
92 | lsr temp ;Msb ins Lsb schieben |
93 | ori temp,0x30 ;$30 dazuodern erzeugt ascii 30 -39 da nur zahl 0-9 |
94 | mov r6,temp |
95 | andi aa,0x0f ;löschen des Msb |
96 | ori aa,0x30 |
97 | mov r7,aa |
98 | ret |
kann man mit AVRStudio simulieren
Hi Ohne Gewähr: Vorsicht Pseudocode! in r16,ADCL in r17,ADCH wenn Bit1 von r17=H dann com r16 ; change sign com r17 subi r16, LOW(-1) sbci r17,High(-1) weiter mit add r16, Low($200) adc r17, High($200) MfG Spess
Hallo, ist doch ganz einfach: das Höchstwertige Bit enthält Dein Vorzeichen (0 = +, 1 = -) Damit das Ganze ein "echtes" 2er Komplement gibt könntest Du das Vorzeichen in alle bits oberhalb des Vorzeichens eintragen (also wenn Bit9 gesetzt ist dann setze Bit 10-15 ebenfalls). In Assembler wäre dies eine einfache Oder-Verknüpfung im High-Byte mit 0xFC falls Bit 9 gesetzt ist. Danach hast du ein echtes 2er-Komplement. (-512 bis +511) Wenn Du jetzt 512 addierst (also 0x02 zum High-Byte) dann erhälst Du den Zahlenbereich 0..1023 Tims Vorschlag in "C" macht im Prinzip auch nichts anderes.
Du kannst auch ADLAR setzen. Damit erhältst Du vorzeichenbehaftete fortlaufende Zahlen und sparst Dir ggfs. die Schieberei.
Hi Noch mal im Reinformat: in r16,ADCL in r17,ADCH sbrs r17,1 rjmp aaa com r16 ; change sign of dividend com r17 subi r16, LOW(-1) sbci r17,High(-1) aaa: ldi r18, Low($200) ldi r19,High($200) add r16,r18 adc r17,r19 MfG Spess
stelle fest ich kriegs heute in meine birne nicht rein. vielleicht schon zu lange dran rumprobiert. ich probiers mal mit deinem code spess!
gibts eigentlich einen AVR der das auch bei differentiellen inputs als "lineares" ergebnis ausgeben kann? das wäre für mich glatt ein grund dahin zu wechseln. ich kapier den sinn davon nicht, es macht diese differentiellen eingänge unnötig kompliziert.
geht leider noch nicht, der code negiert mir das ergebnis. sprich beim absenken der zu messenden spannung wird eine steigende "gemessen". irgendwas ist da noch murks aber ich hab heute keine lust mehr mich weiter mit dem schrott zu befassen.
Hi >gibts eigentlich einen AVR der das auch bei differentiellen inputs als >"lineares" ergebnis ausgeben kann? das wäre für mich glatt ein grund >dahin zu wechseln. ich kapier den sinn davon nicht, es macht diese >differentiellen eingänge unnötig kompliziert. Warum?. Das widerspricht für meine Begriffe dem Prinzip der differenziellen Messung. Es soll ja bestimmt werden, um welchen Betrag eine Spannung grösser oder kleiner als eine andere ist. Möglicherweise liegt dein Denkfehler schon etwas weiter davor. Aber da niemand weiss, worum es geht........... MfG Spess
es geht um eine möglichst genaue spannungsmessung in einem vorgegebenen bereich. mehr nicht. um die auflösung zu verbessern wollte ich den vollen messbereich auf den interessanten spannungsbereich bringen, das wären 9-16V. die 9V müssen daher irgendwie "weg". mit einem differentiellen verstärker und einer 10x gain stage ginge das sooo schön wenn man anstelle GND an einen pin eine feste offsetspannung anlegt, welche der des spannungsteilers bei 9V entspricht. der differentialverstärker würde bei der messung von 12V nun nur noch 3V "sehen" und der ADC kann im bereich von 9-16V mit vollen 10bit messen. jedenfalls in der theorie. in der praxis schreibt der atmel kack aber vor, daß die messung nicht von 0..1023 sondern von -512..511 zu erfolgen hat. klasse idee, kann mir mal einer sagen wieso das sein MUSS?! okay, das bedeutet als erstes, daß die referenzspannung zum "wegkompensieren" der unwichtigen 9V um 0.25V angehoben werden muß damit man den vollen messbereich bekommt. aber daß dieses "+-"-verhalten bis ins programm reingezogen wird ist mir unverständlich - ein adc-ergebnis im bereich 0..1023 wäre deutlich einfacher zu handhaben. wenn dann jemand positive/negative ausgaben braucht wäre das ebenfalls sehr einfach möglich, das höchste bit läßt sich immer noch als vorzeichen gebrauchen...
Ben _ schrieb: > in der praxis schreibt der atmel kack aber vor, daß die messung nicht > von 0..1023 sondern von -512..511 zu erfolgen hat. klasse idee, kann mir > mal einer sagen wieso das sein MUSS?! Weil die Differenz nun mal positiv oder negativ sein kann. Wo liegt denn da das Problem? Vorzeichenbit ansehen, erweitern auf 16 Bit und 512 addieren. Das kann doch nicht so schwer sein. > einfacher zu handhaben. wenn dann jemand positive/negative ausgaben > braucht wäre das ebenfalls sehr einfach möglich, das ist genauso einfach/schwierig wie der umgekehrte Weg. Du stellst dich an, wie jemand der sich wundert warum sein OpAmp auch negative Differenzen verstärkt.
na das problem ist aber auch, daß sich durch den schrott die 10x gain stage wie eine 5x gain stage verhält. das ist für eine sinnvolle strommessung mit der internen referenz schon wieder die ganz unterste grenze. 200x würden sich wie 100x verhalten, das ist aber schon wieder zuviel des guten. reale 10x wären schon schick gewesen, so kostet das die hälfte der auflösung. zum glück immer noch genug, aber es wäre halt mehr drin gewesen. ich fänds praktischer wenn ich immer einen wert zwischen 0..1023 bekommen würde, den nullpunkt kann man sich dann mit einfachen ADDs bzw. SUBs hinschieben wo man ihn haben will. habe für das eigentliche problem aber eine supereinfache lösung gefunden: mit einem XOR auf das vorzeichenbit ballern und der spuk ist vorbei!
Und warum nimmst Du nicht die Mitte des interessierenden Bereichs als Referenzspannung? Da Du die ja sowieso mit einem einfachen Spannungsteiler erzeugen willst ist die dort genauso ungenau. Gast
> Und warum nimmst Du nicht die Mitte des interessierenden Bereichs als > Referenzspannung? hab ich. anders gehts ja auch nicht.
Ben _ schrieb: > geht leider noch nicht, der code negiert mir das ergebnis. sprich beim > absenken der zu messenden spannung wird eine steigende "gemessen". Das Ergebnis darf auch nicht komplementiert werden, es muss das Vorzeichen ergänzt (nach oben erweitert) werden. Code:
1 | in r16,ADCL |
2 | in r17,ADCH |
3 | |
4 | sbrs r17,2 |
5 | rjmp is_positive |
6 | |
7 | ori r17,0xFC // Vorzeichen erweitern |
8 | |
9 | is_positive: |
Ergebnis ist eine Zahl zwischen -4096 bis +4095.
Der letzte Satz war nicht ganz richtig: Das Ergebnis ist eine Zahl zwischen -512 und +511. Wie Du von dort aus auf 0..1023 kommst, bedarf wohl keiner Erklärung.
Hallo, in r16,ADCL in r17,ADCH subi r17,0x02 // add 02 zum H-Teil andi r17,0x03 // Überträge ignorieren sollte passen. Gruß aus Berlin Michael
IN R16,ADCL IN R17,ADCH LDI R18,2 EOR R17,R18
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.