Forum: Mikrocontroller und Digitale Elektronik 10 bit ADC wert verarbeiten


von Anton B. (pic16f887)


Lesenswert?

Hallo

ich habe folgendes Problem:

ich benutzte den ADC des PIC16F887. Dieser ADC hat eine Auflösung von 10 
bit und speichert diese 10bit im Register ADRESH und ADRESL.
Nun möchte mit diesen 10bit rechnen. Nur wie mache ich das ?
Ich habe doch nur 8 bit breite Register.

Angenommen es kommen aus dem ADC der Wert d'614' (b'1001100110')
Dieser wert wird in ADRESH und ADRESL abgelegt.

bit 0 - 7 befindet sich in ADRESL und bit 8-9 befinden sich in ADRESH.

Nun hab ich ja im Register ADRESL den Decimalwert 102 und im Register 
ADRESH den decimalwert 2
2+102= 104
Das geht logischer weise nicht!

Kann man evt 2 register zusammenfügen sodass ich ein 16 bit breites 
Register habe? dann wäre das rechnen kein problem mehr.

Oder wie verwertet man 10 bit werte mit 8 bit breiten registern?

von Chris B. (dekatz)


Lesenswert?

Wenn ein 8-Bit Register überläuft dann hat der entstehende Übertrag 
einen Wert von 256. In ADRESH steht die Anzahl der "Überläufe" von 
ADRESL...also:
ADCwert = (ADRESH * 256) + ADRESL

: Bearbeitet durch User
von Anton B. (pic16f887)


Lesenswert?

Chris B. schrieb:
> Wenn ein 8-Bit Register überläuft dann hat der entstehende Übertrag
> einen Wert von 256. In ADRESH steht die Anzahl der "Überläufe" von
> ADRESL...also:
> ADCwert = (ADRESH * 256) + ADRESL

Okay das hab ich verstanden. Aber wenn ich die werte aus ADRESH und 
ADRESL in ein anderes Register schiebe. Zum Beispiel in 0x20 und 0x21 
funktioniert das genauso?

von Gerald G. (gerald_g)


Lesenswert?

Welchen Compiler nimmst du denn?
Bei vielen kann man dann einfach einer 16bit variable den wert "ADRES" 
zuweisen ( ohne H oder L am Ende)
Der Compiler macht das dann richtig

von Anton B. (pic16f887)


Lesenswert?

Gerald G. schrieb:
> Welchen Compiler nimmst du denn?
Naja MPLAB (oder was ist gemeint?)
> Bei vielen kann man dann einfach einer 16bit variable den wert "ADRES"
> zuweisen ( ohne H oder L am Ende)
> Der Compiler macht das dann richtig
Wie soll ich das verstehen? Besteht das Register aus aus 2 Registern?

von Ingo (Gast)


Lesenswert?

Ich tippe auf asm, in C stellt sich solch eine Frage fast nicht

von Anton B. (pic16f887)


Lesenswert?

Ingo schrieb:
> Ich tippe auf asm, in C stellt sich solch eine Frage fast nicht

Ne, ich nutze das Programm MPLAB und schreibe in Assembler.

von Ingo (Gast)


Lesenswert?

Achso, dann is gut!

von Ingo (Gast)


Lesenswert?

Dachte schon du tust dir asm wirklich an

von Anton B. (pic16f887)


Lesenswert?

Ich möchte gerne den wert 614 aus dem ADC mit 0,4883 multiplizieren. Die 
614 befinden sich in ADRESH und ADRESL.
Kann mir jemand da ein beispiel geben?

von Anton B. (pic16f887)


Lesenswert?

Ingo schrieb:
> Dachte schon du tust dir asm wirklich an

ASM kenn ich gar nicht mal :D

von Chris B. (dekatz)


Lesenswert?

Anton B. schrieb:
> Chris B. schrieb:
>
> Okay das hab ich verstanden. Aber wenn ich die werte aus ADRESH und
> ADRESL in ein anderes Register schiebe. Zum Beispiel in 0x20 und 0x21
> funktioniert das genauso?

Das obige Beispiel macht nur in einer Hochsprache Sinn.

Um den 8 + 2 Bit ADC-Wert in Assembler weiterzuverarbeiten und z.B. eine 
Spannung auf einem LCD anzuzeigen, bedarf es noch einiges an Aufwand 
(Umwandlung in eine (gepackte) BCD-Zahl und dann weiter in einen String 
und und...)

von Ingo (Gast)


Lesenswert?

>Das obige Beispiel macht nur in >einer Hochsprache Sinn.
c-hater fass!!!

von Chris B. (dekatz)


Lesenswert?

Ingo schrieb:
>>Das obige Beispiel macht nur in >einer Hochsprache Sinn.
> c-hater fass!!!

Die heutigen Assembler sind ja auch schon so neumodisches 
Klicki-Bunti-Zeugs.
Wenn schon, dann gleich ordentlich: Handassemblierung auf toten Holz mit 
Graphitstift und Debugging mit Naturkautschuk. :-D

von Ingo (Gast)


Lesenswert?

wir sollten die Dinger wieder abschaffen, Früher war eh alles bisser...

Wenn ich so manche Kollegen sehe, kurz vor der Rente, keinen Durchblick 
mehr was stand der Technik ist, aber große Sprüche klopfen. Aber Hand am 
Ohr...

Hört doch bitte mit diesem steinzeitmäßigem Verhalten auf! Heut zu Tage 
verfügt jeder PC, der nicht älter als 10 Jahre ist, um genug rechenpower 
um alle Tools zu stemmen...

von Anton B. (pic16f887)


Lesenswert?

Chris B. schrieb:
> Anton B. schrieb:
>> Chris B. schrieb:
>>
>> Okay das hab ich verstanden. Aber wenn ich die werte aus ADRESH und
>> ADRESL in ein anderes Register schiebe. Zum Beispiel in 0x20 und 0x21
>> funktioniert das genauso?
>
> Das obige Beispiel macht nur in einer Hochsprache Sinn.
>
> Um den 8 + 2 Bit ADC-Wert in Assembler weiterzuverarbeiten und z.B. eine
> Spannung auf einem LCD anzuzeigen, bedarf es noch einiges an Aufwand
> (Umwandlung in eine (gepackte) BCD-Zahl und dann weiter in einen String
> und und...)

Alles klar. Das ist mir für mein erstes Projekt zu anstrengend. Da ich 
eh ein Temperatursensor benutze, der 10mv/k seine Ausgangsspannung 
ändert reicht auch eine Auflösung von 8 Bit. Muss ich ja nur umstellen.

von Anton B. (pic16f887)


Lesenswert?

Anton B. schrieb:
> Chris B. schrieb:
>> Anton B. schrieb:
>>> Chris B. schrieb:
>>>
>>> Okay das hab ich verstanden. Aber wenn ich die werte aus ADRESH und
>>> ADRESL in ein anderes Register schiebe. Zum Beispiel in 0x20 und 0x21
>>> funktioniert das genauso?
>>
>> Das obige Beispiel macht nur in einer Hochsprache Sinn.
>>
>> Um den 8 + 2 Bit ADC-Wert in Assembler weiterzuverarbeiten und z.B. eine
>> Spannung auf einem LCD anzuzeigen, bedarf es noch einiges an Aufwand
>> (Umwandlung in eine (gepackte) BCD-Zahl und dann weiter in einen String
>> und und...)
>
> Alles klar. Das ist mir für mein erstes Projekt zu anstrengend. Da ich
> eh ein Temperatursensor benutze, der 10mv/k seine Ausgangsspannung
> ändert reicht auch eine Auflösung von 8 Bit. Muss ich ja nur umstellen.

Hallo nochmal,
Ich suche schon seit tagen nach einer Lösung wie ich den ADC sagen kann 
das er mir nur 8 bit rausgeben soll statt 10 bit.
Habt ihr eine lösung?

von Justus S. (jussa)


Lesenswert?

Anton B. schrieb:
> Ich suche schon seit tagen nach einer Lösung

dann solltest du einfach mal ins Datenblatt schauen...

von Anton B. (pic16f887)


Lesenswert?

Justus Skorps schrieb:
> Anton B. schrieb:
>> Ich suche schon seit tagen nach einer Lösung
>
> dann solltest du einfach mal ins Datenblatt schauen...

Das hab ich schon 3 mal durchgelesen... steht nichts drin

von Dietrich L. (dietrichl)


Lesenswert?

Anton B. schrieb:
> Ich suche schon seit tagen nach einer Lösung wie ich den ADC sagen kann
> das er mir nur 8 bit rausgeben soll statt 10 bit.

Kleine Hilfe: er erzeugt nicht wirklich nur 8 Bit. Die Frage ist eher, 
wo die Bits in den Registern stehen und welchen Teil Du bei der 
Weiterverarbeitung ignorierst.

Gruß Dietrich

von Justus S. (jussa)


Lesenswert?

Anton B. schrieb:
> steht nichts drin

doch tut es, nennt sich ADFM-Bit...

von Anton B. (pic16f887)


Lesenswert?

Dietrich L. schrieb:
> Anton B. schrieb:
>> Ich suche schon seit tagen nach einer Lösung wie ich den ADC sagen kann
>> das er mir nur 8 bit rausgeben soll statt 10 bit.
>
> Kleine Hilfe: er erzeugt nicht wirklich nur 8 Bit. Die Frage ist eher,
> wo die Bits in den Registern stehen und welchen Teil Du bei der
> Weiterverarbeitung ignorierst.
>
> Gruß Dietrich

achso..... Jetzt machts klick! Danke ;)

von c-hater (Gast)


Lesenswert?

Anton B. schrieb:

> Ne, ich nutze das Programm MPLAB und schreibe in Assembler.

Dann solltest du dringend lernen, wie man in Assembler breitere 
Datentypen realisiert.

Speichern ist einfach, da nimmt man für 16Bit einfach zwei Bytes. Aber 
schon bei so simplen Sachen wie dem Addieren oder Subtrahieren wird's 
komplizierter, da muß man Übertrage zwischen den Bytes mitnehmen.

Wenn du keinen Bock darauf hast, das zu lernen, nimm eine Hochsprache. 
Also alles, bloß nicht C. Das ist keine wirkliche Hochsprache. Du mußt 
fast genausoviel über den Schmutz in den Tiefen der Maschine wissen, als 
wenn du in Asm programmierst, hast aber längst nicht alle Freiheiten von 
Asm.

C ist Dreck.

von Ingo (Gast)


Lesenswert?

@c-hater
Immer wieder köstlich deine Argumentation... Was empfiehlst du denn als 
waschechte Hochsprache für einen kleinen AVR mit 1k Flash?

von Bastler (Gast)


Lesenswert?

Anton B. schrieb:
> Ich möchte gerne den wert 614 aus dem ADC mit 0,4883 multiplizieren. Die
> 614 befinden sich in ADRESH und ADRESL.
> Kann mir jemand da ein beispiel geben?

http://www.avr-projekte.de/rechnen.htm#Rechnen_mit_Festkomma_

Das Programmbeispiel ist zwar für AVR, trifft aber genau auf dein 
Problem zu.

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Ingo schrieb:
> Was empfiehlst du denn als waschechte Hochsprache für einen kleinen
> AVR mit 1k Flash?

OOASM ;-)

von c-hater (Gast)


Lesenswert?

Ingo schrieb:

> Immer wieder köstlich deine Argumentation... Was empfiehlst du denn als
> waschechte Hochsprache für einen kleinen AVR mit 1k Flash?

Keine. Alles unterhalb 8k (Code+konstante Daten) macht man natürlich 
immer in Assembler, ohne auch nur ansatzweise über eine Alternative 
nachzudenken.

Im Bereich 16..64k wird man sinnvollerweise darüber nachdenken. Und 
manchmal entscheide sogar ich mich hier für C, auch wenn ich es hasse 
wie die Pest.

Oberhalb von 64k braucht man wieder nicht mehr nachdenken, da ist 
Hochsprache (maximal mit Asm-Einschüben für zeitkritischen Kram) 
angesagt. Und dann natürlich eine richtige objektorientierte 
Hochsprache. Notfalls sogar C++, auch wenn ich das fast genauso hasse 
wie C. Da hängt viel zuviel C-Schmutz im Sprachkonzept...

von Bernie (Gast)


Lesenswert?

Hier kann wohl keiner was!
Besonders die klugsch... Sprachen-Schwafler!

Eigentlich voll easy in ASM:
(Leider kenne ich nur die AVR-Konventionen, beim PIC
wird es aber nicht viel anders sein.)

ADRESH und ADRESL in zwei Arbeitsregister kopieren,
für die Multiplikation 0,4883 * 65536 = 32001 = 0x07D1
in zwei weitere Arbeitsregister laden.

16 * 16 Bit unsigned Multiplikationsroutine mit diesen
Registern ausführen. (Findet man bestimmt auf
intelligenteren Sites, für AVR wird man bei
 http://elm-chan.org/cc_e.html  fündig.)

Vom 4 Byte Resultat sind die 2 oberen Byte das Ergebnis.
(Mit dem Verwerfen der unteren 2 Byte kürzt sich die
Erweiterung um 65536 wieder raus.)

Kriegt man das mit einem PIC nicht hin???

von Anton B. (pic16f887)


Lesenswert?

Hallo


Ich habe es nach langerzeit nun hinbekommen Zahlen größer 8 bit zu 
multiplizieren. Nun stellt sich ein weiteres Problem ein. Da ich meine 
Zahl (616) gern mit 61 multiplizieren möchte, habe ich zuerst die Zahl 
mal 64 genommen ( 6 mal * 2) [Ergebniss=39424]. Nun muss ich diese Zahl 
3 mal minus 616 nehmen um auf das richtige ergebniss [37576] zu kommen.
Kennt ihr eine Lösung oder ein Link wo ich das nachschauen kann, wie ich 
Zahlen größer 8 bit Subtrahiere?

von Karl H. (kbuchegg)


Lesenswert?

Anton B. schrieb:
> Hallo
>
>
> Ich habe es nach langerzeit nun hinbekommen Zahlen größer 8 bit zu
> multiplizieren.


Um ehrlich zu sein bezweifle ich das, wenn ich den Rest deines Postings 
betrachte. Was du rausgefunden hast ist, dass ein Linksverschieben um 1 
Bit einer Multiplkation mit 2 entspricht und demenstprechend ein 
mehrmaliges Schieben einer Multiplikation mit einer entsprechenden 2-er 
Potenz (2, 4, 8, 16, etc.).
Das ist aber von tatsächlicem Multiplizieren weit entfernt.

Man kann diese Schiebe-Strategie verfolgen, durchaus. Aber wenn man 
tatsächlich Multiplizeren kann, dann bleibt es nicht aus, auch die 
einfache Aufgabe 'Addition/Subtraktion von 16 Bit Zahlen in 2 Registern' 
lösen zu können. Die Aufagbe ist deswegen einfach, weil die Prozessoren 
dafür eigene Instruktionen haben, die einen möglichen Übertrag von einer 
Operation in die nächste berücksichtigen können.

> Kennt ihr eine Lösung oder ein Link wo ich das nachschauen kann, wie ich
> Zahlen größer 8 bit Subtrahiere?

Dein µC hat Instruktionen zum Addieren bzw. Subtrahieren.
Die gibt es in der Version mit bzw. ohne Berücksichtigung des Carry 
Flags.
Ein Blick in die Tabelle der vom µC unterstützen OPerationen bzw. 
Nachlesen wie sie funktionieren hilft da ungemein. Und ja. Das steht 
alles im Datenblatt des Prozessors bzw. in einem Dokument welches den 
'Instruction Set' beschreibt. Gewöhn dich daran, dass du Unterlagen 
studieren musst, das wirst du noch oft und nach lange tun müssen.

Das Carry Flag ist nichts anders als der Übertrag bzw. Unterlauf, den du 
auch so machst. Wenn du addierst, dann kann dein "Hardware-Addierer" 
(genannt Brain) das nur im Zahlenbereich 0 bis 9 tun. Willst du 
2-stellige Zahlen addieren
1
    24
2
    28
3
  -----

dann rechnest du
1
  8 plus 3 ergibt 12
die 2 schreibst du beim Ergebnis hin, die 1 (von den Zehnern) merkst du 
dir und rechnest ihn bei der restlichen Addition noch mit dazu
1
   24
2
   28
3
   1
4
  ----
5
    2
1 plus 2 plus 2 macht 5
1
   24
2
   28
3
   1
4
  ----
5
   52

Die Rolle die hier das 'die 1 merkst du dir' spielt, genau diese Rolle 
spielt im µC das sog. Carry Flag. UNd folgerichtig gibt es auch 2 
Additionen, einmal ohne Einrechnung das Carry Flags (das hast du bei den 
Einern gebraucht) und einmal mit Einrechnung des Carry Flags (die 
Operation hast du bei den Zehnern gebraucht).

Nicht anders funktioniert das, wenn du eine 16 Bit Zahl in 2 Registern 
addierst. Die 'kleinen Stellen' addierst du ohne Einrechnung des Carry, 
die 'grossen Stellen' addierst du mit der Operation, die auch das Carry 
Flag (welches von der vorhergehenden Operation je nachdem auf 0 oder 1 
gesetzt wurde) berücksichtig.

Und nicht anders funktioniert das bei der Subtraktion.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

In einem Punkt muss ich mich korrigieren:

Der PIC hat anscheinend keine 2 verschiedenen Additionsbefehle

http://www.sprut.de/electronic/pic/assemble/befehle.html

d.h. das Carry Flag wird nicht automatisch mit eingerechnet, weil es 
keinen Befehl dafür gibt. Statt dessen muss man sich selbst darum 
kümmern.

http://www.sprut.de/electronic/pic/math/math.htm

: Bearbeitet durch User
von Chris B. (dekatz)


Lesenswert?

Anton B. schrieb:
> Hallo
>
> Kennt ihr eine Lösung oder ein Link wo ich das nachschauen kann, wie ich
> Zahlen größer 8 bit Subtrahiere?

Google mal nach AN617 von MICROCHIP (Fixed Point Arithmetik)
Dort finden sich nicht nur eine Routine für simple 16 Bit 
Addition/Subtraktion sondern gleich eine ganze Bibliothek für 8x8, 8x16, 
16x16, 24x16, 24x24, 32x16, 32x24 udn 32x32 Multiplikation (jeweils 
signed/unsigned) und das alles in die Gegenrichtung - sprich Division.
(den ganzen Source gibt es auch als ZIP-File!)

Man muss sich natürlich in die verwendtet Datenstruktur der Parameter 
einarbeiten, aber der Zeitaufwand lohnt falls man wirklich in Assembler 
aufwändigere Berechnungen in FP-Arithmetik machen will.

btw: die Addition und Subtraktion findet sich ja zum Glück gleich auf 
Seite 2 oder 3..... ;-)

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
Noch kein Account? Hier anmelden.