mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Wie Zahl subtrahieren, die in 4 Registern steht?


Autor: 4register (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

es gibt ja die befehle subi und sbci
Dafür kann man aber ja immer nur ein Register nehmen, wie subtrahiert 
man also was, das in 4 Registern steht?

Autor: oha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In 4 registern ? Eine 32 bit Zahl ? Also, es gibt SUB, SBC, SUBI, etwa.
Damit kann man alles machen. Was soll denn genau gemacht werden ?

Unsigned32 - konstante32
unsigned32 - konstante16
Unsigned32 - unsigned32
unsigned32 - signed32
unsigned32 - unsigned16
unsigned32 - signed16
unsigned32 - unsigned8
unsigned32 - signed8

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Dafür kann man aber ja immer nur ein Register nehmen, wie subtrahiert
> man also was, das in 4 Registern steht?

Genauso, wie du das in der Schule mit Papier und Bleistift gelernt hast:
Mit dem niederwertisten Byte beginnen (SUB oder SUBI), dann der Reihe
nach die höherwertigen Bytes abarbeiten und dabei jeweils den Übertrag
berücksichtigen (SBC bzw. SBCI). Du brauchst für n Bytes also 1 SUB[I]-
und n-1 SBC[I]-Befehle.

Autor: 4register (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm,

also wenn sie in temp1..4 steht, und man zB 1 abziehen möchte, quasi so? 
:

subi temp1, (1)
subi temp2, (1)
sbci temp2, (1)
subi temp3, (1)
sbci temp3, (1)
subi temp4, (1)
sbci temp4, (1)

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, so:

subi temp1, (1)
sbci temp2, (0)
sbci temp3, (0)
sbci temp4, (0)

bgezogen wird nur 1. Die sbci-Befehle haben nur die Aufgabe, evtl. 
entstandene Borrows auf die nächste Stelle zu übertragen.

Autor: oha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nicht vergessen. auf tiefer Adresse steht auch auch das tieferwertige 
byte.

Autor: Marius Wensing (mw1987)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bist du dir da ganz sicher?

Ich würd mir mal bei Wikipedia oder so anschauen, was der Unterschied 
zwischen Little und Big Endian ist.

MfG
Marius

Autor: oha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fuer die AVR ist das so. Ja. Sicher.

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

für den AVR gilt in diesem Fall die Reihenfolge, in der sie der 
Programmierer in die Register rein geschrieben hat.

Anhaltspunkt wäre nur Ablage von 16Bit Werten in den Doppelregistern und 
damit die Nutzung der zugehörigen Befehle und die Ablage von Adressen im 
Flash wegen der Wordorganisation.

Verbindlich ist es aber genaugenommen auch nicht oder habe ich im 
AVR-Datenblatt was übersehen?

Gruß aus Berlin
Michael

Autor: oha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja. Der AVR ist little endian. Denn er hat 16 bit befehle. Genau 
hinschauen...

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oha wrote:
> Nicht vergessen. auf tiefer Adresse steht auch auch das tieferwertige
> byte.

Als ASM-Programmierer kann man das halten, wie man will. So lange keine 
Kompatibilität zu einer Progrmmiersprache erforderlich ist und man auf 
die Bequemlichkeit verzichten will, eine long-Variable im Debugger als 
solche zu sehen, kann man die vier Bytes sogar wahllos im Speicher 
verstreuen, oder gar Teile davon, oder alles in Registern halten.

Autor: oha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der AVR arbeitet intern schon mit little endian. Daher macht man sich 
Zusatzarbeit wenn man umgekehrt arbeiten will.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oha wrote:
> Der AVR arbeitet intern schon mit little endian. Daher macht man sich
> Zusatzarbeit wenn man umgekehrt arbeiten will.

Will man nur rechnen, ergibt sich keine Zusatzarbeit.
Erst, wenn das Ergebnis ein Adreßpointer (X,Y,Z) sein soll, ergibt sich 
eventuell etwas MOV-Arbeit.

Man hat also als Assemblerprogrammierer die freie Wahl. Ich benutze in 
den Arithmetikroutinen (+,-,/,*) daher gar keine festen Register, 
sondern Defines (a0..a3,b0..3). Wie man die dann Registern zuordnet, ist 
wurscht.


Peter

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger wrote:

> Will man nur rechnen, ergibt sich keine Zusatzarbeit.

Abgesehen von den AT90 und ein paar antiken Tinys haben AVRs auch ein 
bischen 16-Bit Arithmetik, wie ADIW. Damit wird aus dem Beispiel oben
 sbiw temp1, (1)
 sbci temp3, (0)
 sbci temp4, (0)
und dann ist nicht ganz unwichtig wie temp1/2 zueinander liegen.

Autor: 4register (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich hab so ein programm, dass mir die spannung in V anzeigt. wenn ich 
nun möchte, dass es mir immer 1V weniger anzeigt, muss ich dann das 
ganze platzieren, bevor es in ASCII oder nachdem es in ASCII umgewandelt 
wurde?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
4register wrote:
> ich hab so ein programm, dass mir die spannung in V anzeigt. wenn ich
> nun möchte, dass es mir immer 1V weniger anzeigt, muss ich dann das
> ganze platzieren, bevor es in ASCII oder nachdem es in ASCII umgewandelt
> wurde?


Sinnigerweise wird man das vor der ASCII Umwandlung machen.

Was interessiert alles was nach der ASCII Umwandlung kommt, was dein 
String zu bedeuten hat? Eben, gar nichts. Für die Ausgaberoutinen ist 
das einfach nur ein Text, nicht mehr.

Autor: oha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nochmals zurueck zu 16bit operationen... ADIW und SUBIW sind wesentliche 
Vereinfachungen, die man nicht sausen lassen sollte.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oha wrote:
> Nochmals zurueck zu 16bit operationen... ADIW und SUBIW sind wesentliche
> Vereinfachungen, die man nicht sausen lassen sollte.

Sind sie das?

Der Schreibaufwand im Assembler ist geringer, aber sonst gibts kaum 
einen Unterschied zu den Einzeloperationen.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kürzer.

Autor: Lymangood (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>es gibt ja die befehle subi und sbci
>Dafür kann man aber ja immer nur ein Register nehmen, wie subtrahiert
>man also was, das in 4 Registern steht?

Und wenn du dann damit fertig bist, probierst du den Spass mal als 
Addition. Dann wirst du feststellen, dass die AVR-Architektur der letzte 
Schrott ist und bei Atmel, im Gegensatz zu ihrer Werbung, niemals Kenner 
der Materie gearbeitet haben.

Atmel ist der letzte Schrott den es gibt!

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oha wrote:
> Nochmals zurueck zu 16bit operationen... ADIW und SUBIW sind wesentliche
> Vereinfachungen, die man nicht sausen lassen sollte.

Sie sind speziell nur dazu gedacht, ein kleines konstantes Offset auf 
nen Pointer zu berechnen.

In einer Math-Lib spielen sie keine Rolle, da möchte man 2 x-beliebige 
Werte addieren können.


Peter

Autor: mmerten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
zumal

subi
sbci

genauso 2 Takte braucht wie sbiw

daher nur 1 Wort weniger Flash-Bedarf aber nicht schneller und 
eingeschränkt.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lymangood wrote:

> Und wenn du dann damit fertig bist, probierst du den Spass mal als
> Addition.

Begründung? Wenn du ADDI,ADCI vermisst, dann denk dran, dass sich 
Addition und Subtraktion hier letztlich nur in den Flags unterscheiden. 
Für den Assembler-Programmierer ist das etwas hässlich aber dem Compiler 
völlig schnurz. Andererseits erpart das so erheblich Coderaum für 
wichtigere Befehle (SUBI+SBCI benötigen zusammen 12,5% des Coderaums).

Autor: Lymangood (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>hier letztlich nur in den Flags unterscheiden.
Naja, das ist ja das Problem, wenn du mit Zahlen grösser 8 Bit 
arbeitest.

>(SUBI+SBCI benötigen zusammen 12,5% des Coderaums).
Das ist Quatsch bei annähernd einhundert Befehlen. Oder, auf was 
beziehst du dich mit den 12,5 Prozent?

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lymangood wrote:
>>(SUBI+SBCI benötigen zusammen 12,5% des Coderaums).
> Das ist Quatsch bei annähernd einhundert Befehlen. Oder, auf was
> beziehst du dich mit den 12,5 Prozent?

Ja, alles Quatsch und Atmel ist scheiße!

Zusammen mit den Argumenten belegen beide Befehle (in allen möglichen 
Parametervarianten) nun mal 12,5 Prozent der möglichen 16 Bit.

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lymangood wrote:

> Atmel ist der letzte Schrott den es gibt!

Na ja, ich würde a den Mund nicht so voll nehmen. Instruktionssätze 
werden üblicherweise nicht mit irgend jemandem ausgehandelt, sondern an 
Hand von Statistiken über realen Code konstruiert. Als Randbedingung 
gehen Restriktionen durch Codewortbreite, vorhandene Hardwaremodule etc. 
pp. ein.

Aber das sieht man als Feld-, Wald- und Wiesengroßmaul natürlich 
nicht...

Autor: 4Register (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm,

habs in allen Variationen probiert, aber nie zieht der Controller was 
ab!
Dachte mir, dass dürfte nicht weiter schwierig werden, aber irgendwie 
funktioniert das nicht. Er zeigt halt nun statt 2,5 mal 2,3 V oder so 
an, aber nie das gewünschte :-(

Autor: oha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schade... zeig mal den code.

Autor: 4Register (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es ist der Code, der hier auf der Seite vorgestellt wird und läuft 
soweit einwandfrei.
Bei den ***** habe ich die Subtraktion mit hingeschrieben, da die Zahl 
nach der Multiplikation ja in temp1-4 abgelegt wird.




.include "m8def.inc"

.def z0        = r1          ; Zahl für Integer -> ASCII Umwandlung
.def z1        = r2
.def z2        = r3
.def z3        = r4
.def temp1     = r16         ; allgemeines Register, zur kurzfristigen 
Verwendung
.def temp2     = r17         ; Register für 24 Bit Addition, 
niederwertigstes Byte (LSB)
.def temp3     = r18         ; Register für 24 Bit Addition, mittlerers 
Byte
.def temp4     = r19         ; Register für 24 Bit Addition, 
höchstwertigstes Byte (MSB)
.def adlow     = r20         ; Ergebnis vom ADC-Mittelwert der 256 
Messungen
.def adhigh    = r21         ; Ergebnis vom ADC-Mittelwert der 256 
Messungen
.def messungen = r22         ; Schleifenzähler für die Messungen
.def zeichen   = r23         ; Zeichen zur Ausgabe auf den UART
.def temp5     = r24
.def temp6     = r25

; Faktor für Umrechung des ADC-Wertes in Spannung
; = (Referenzspannung / 1024 ) * 100000
; = 5V / 1024 * 1.000.000
.equ Faktor = 4883

.equ F_CPU = 4000000                            ; Systemtakt in Hz
.equ BAUD  = 9600                               ; Baudrate

; Berechnungen
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille

.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille 
Fehler
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit 
zu hoch!"
.endif

; RAM
.dseg
.org 0x60
Puffer: .byte 10

; hier geht das Programm los
.cseg
.org 0

    ldi     temp1, LOW(RAMEND)                  ; Stackpointer 
initialisieren
    out     SPL, temp1
    ldi     temp1, HIGH(RAMEND)
    out     SPH, temp1

;UART Initalisierung

    ldi     temp1, LOW(UBRR_VAL)                ; Baudrate einstellen
    out     UBRRL, temp1
    ldi     temp1, HIGH(UBRR_VAL)
    out     UBRRH, temp1

    sbi     UCSRB, TXEN                         ; TX einschalten

; ADC initialisieren: Single Conversion, Vorteiler 128
; Kanal 0, interne Referenzspannung AVCC

    ldi     temp1, (1<<REFS0)
    out     ADMUX, temp1
    ldi     temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
    out     ADCSRA, temp1

Hauptschleife:
    clr     temp1
    clr     temp2
    clr     temp3
    clr     temp4

    ldi     messungen, 0        ; 256 Schleifendurchläufe

; neuen ADC-Wert lesen  (Schleife - 256 mal)

adc_messung:
    sbi     ADCSRA, ADSC        ; den ADC starten

adc_warten:
    sbic    ADCSRA, ADSC        ; wenn der ADC fertig ist, wird dieses 
Bit gelöscht
    rjmp    adc_warten

; ADC einlesen:

    in      adlow, ADCL         ; immer zuerst LOW Byte lesen
    in      adhigh, ADCH        ; danach das mittlerweile gesperrte High 
Byte

; alle 256 ADC-Werte addieren
; dazu wird mit den Registern temp4, temp3 und temp2 ein
; 24-Bit breites Akkumulationsregister gebildet, in dem
; die 10 Bit Werte aus adhigh, adlow aufsummiert werden

    add     temp2, adlow        ; addieren
    adc     temp3, adhigh       ; addieren über Carry
    adc     temp4, temp1        ; addieren über Carry, temp1 enthält 0
    dec     messungen           ; Schleifenzähler MINUS 1
    brne    adc_messung         ; wenn noch keine 256 ADC Werte -> 
nächsten Wert einlesen

; Aus den 256 Werten den Mittelwert berechnen
; Bei 256 Werten ist das ganz einfach: Das niederwertigste Byte
; (im Register temp2) fällt einfach weg
;
; allerdings wird der Wert noch gerundet

    cpi     temp2,128           ; "Kommastelle" kleiner als 128 ?
    brlo    nicht_runden        ; ist kleiner ==> Sprung

; Aufrunden
    subi    temp3, low(-1)      ; addieren von 1
    sbci    temp4, high(-1)     ; addieren des Carry

nicht_runden:

;   Ergebnis nach adlow und adhigh kopieren
;   damit die temp Register frei werden

    mov     adlow, temp3
    mov     adhigh, temp4

; in Spannung umrechnen

    ldi     temp5,low(Faktor)
    ldi     temp6,high(Faktor)
    rcall   mul_16x16

;************** subtraktions-Test
subi temp1, (1)
sbci temp2, (0)
sbci temp3, (0)
sbci temp4, (0)

;**************

; in ASCII umwandeln

    ldi     XL, low(Puffer)
    ldi     XH, high(Puffer)
    rcall   Int_to_ASCII

;an UART Senden

    ldi     ZL, low(Puffer+3)
    ldi     ZH, high(Puffer+3)
    ldi     temp1, 1
    rcall   sende_zeichen       ; eine Vorkommastelle ausgeben

    ldi     zeichen, ','        ; Komma ausgeben
    rcall   sende_einzelzeichen

    ldi     temp1, 3            ; Drei Nachkommastellen ausgeben
    rcall   sende_zeichen

    ldi     zeichen, 'V'        ; Volt Zeichen ausgeben
    rcall   sende_einzelzeichen

    ldi     zeichen, 10         ; New Line Steuerzeichen
    rcall   sende_einzelzeichen

    ldi     zeichen, 13         ; Carrige Return Steuerzeichen
    rcall   sende_einzelzeichen

    rjmp    Hauptschleife

; Ende des Hauptprogramms

; Unterprogramme

 ; ein Zeichen per UART senden

sende_einzelzeichen:
    sbis    UCSRA,UDRE          ; Warten, bis UDR bereit ist ...
    rjmp    sende_einzelzeichen
    out     UDR, zeichen        ; und Zeichen ausgeben
    ret

; mehrere Zeichen ausgeben, welche durch Z adressiert werden
; Anzahl in temp1

sende_zeichen:
    sbis    UCSRA,UDRE          ; Warten, bis UDR bereit ist ...
    rjmp    sende_zeichen
    ld      zeichen, Z+         ; Zeichen laden
    out     UDR, zeichen        ; und Zeichen ausgeben
    dec     temp1
    brne    sende_zeichen
    ret

; 32 Bit Zahl in ASCII umwandeln
; Zahl liegt in temp1..4
; Ergebnis ist ein 10stelliger ASCII String, welcher im SRAM abgelegt 
wird
; Adressierung über X Pointer
; mehrfache Subtraktion wird als Ersatz für eine Division durchgeführt.

Int_to_ASCII:

    push    ZL                      ; Register sichern
    push    ZH
    push    temp5
    push    temp6

    ldi     ZL,low(Tabelle*2)       ; Zeiger auf Tabelle
    ldi     ZH,high(Tabelle*2)
    ldi     temp5, 10               ; Schleifenzähler

Int_to_ASCII_schleife:
    ldi     temp6, -1+'0'           ; Ziffernzähler zählt direkt im 
ASCII Code
    lpm     z0,Z+                   ; Nächste Zahl laden
    lpm     z1,Z+
    lpm     z2,Z+
    lpm     z3,Z+

Int_to_ASCII_ziffer:
    inc     temp6                   ; Ziffer erhöhen
    sub     temp1, z0               ; Zahl subrahieren
    sbc     temp2, z1               ; 32 Bit
    sbc     temp3, z2
    sbc     temp4, z3
    brge    Int_to_ASCII_ziffer     ; noch kein Unterlauf, nochmal

    add     temp1, z0               ; Unterlauf, eimal wieder addieren
    adc     temp2, z1               ; 32 Bit
    adc     temp3, z2
    adc     temp4, z3
    st      X+,temp6                ; Ziffer speichern
    dec     temp5
    brne    Int_to_ASCII_schleife   ; noch eine Ziffer?

    pop     temp6
    pop     temp5
    pop     ZH
    pop     ZL                      ; Register wieder herstellen
    ret

; Tabelle mit Zahlen für die Berechung der Ziffern
; 1 Milliarde bis 1
Tabelle:
.dd 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 
10, 1

; 16 Bit Wert in Spannung umrechnen
;
; = 16Bitx16Bit=32 Bit Multiplikation
; = vier 8x8 Bit Multiplikationen
;
; adlow/adhigh * temp5/temp6

mul_16x16:
    push    zeichen
    clr     temp1                   ; 32 Bit Akku löschen
    clr     temp2
    clr     temp3
    clr     temp4
    clr     zeichen                 ; Null, für Carry-Addition

    mul     adlow, temp5            ; erste Multiplikation
    add     temp1, r0               ; und akkumulieren
    adc     temp2, r1

    mul     adhigh, temp5           ; zweite Multiplikation
    add     temp2, r0               ; und gewichtet akkumlieren
    adc     temp3, r1

    mul     adlow, temp6            ; dritte Multiplikation
    add     temp2, r0               ; und gewichtet akkumlieren
    adc     temp3, r1
    adc     temp4, zeichen          ; carry addieren

    mul     adhigh, temp6           ; vierte Multiplikation
    add     temp3, r0               ; und gewichtet akkumlieren
    adc     temp4, r1

    pop     zeichen
    ret

Autor: Lymangood (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Simon K.
>Zusammen mit den Argumenten belegen beide Befehle (in allen möglichen
>Parametervarianten) nun mal 12,5 Prozent der möglichen 16 Bit.

Haha, tut mir leid aber ich kann dir echt nicht folgen. (roflmao)
(Wieviel Parametervarianten sind es denn nu?)

@Uhu Uhuhu
>Na ja, ich würde a den Mund nicht so voll nehmen. Instruktionssätze
>werden üblicherweise nicht mit irgend jemandem ausgehandelt, sondern an
>Hand von Statistiken über realen Code konstruiert. Als Randbedingung
>gehen Restriktionen durch Codewortbreite, vorhandene Hardwaremodule etc.
>pp. ein.
Ja, so sollte es eigentlich sein. Hat aber nur indirekt mit dem 
Fallbeispiel zu tun.

>Aber das sieht man als Feld-, Wald- und Wiesengroßmaul natürlich
>nicht...
Blanke Polemik. Auf das Beispiel selbst bist du nicht näher eingegangen, 
wozu auch.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Bei den ***** habe ich die Subtraktion mit hingeschrieben, da die Zahl
>nach der Multiplikation ja in temp1-4 abgelegt wird.

Und was soll da jetzt subtrahiert werden?

@anderen: Tauscht eure EMailadressen, und lasst die Sekundanten die Wahl 
der Waffen.
Kindergarten.

MfG Spess

Autor: 4Register (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ähm, naja 1. So dass bei 2V zum Beispiel 1V erscheint. Hab ich das 
falsch verstanden?

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Wenn ich das richtig gesehen habe, entspricht bei dir 1000 1V.
Dann sollte es so gehen:

subi temp1, Low(1000)
sbci temp2, byte2(1000)
sbci temp3, byte3(1000)
sbci temp4, byte4(1000)

Assembler2 benutzen!

MfG Spess

Autor: pillepalle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich kann da jetzt nicht mehr folgen ...
2-1=1 ja dann ? ?

Autor: 4register (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So habe das mal getestet! Super, danke Spess! Es waren zwar nicht 1000 
sondern 1.000.000 aber es scheint soweit zu klappen.

Nur kann es sein, dass das auch sonst irgendwas am Programm ändert, 
ausgenommen die Subtraktion?
Ich habe hier eine Spannung, die ich ändern kann. Und nun gibt es beim 
messen Sprünge auf 9,9V, wobei ich wegen der Referenz ja nur bis 5V 
messen kann.

und gibt es irgendeinen Befehl für ein optionales "-" Zeichen? Da ich, 
um bei dem 2V Beispiel zu bleiben, wenn ich nun 3 abziehe (+)1V erhalte. 
Oder müsste das per if-Konstruktion gemacht werden?




@pillepalle: also falls du damit meinst, dass du den Sinn meines 
Programmes nicht verstanden hast, es geht konkret darum den Offset eines 
elektr. Gerätes rauszuhauen und dafür bräuchte ich die Subtraktion

Autor: pillepalle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja ,aber warum machst du das nicht schon vorher bevor du den ADC Wert in 
eine Spannung umrechnest
also 5Volt ref/1023 = ca. 4,8mV  also zieh doch deinen Offset schon mal 
vom gebildeten mittelwert ab und fertig ....

Autor: pillepalle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
zu negativen Zahlen fällt mir jetzt nur Zweierkomplement zu ein
also bei 8 Bit zahlen wäre dann ein gesetztes Bit 7 der hinweis auf eine 
negative zahl

+125    01111101    7Dh
0   00000000   00h
-55   11001001   C9h

Autor: 4register (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>ja ,aber warum machst du das nicht schon vorher bevor du den ADC Wert in
>eine Spannung umrechnest
>also 5Volt ref/1023 = ca. 4,8mV  also zieh doch deinen Offset schon mal
>vom gebildeten mittelwert ab und fertig ....


Hm, das muesste doch aufs selbe raus kommen, oder?


Also ich hab das nun mal genauer getestet mit der Programmänderung und 
da geht dann später definitiv was schief... Also es zeigt nun zwar schön 
0V an, aber sobald sich die Spannung ändert ist die Spannungsänderung 
nach der Programmänderung anders als sie ohne der Programmänderung ist.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Einen Überlauf (->negative Zahl) erkennst du am gesetzten Carry-Flag 
nach der Subtraktion. Damit hast du dein 'Minus'. Um dein Ergebnis in 
einen positiven Wert (das was du als Wert nach dem 'Minus' ausgeben 
willst) umzurechnen, musst du Null-Ergebnis rechnen (entspricht 'neg' 
2er-Komplement).

MfG Spess

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.