Hallo,
ich habe mir das Tutorial über den Analog bzw. Digitalkonverter
durchgelesen.
Leider ist das Beispiel mit dem Quelltext nicht nur auf den
Analog/Digitalkonverter beschränkt, sondern beeinhaltet noch die UART
Schnittstelle und die Mittelwertbildung, sodass das eigentliche
Augenmerk nicht nur auf dem AD Konverter liegt.
Deswegen ist mir leider nicht ersichtlich, wie genau man nun eine analog
anliegende Spanung als Wert in einem Register speichern kann.
Könntet ihr mir das erklären?
Jochen
Moin,
hatte das gleiche Problem. Am besten liest du im Datenblatt nach was die
Bits machenund setzt die nacheinenader entsprechend. Habe leider die
Dateien nicht hier, sonst könnte ich das geanuer sagen, aber es gibt ein
Bit, das den ADC startet und ein anderes, das gesetzt wird wenn er
fertig ist (oder ist es sogar das gleiche?) Danach steht das Ergebnis in
den Ergebnisregistern(Ich glaube ADCH und ADCL). Die kannst du auslesen,
musst aber auf die Reihenfolge warten, weil sonst das Register, das du
noch nicht auisgelesen hast überschrieben werden kann (im
Free-Runnning-Mode).
Frag, wenn das zu ungenau war ;)
Dussel
Das ist der wsentliche Teil aus dem tutorial-Programm:
; neuen ADC-Wert lesen (Schleife - 256 mal)
sample_adc:
sbi ADCSRA, ADSC ; den ADC starten
wait_adc:
sbic ADCSRA, ADSC ; wenn der ADC fertig ist, wird dieses Bit
gelöscht
rjmp wait_adc
; ADC einlesen:
in adlow, ADCL ; immer zuerst LOW Byte lesen
in adhigh, ADCH ; danach das mittlerweile gesperrte High
Byte
Bei sowas lese ich im Datenblatt eigentlich immer nur, was die einzelnen
Bits machen, den Rest, was die Batueile alles können und wie die
funktionieren braucht man eigentlich aös Anfänger nicht. Das macht schon
vieles einfacher. Englisch musst du natürlich ein bnisschen verstehen.
Das Beispiel oben zeigt eigentlich alles was du wissen musst.
Dussel
Zitat aus dem Tutorial:
> Die Ergebnisregister ADCL und ADCH> Immer zuerst ADCL und erst dann ADCH auslesen. Beim Zugriff auf> ADCL wird das ADCH Register gegenüber Veränderungen vom ADC> gesperrt. Erst beim nächsten Auslesen des ADCH-Registers wird> diese Sperre wieder aufgehoben.> Dadurch ist sichergestellt, daß die Inhalte von ADCL und ADCH immer> aus demselben Wandlungsergebnis stammen, selbst wenn der ADC im> Hintergrund selbsttätig weiterwandelt.
Ich denke, Du hast es gründlich gelesen?
Ja hab ich auch.
Aber das hab ich nicht ganz verstanden.
Eine weitere Frage:
An welchem Port leg ich die Spannung denn genau an, und wie bekomm ich
den Wert nun in ein Register, mit dem ich weiterarbeiten kann?
> An welchem Port leg ich die Spannung denn genau an
Steht im Tutorial:
http://www.mikrocontroller.net/articles/AVR-Tutorial:_ADC#Beschaltung_des_ADC-Kanaleingangs> wie bekomm ich
den Wert nun in ein Register, mit dem ich weiterarbeiten kann?
Siehe Programmbeispiel oben bei "; ADC einlesen".
adlow und adhigh sind dabei im Beispielprogramm wie folgt definiert:
.def adlow = r20
.def adhigh = r21
Ich habe es jetzt ausprobiert und mit dem Auszug von "Gast" getestet.
An Pin C0 habe ich 5 V angelegt.
Port B habe ich als Ausgang konfiguriert und da einen 7 Seg. Treiber
dran und an 7 Segmentanzeigen. Das, was an Port B binär anliegt ist
dezimal sichtbar.
Ich habe also an Pin C0 eine Spannung anliegen.
Am Ende des Quellcodes von "Gast" sende ich noch adhigh an Port B und
somit an die 7 Segmmentanzeige, die aber leider keine Änderung anzeigt.
Mein Programm sieht in etwa so aus:
; neuen ADC-Wert lesen (Schleife - 256 mal)
sample_adc:
sbi ADCSRA, ADSC ; den ADC starten
wait_adc:
sbic ADCSRA, ADSC ; wenn der ADC fertig ist, wird dieses Bit
gelöscht
rjmp wait_adc
; ADC einlesen:
in adlow, ADCL ; immer zuerst LOW Byte lesen
in adhigh, ADCH ; danach das mittlerweile gesperrte High
Byte
out PortB, adhigh
Natürlich habe ich vorher PortB als Ausgang konfiguriert.
Warum zeigt die Anzeige nichts an?
> Mein Programm sieht in etwa so aus:
'In etwa so' ist immer schlecht.
Der Teufel steckt im Detail und kann auch ganz woanders
zu finden sein.
Soo gross wird dein Programm ja nicht sein. Poste es komplett
und wenn es tatsächlich mehr als sagen wir mal 50 Zeilen hat,
dann specke vorher ab, bis nur noch die relevanten Dinge
übrig bleiben, du in etwa in diesem Zeielenbereich bist und
(ganz wichtig) das Programm das Fehlverhalten immer noch
zeigt.
Denk immer drann: Es gibt nichts besseres zur Fehlersuche
als wenn hier jedermann in der Lage ist, dein Programm
in einen Prozessor zu brennen und mal laufen zu lassen.
Das muss dein Ziel sein.
Hi, hier ist der Quellcode.
Wie gesagt an Port B sollten dann die Zahlen binär anliegen aber meine
Segmentanzeige zeigt nur "0" an. AREF habe ich mit einem 100 N
Kondensator auf Masse und testweise auch mal an 5V (Versorgungsspannung)
angeschlossen. In beiden Fällen das gleiche Ergebnis...
.include "m8def.inc"
.def temp = r16
.def temp1=r17
.def adlow =r20
.def adhigh=r21
.org 0x0000
rjmp main
ldi temp1,(1<<REFS0)
out ADMUX, temp1
ldi temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1)| (1<<ADPS0)
out ADCSRA, temp1
main:
ldi temp, LOW(RAMEND) ;Stackpointer initalisieren
out SPL, temp
ldi temp, HIGH(RAMEnD)
out SPH, temp
sbi DDRB,0
sbi ddrB,1
sbi ddrB,2
sbi ddrB,3
ldi r22, 9
sample_adc:
sbi ADCSRA, ADSC
wait_adc:
sbic ADCSRA, ADSC
rjmp wait_adc
in adlow,ADCL
in adhigh, ADCH
loop:
out PORTB, adhigh
rjmp loop
rjmp loop
muß
rjmp sample_adc
heißen, wenn Du ständig und nicht nur ein einziges Mal wandeln möchtest.
Außerdem muß zuerst SPH, dann SPL geschrieben werden.
Danke!
Mit dieser Änderung habe ich erreicht, dass manchmal etwas angezeigt
wird. Es ist aber eine wacklige Sache, manchmal wird auch einfach nur
die Null ausgegeben. Habe ich möglicherweise einen Widerstand vergessen?
Was ist mit AREF? Reicht es diesen Eingang mit einem 100N Kondensator zu
verbinden, der auch noch an der Masse angeschlossen ist?
Nichts desto troz bekomme ich, wenn ich Pin C0 auf 5 V liege an der
Segmentanzeige die Zahl 3 ausgegeben.
Mit der Formel erhalte ich jetzt
3*5V / 1024 = 0,014 V.
Ich habe aber 5 V angelegt.
Hallo,
3 ist doch richtig...
Du gibst das H-Byte aus, der maximal mögliche Wandlerwert bei Uin >=
Uref ist 0x3FF, H-Byte also 3.
Gruß aus Berlin
Michael
Ich komme leider immer noch nicht auf die 5 V:
(ADChigh * 256) + ADClow = Ergebnis
ADChigh = 3
ADClow = 0 (0 wird ausgegeben, wenn ich low ausgebe)
(3 * 256) + 0 = 768 (ungleich 5)
Tut mir leid, wenn ich noch mal nachfragen muss.
Was meinst DU mit der Betriebsart 'left-adjusted'? Was bewirtkt sie? Wo
muss ich das eingeben?
Das wird im Register ADMUX eingestellt (Datenblatt seite 206 und 208).
das Bit 5 heißt ADLAR und schiebt die Bits einfach nach links bis zum
Bit 7 des ADCH.
Am Besten mal das Datenblatt studieren! ;)
und was könnte ich damit erreichen ? Wie bekomme ich hin, dass die 5
angezeigt wird?
Wie komme ich rechnerisch von der 3 auf die 5? Die Formel funktioniert
bei mir ja nicht (s.o)
Also:
1. ADCL auslesen und zwischenspeichern
2. ADCH auslesen und mit 256 multiplizieren
3. ADCL und multipliziertes Ergebnis von ADCH addieren
4. Berechnung durchführen: (5 / 1023)*Summe Messwert = Spannung
^^^^
NICHT 1024 ! Es wird ab 0 gezählt, also 0..1023 => 1024 Schritte.
Hi
@power: AVRs haben 8-Bit Register. Statt mit 256 zu multiplizieren
reicht es ADCL und ADCH in zwei Register einzulesen. Mit der Berechnung
ist Jochen mit Sicherheit überfordert.
Einfacher wäre es die Eingangsspannung (bei 5V) auf 3,125V zu teilen.
Dann ergibt sich ein ADC-Wert von 640D ( 5*128). Dann 7 mal
Rechtsschieben. Ergebnis: 5.
MfG Spess
Power wrote:
> Also:> 1. ADCL auslesen und zwischenspeichern> 2. ADCH auslesen und mit 256 multiplizieren> 3. ADCL und multipliziertes Ergebnis von ADCH addieren> 4. Berechnung durchführen: (5 / 1023)*Summe Messwert = Spannung> ^^^^> NICHT 1024 ! Es wird ab 0 gezählt, also 0..1023 => 1024 Schritte.
Mensch, Power, das ist doch hier schon zigmal durchdiskutiert worden:
Die Formel für das Wandlungsergebnis lautet
woraus nach Umstellung folgt
Noch mal zur Verdeutlichung: Die Referenzspannung wird in 1024 Schritte
unterteilt. Der höchste Messwert ist 1023 (die höchste in 10 Bit
darstellbare Zahl). Die höchste messbare Spannung ist demnach
wobei das allerdings nur die letzte Digitalisierungsstufe darstellt und
demzufolge nur bedeutet, dass alle Spannungen, die größer als V_REF - 1
LSB sind, zum Ergebnis 1023 führen.
Das nur am Rande, um Missverständnisse zu vermeiden. Für die Berechnung
an sich ist es zunächst mal unerheblich, da der Fehler nur bei ca. 1
Promill liegt...
Ich denke, mein Fehler lag daran, dass ich ADCL an Port B ausgegeben
habe, an dem der Dekoder und die Segmentanzeige war, 255 kann so ja
schlecht dargestellt werden.
Wie ist denn der Assemblerbefehl für eine Division?
jochen wrote:
> Wie ist denn der Assemblerbefehl für eine Division?
Die AVRs haben keinen Hardware-Divider, weshalb es auch keinen
Divisions-Befehl gibt. Eine Division muss im AVR durch Algorithmen aus
anderen Operationen zusammengesetzt werden. Schau mal hier in der
Codesammlung und/oder auf der ATMEL-Homepage, da gibts eine Application
Note mit Divisionsalgorithmen in Assembler.
Ergänzung:
Eine Division durch 2^n lässt sich durch Bit-Schiebeoperationen
durchführen (Division durch 2^n entspricht einem Rechtsschieben um n
Bit). Aber ich denke, Du brauchst eher etwas zur Umrechnung der
Hex-Werte in Dezimalzahlen, also eine Division durch 10, gelle? Ich
denke, auch dazu dürfte es in der Codesammlung etwas geben (Hex nach BCD
o.ä.)
@ Johannes M.:
(sorry für den neuen Nick, hab' endlich Zeit gefunden mich anzumelden
;))
(5/1023) * 1023 = 5
und
(5/1023) * 0 = 0
oder?
Also decke ich somit den tatsäclichen Bereich ab.
Nachgemessenermaßen (mit Kalibrierquelle) ist das auch so.
Ahja dann hab ich noch eine Frage und zwar zu dem Wackelkontakt von
oben:
Die Bauteile sind alle fest auf den Steckbrett also ein mechanischer
Fehelr wird es kaum sein.
Es wird meistens eine 0 angezeigt, nur mit Glück und nach ein paar
Versuchen schaffe ich es, dass die 3 auf der Segmentanzeige steht.
AREF habe ich mit einem 100 N Kondensator gegen Masse und sonst VXX auf
Plus und GND auf Minus und auch ein 100 N dazwischen.
Thilo M. wrote:
> @ Johannes M.:> (sorry für den neuen Nick, hab' endlich Zeit gefunden mich anzumelden> ;))
Na, so lange dauert das aber auch nicht...;-)
> (5/1023) * 1023 = 5> und> (5/1023) * 0 = 0> oder?
Nö, eben nicht! Am besten schauste Dir mal eine Beschreibung der
Funktion des Successive Approximation Converters an (konkrete Quelle im
Netz hab ich grad nicht parat, sollte aber mit "Ole Friend" Google o.ä.
zu finden sein). Da steht erstens die korrekte Formel (mit 1024!) und
außerdem, warum das so ist (das gehört imho nicht hierher, zumal es wie
gesagt hier schon einige Threads zu dem Thema gab, in denen der ADC
quasi totdiskutiert wurde).
> Also decke ich somit den tatsäclichen Bereich ab.> Nachgemessenermaßen (mit Kalibrierquelle) ist das auch so.
Wer viel misst, misst viel Mist... Im Ernst: Ein SAR-Wandler kann
nicht VREF wandeln. Gründe siehe voriger Absatz. Dass bei der Messung
eine (scheinbare) Übereinstimmung herauskommt, liegt erstens an der
Auflösung (1 LSB ist bei VREF = 5 V grad mal bei knapp 50 mV) und an der
Digitalisierung (siehe mein vorletztes Posting). Und ja: Bei VREF = 5 V
und VIN = 5 V kriegst Du (aus o.g. Gründen) selbstverständlich den
Maximalwert raus! Aber eben (bei gleichem VREF) auch bei VIN = 4,951 V
(VREF - 1LSB). Alles, was größer ist, als VREF-1LSB gibt 1023...
EDIT: Die Formel steht übrigens auch in den Datenblättern der
betreffenden AVRs. OK, in den ATMEL-Datenblättern sind auch von Zeit zu
Zeit ein paar Fehlerchen drin, aber in dem Fall lügt das Datenblatt mal
nicht...
OK, will nicht weiter diskutieren. Tatsache ist, wenn ich 5V anlege will
ich auch 5.000V sehen, nicht etwas kleineres. Dass die Schrittweite
nicht 4.883mV sondern 4.888mV ist stört wohl niemanden! Der Endanschlag
sollte jedoch 5.000 zeigen, nicht 4.995.
jochen wrote:
> Können in einem Register eigentlich auch Bruchzahlen stehen also z.B.> 4,2> oder sogar irrationale Zahlen?
Wie man die 8 Bit in einem Register interpretiert, ist weitgehend Sache
des Anwenders. Es steht Dir frei, Register für Deine Interpretation
aufzuteilen. Allerdings besitzen die AVRs mit Hardware-Multiplier
tatsächlich Multiplikations-Befehle (fmul..., fractional multiply), die
auf eben einer solchen Aufteilung des Register-Inhalts in Vor- und
Nachkommateil basieren.
Thilo M. wrote:
> OK, will nicht weiter diskutieren. Tatsache ist, wenn ich 5V anlege will> ich auch 5.000V sehen, nicht etwas kleineres. Dass die Schrittweite> nicht 4.883mV sondern 4.888mV ist stört wohl niemanden! Der Endanschlag> sollte jedoch 5.000 zeigen, nicht 4.995.
Du kannst (wie schon gesagt) bei der sukzessiven Approximation keine
VREF messen. Das ist Fakt. (<- Punkt!)
jochen wrote:
> Können in einem Register eigentlich auch Bruchzahlen stehen also z.B.> 4,2> oder sogar irrationale Zahlen?
Siehe Johannes oben für eine generelle Antwort. Der ADC hingegen spuckt
in seinen Registern eine einfache natürliche Zahl aus, die umgerechnet
werden kann. (Siehe Datenblatt...)
Das habe ich noch nicht ganz verstanden.
Ich verdeutliche das Problem anhand von Johannes Formel.
Wenn ich diese Formel anwende bekomme ich
1023*5 / 1024 = 4,9(95117188)
stimmt das soweit?
Wie würde diese Zahl denn jetzt konkret in einem Register aussehen?
würde das in etwa so sein:
100,1001
4,9
@jochen: Nein, warum würdest du denn sonst eine Formel brauchen? Das
macht doch null Sinn!
Du hast doch selbst ein Beispiel gegeben:
jochen wrote:
> 1023*5 / 1024 = 4,9(95117188)
1023 ist der Wert, den du aus den Beiden Registern gelesen hast. 5 ist
die Referenzspannung in Volt und 4,9.... ist das Ergebnis in Volt. Das
ist die Spannung, die am ADC-Pin anliegt.
Das ist mir schon klar. Die Frage ist was passiert, wenn bei einem
Rechenschritt mal keine ganzen Zahlen auftreten.
z.B.
ldi r4,5
ldi r6,8
wenn ich jetzt
r4 / r6 rechne (über andere Operationen) und das Ergebnis z.B. in r8
speicher, hat r8 ja den Wert 0,625
wie sähe aber der Inhalt des Registers nun wirklich aus ? (binär)
jochen wrote:
> z.B.>> ldi r4,5> ldi r6,8>> wenn ich jetzt> r4 / r6 rechne (über andere Operationen) und das Ergebnis z.B. in r8> speicher, hat r8 ja den Wert 0,625>> wie sähe aber der Inhalt des Registers nun wirklich aus ? (binär)
Kommt drauf an. Wenn du C benutzt und einen float datentyp nimmst, wird
die Zahl als Fließkommazahl dargestellt (Allerdings in mehr als einem
Register...).
Divisionsfunktionen in Assembler funktionieren anders. Diese Routinen
spucken in der Regel das Ergebnis und den Rest der Division aus. Sprich:
8/5 = 1 Rest 3
3/4 = 0 Rest 3
Dieses Gesamt-ergebnis ist aber dann auf mehrere Register aufgeteilt.
Wie also schon von dem guten johnny-m gesagt:
> Wie man die 8 Bit in einem Register interpretiert, ist weitgehend Sache> des Anwenders.
Sprich: Wie das Ergebnis der Division aussieht ist Sache der
Divisionsfunktion (Die ja der "Anwender" entwickelt hat).
> Das ist mir schon klar. Die Frage ist was passiert, wenn bei einem> Rechenschritt mal keine ganzen Zahlen auftreten.
Hast Du in der Schule mal schriftliche Division gelernt? Da kommt immer
ein Divisionsergebnis und ein Rest raus. Und genau das passiert auch bei
den Standard-Divisionsalgorithmen.
Du kannst die Formel in Assembler nicht direkt anwenden! Der Controller
kann grundsätzlich nur mit ganzen (binär-)Zahlen rechnen. Alles
darüberhinausgehende sind Tricks, mit denen man sich behelfen kann,
indem man so tut als handele es sich um etwas anderes als ganze Zahlen.
Es ist, wie oben schon gesagt, eine reine Interpretationssache. Ein
Trick wäre z.B., die ganze Berechnung in mV durchzuführen (Faktor 1000,
5 V wäre dann ein Wert von 5000) und erst bei der Berechnung der
auszugebenden Ziffern an der richtigen Stelle das Dezimaltrennzeichen
einzubauen. Das ganze lässt sich aber (wie so vieles) nicht in einem
Register durchführen, da da nunmal nur 256 verschiedene Zustände
reingehen.
>5 ist die Referenzspannung in Volt und 4,9.... ist das Ergebnis in Volt.>Das ist die Spannung, die am ADC-Pin anliegt.
FALSCH!
Es liegen 5V an.
Das ist es ja, was ich sagen will! Wenn ich dieselbe Spannung von genau
5.000V an Uref unf den Messeingang lege, bekomme ich bei der Formel
1023*5 / 1024 = 4,9(95117188)V raus. => passt nicht. Deshalb muss
(5/1023)*Messwert benutzt werden.
Es liegen definitiv 5V am Eingang an, diese will ich als Ergebnis auch
sehen, egal was die Technik der AD-Wandlung zulässt.
Thilo M. wrote:
>>5 ist die Referenzspannung in Volt und 4,9.... ist das Ergebnis in Volt.>>Das ist die Spannung, die am ADC-Pin anliegt.>> FALSCH!> Es liegen 5V an.> Das ist es ja, was ich sagen will! Wenn ich dieselbe Spannung von genau> 5.000V an Uref unf den Messeingang lege, bekomme ich bei der Formel> 1023*5 / 1024 = 4,9(95117188)V raus. => passt nicht. Deshalb muss> (5/1023)*Messwert benutzt werden.> Es liegen definitiv 5V am Eingang an, diese will ich als Ergebnis auch> sehen, egal was die Technik der AD-Wandlung zulässt.
Nein, du liegst falsch. Es liegen 5V an - soweit richtig. Aber was ist
an folgendem, einfachen, deutschen, grammatikalisch richtigen Satz
falsch zu verstehen:
johnny-m wrote:
> Alles, was größer ist, als VREF-1LSB gibt 1023...
Du kannst eine Spannung, die genauso groß ist wie VREF mit einem SAR
Wandler NICHT messen.
Ja, das merk ich auch gerade. Wenn ich jetzt z.B.
3*256 = 768 rechnen möchte komme ich mit 8 Bit nicht aus.
Welchen Trick nimmt man denn um das doch zu berechnen?
Thilo M. wrote:
>>5 ist die Referenzspannung in Volt und 4,9.... ist das Ergebnis in Volt.>>Das ist die Spannung, die am ADC-Pin anliegt.>> FALSCH!> Es liegen 5V an.> Das ist es ja, was ich sagen will! Wenn ich dieselbe Spannung von genau> 5.000V an Uref unf den Messeingang lege, bekomme ich bei der Formel> 1023*5 / 1024 = 4,9(95117188)V raus. => passt nicht. Deshalb muss> (5/1023)*Messwert benutzt werden.> Es liegen definitiv 5V am Eingang an, diese will ich als Ergebnis auch> sehen, egal was die Technik der AD-Wandlung zulässt.
Himmelarsch, NEIN. Deine Formel ist FALSCH!!! Wenn es DIR egal ist, was
da rauskommt, dann ist das DEINE Sache. Erzähl aber bitte keinem
Anfänger, dass das korrekt ist!
Vorschlag: Lies Dir bitte, bevor Du hier weiter solche Sachen
verbreitest, in der einschlägigen Literatur durch, wie der Wandler
funktioniert und bei welcher Spannung er 1023 ausspuckt (nämlich bei
allem, was größer oder gleich VREF - 1 LSB ist).
jochen wrote:
> Ja, das merk ich auch gerade. Wenn ich jetzt z.B.>> 3*256 = 768 rechnen möchte komme ich mit 8 Bit nicht aus.> Welchen Trick nimmt man denn um das doch zu berechnen?
Jou richtig erkannt. Deswegen wird das 10Bit breite Ergebnis ja auch
nicht in einem 8-Bit Register untergebracht, sondern in zweien :-)
In C kannst du einfach einen Int-Typen nehmen. Der hat noch genug Platz
für ein paar Berechnungen. In Assembler gibt es spezielle
Arithmetik-befehle um eine 16-Bit (bzw 10-Bit in diesem Falle) Zahl, die
auf 2 Registern aufgeteilt ist, als eine zu interpretieren. Diese
Funktionen benutzen das Carry-Bit.
Zum Beispiel:
ADD - ADC
SUBI - SUBC
Erstere ist eine reine 8-Bit Funktion. Letzteres das zugehörige
Größer-als-ein-register pendant.
Thilo M.
> 1023 SIND 5V. Was ist daran nicht zu verstehen?
Da ist alles dran zu verstehen. Das Problem ist nur - Das ist falsch :P
Simon Küppers wrote:
> johnny-m wrote:>> Alles, was größer ist, als VREF-1LSB gibt 1023...>> Du kannst eine Spannung, die genauso groß ist wie VREF mit einem SAR> Wandler NICHT messen.
Genau das sage ich ja die ganze Zeit. Der letzte Digitalisierungsschritt
ist VREF-1LSB. Alles was größer / gleich VREF-1LSB ist, ergibt 1023!
So, und jetzt mach ich Feierabend für heute...
@Simon, bevor ich mich damit befasse würde ich gerne wissen was du mit
"Deswegen wird das 10Bit breite Ergebnis ja auch
nicht in einem 8-Bit Register untergebracht, sondern in zweien "
meinst.
Wahrscheinlich das low und high Registern, in denen der gemessene Wert
gespeichert wird. Leider habe ich bis jetzt noch nicht verstanden, was
das überhaupt für Zahlen sind, die da gespeichert werden (sondern nur,
dass sie über eine Formel in den richtigen Wert gewandelt werden
müssen).
Was sind das für 2 Zahlen :-) ?
Thilo M. wrote:
> 1023 SIND 5V. Was ist daran nicht zu verstehen?
Nööö, 1024 sind 5V... Das Verbiegen des Faktors ist die schlechtere
Lösung. Die bessere Lösung ist das Addieren eines Wertes der halben
Auflösung (Rundung)...
Wobei ich es lächerlich finde eine Genauigkeit vorzutäuschen, die
aufgrund der anderen Gegebenheiten gar nicht möglich ist. Hier mal ein
ganz einfaches Beispiel für ADC mit Skalierung:
;Beispiel für ADC am Mega8535...
;Es wird die Spannung eines 12V-Blei-Gel-Akkus gemessen, der über
;einen 78L05 einen Mega8535 versorgt. Als Referenz wird AVCC des
;AVRs genommen (also die 5V des 78L05), die Spannung des 12V-Akkus
;wird über einen Spannungsteiler aus drei gleichen Widerständen
;(3 x 10k) durch 3 geteilt und an ADC7 angelegt.
;Da es kein "Messgerät", sondern nur eine Akkuzustandsanzeige sein
;soll, genügt die Anzeige mit einer Nachkommastelle ("12,9V") auf
;dem LCD 8x24, das noch genügend andere Dinge anzuzeigen hat.
;ADC-Initialisierung in der Reset-Routine:
1
...
2
ldi wl,(1<<adlar)|(1<<refs0)+7;ADC-Quelle 0,
3
out admux,wl ;linksbuendig
4
ldi wl,(1<<aden)|(1<<adsc)|(1<<adate)+4 ;ADC ein
5
out adcsra,wl ;
6
...
;zyklischer Aufruf in der Mainloop alle 100 ms:
1
...
2
in r0,adch ;ADC-Wert (1/3 der Akkuspannung) einlesen
3
ldi wl,151 ;Skalierungsfaktor
4
mul r0,wl ;auf ZehntelVolt skalieren
5
locate 6,5 ;Ausgabeposition Spannung
6
print16 null,r1,1,using ;Wert mit 1 Kommastelle ausgeben
jochen wrote:
> @Simon, bevor ich mich damit befasse würde ich gerne wissen was du mit>> "Deswegen wird das 10Bit breite Ergebnis ja auch> nicht in einem 8-Bit Register untergebracht, sondern in zweien ">> meinst.>> Wahrscheinlich das low und high Registern, in denen der gemessene Wert> gespeichert wird. Leider habe ich bis jetzt noch nicht verstanden, was> das überhaupt für Zahlen sind, die da gespeichert werden (sondern nur,> dass sie über eine Formel in den richtigen Wert gewandelt werden> müssen).>> Was sind das für 2 Zahlen :-) ?
Die 2 Zahlen sind eigentlich eine Zahl. Und zwar eine 10-Bit breite
Zahl. Du musst dir das so vorstellen:
Der AD-Converter hat eine bestimmte Auflösung (hier nämlich 10-Bit). Das
heißt: Er kann einen Spannungsbereich (nämlich 0V bis VREF) in 2^10
Stufen aufteilen. Legst du jetzt eine Spannung an den Pin an, und lässt
den AD-Converter wandeln, so gibt er dir als Ergebnis sozusagen die
Stufe aus, in der sich die an den AD-Pin gelegte Spannung befindet.
Das kann eine Zahl sein, die zwischen 0 (Spannung ist 0V) und 1023
(Spannung ist VREF-1LSB) liegt.
Das ist die ganze Funktionalität des ADC-Wandlers. Was du nun mit dem
"Stufen-Wert" anstellst, ist deine Sache. Eine Methode ist es eben diese
Formel anzuwenden um den "Stufen-Wert" in einen absoluten Spannungswert
umzurechnen.
Blöderweise ist die Zahl 1023 (Also der höchste Wert des ADCs) aber 10
Bit breit. Der Controller hat aber nur 8-Bit Register. Also wird der
Wert aufgetrennt und auf zwei Register verteilt. Eigentlich blöd -
oder?. Nö! Denn der Mikrocontroller ist in der Lage eine Zahl, die über
mehrere Register verteilt ist, aber eigentlich zusammengehörig ist auch
als zusammengehörig zu behandeln. Siehe mein obiger Post mit den
Carry-Funktionen. Wenn du nicht weißt, was es mit dem Carry-Flag auf
sich hat, würde ich dir etwas Grundlektüre zur Funktionsweise eines
Mikrocontrollers empfehlen.
@Hannes:
> Nööö, 1024 sind 5V... Das Verbiegen des Faktors ist die schlechtere> Lösung. Die bessere Lösung ist das Addieren eines Wertes der halben> Auflösung (Rundung)...
Du hast schon Recht, allerdings wird der ADC niemals 1024 ausspucken ;)
Aber das weißt du auch selber. Nur dass das hier nicht für Verwirrung
sorgt.
> Wobei ich es lächerlich finde eine Genauigkeit vorzutäuschen, die> aufgrund der anderen Gegebenheiten gar nicht möglich ist.
Da hast du natürlich auch Recht (was auch sonst ;)), aber trotzdem
sollte man immer versuchen mathematisch korrekt zu sein.
Hi
Wie das Ergebnis aussieht ist, von deiner Dividierroutine abhängig. Da
es keinen Dividierbefehl gibt hängt die Interpretation der Zahlen und
das Ergebnis vom Programmierer ab. Für die Floatmultiplikationen der
AVRs wird z.B. bei 8 Bit folgendes Format verwendet:
MSB: Vorzeichen, a*2^-1,b*2^-2, c*2^-3,d*2^-4,e*2^-5,f*2^-6,g*2^-7
wobei Vorzeichen,a..g 0 oder 1 sein können.
Daneben existieren noch eine ganze Reihe anderer Fliess- und
Festkommaformate. Trotzdem ist allen eines gemeinsam: sie bestehen nur
aus Bits(0/1). Nur die Bedeutung eines Bits ist unterschiedlich.
Die meisten Divierroutinen arbeiten mit Ganzzahlen. Bei deinem obigen
Beispiel wurde 0 herauskommen (bestentfalls mit einem Rest 5).
MfG Spess
Danke für dei Beschreibungen, jetzt ist mir dei Funktionsweise auch
einigermaßen klar.
"Wenn du nicht weißt, was es mit dem Carry-Flag auf
sich hat, würde ich dir etwas Grundlektüre zur Funktionsweise eines
Mikrocontrollers empfehlen."
Das Carry Flag ist doch das Flag was gesetzt ist wenn das Ergebnis nicht
mehr in das Register passt, oder irre ich (overflow)
Könntest du / ihr mir noch sagen wie ich eine Zahl, die in mehreren
registern ist aber eigentlich zusammengehört dann auch als
zusammengehörig betrachtet wird?
Und andersrum wie ich mit Zahlen rechne, welche die Bitbreite
überschreiten z.B. 256 *3. Da wurde oben zwar schon was zu gesagt aber
das reicht mir leider nicht.
jochen wrote:
> Das Carry Flag ist doch das Flag was gesetzt ist wenn das Ergebnis nicht> mehr in das Register passt, oder irre ich (overflow)>> Könntest du / ihr mir noch sagen wie ich eine Zahl, die in mehreren> registern ist aber eigentlich zusammengehört dann auch als> zusammengehörig betrachtet wird?> Und andersrum wie ich mit Zahlen rechne, welche die Bitbreite> überschreiten z.B. 256 *3. Da wurde oben zwar schon was zu gesagt aber> das reicht mir leider nicht.
Ja, so in der Art. In Assembler (In C brauchst du dich darum nicht
kümmern.) machst du das folgendermaßen:
So in der Art sollte das aussehen. Funktionsweise:
add (Erster Teil der 16-Bit Addition) setzt das Carry-Flag. Jenachdem,
ob bei der Addition das Register übergelaufen ist.
adc (Zweiter Teil) addiert ebenfalls (wie add) die Register. ABER: Es
wertet zudem noch das Carry-Flag aus. Ist es 1, so wird adc 1 zu dem
High register hinzuzählen.
Ich danke dir, ich muss mir das jetzt in Ruhe ansehen und auch mal die
Zahlen was verändern und mit dem Studio mal simulieren. Das könnte aber
was dauern. Ich melde mich morgen noch einmal und möchte mich recht
herzlich bedanken. Kennt ihr denn Bücher wo sowas alles erklärt ist? Ich
finde leider auch in google keine Links wo man das nachlesen kann. Wie
habt ihr das denn gelernt?
Ich habe mir das Beispiel nun angesehen.
Wie teilt sich eine Zahl denn in 2 Register genau auf, also wie sieht
der low und der high Anteil aus?
Zum Beispiel
ldi r16, HIGH(1024)
ldi r17, LOW(1024)
Jetzt habe ich die 1024 aufgeteilt auf die Register r16 und r17. Ok,
aber was genau von der 1024 ist jetzt in r16 und was genau in r17?
Wird das Register r16 mit dem HIGH-Teil geladen. Das wären:
1
00000100
Das Register r17 wird mit dem LOW-Teil geladen.
1
00000000
Und schon kann der Prozessor damit rechnen.
PS: Die Makros "HIGH" und "LOW" sind nicht unbedingt notwendig, machen
die Sache aber einfacher. Du kannst in diesem Falle hier genauso gut
schreiben:
Danke, Simon!
Ich habe eben überlegt, wie die Multiplikation nach diesem Schema
abläuft, bin aber leider nicht darauf gekommen. Hast du dafür auch ein
Schema?
Kleiner Tip am Rande:
Es gibt bei den AVRs auch ein paar Befehle (z.B. adiw, sbiw), die 16 Bit
(zwei hintereinander befindliche Register) gleichzeitig verarbeiten
können. Diese Befehle funktionieren allerdings nur dann korrekt, wenn
Low- und High-Byte des 16-Bit-Wortes in der richtigen Reihenfolge
stehen. Die AVRs sind "Little-Endian" ("Intel-Format"), d.h. das
Low-Byte eines Datenwortes wird an der niedrigeren Speicheradresse
(niedrigere Registernummer) abgelegt. Um spätere Probleme damit zu
vermeiden, ist es vielleicht sinnvoll, sich gleich die Reihenfolge
anzugewöhnen. In dem Beispiel mit den 1024 müssten dann Low- und
High-Byte vertauscht werden, also
1
ldi r17, HIGH(1024)
2
ldi r16, LOW(1024)
(das ganze gilt übrigens auch für Befehle, die mit indirekter
Adressierung und den damit verbundenen Zeigern, die in speziellen
Registerpaaren stehen, arbeiten und die sich jedem Programmierer
irgendwann aufdrängen)
@Johannes M.: ouh, damit habe ich noch nie gearbeitet :-) Klingt aber
schlüssig.
jochen wrote:
> Danke, Simon!> Ich habe eben überlegt, wie die Multiplikation nach diesem Schema> abläuft, bin aber leider nicht darauf gekommen. Hast du dafür auch ein> Schema?
Die neuen AVRs haben eine Multipliziereinheit, die 2 8-Bit-Werte
multiplizieren können. Das Ergebnis wird aber als 16-Bit ausgegeben.
Logisch: Der Wertebereich ist bei 8Bit * 8Bit = 16Bit.
Bei einer 16*16Bit Multiplikation muss ich leider passen.
Simon Küppers wrote:
> Die neuen AVRs haben eine Multipliziereinheit,...
Genauer gesagt: Die ATMegas. Die Tinys haben sowas nicht.
> ...die 2 8-Bit-Werte> multiplizieren können. Das Ergebnis wird aber als 16-Bit ausgegeben.> Logisch: Der Wertebereich ist bei 8Bit * 8Bit = 16Bit.
Richtig. Und auch dabei ist die Reihenfolge zu beachten: Das Low-Byte
des Ergebnisses liegt im Register mit der niedrigeren Adresse.
Die Appnote AVR200 von ATMEL (deren Existenz ganz oben schon mal
angedeutet wurde) beinhaltet neben Divisions- auch
Multiplikationsroutinen für 8 und 16 Bit, mit und ohne Vorzeichen. Ist
zwar leider auf Englisch, aber es macht jedenfalls Sinn, sich diese
Routinen einfach mal anzusehen und zu versuchen, ihre Funktion zu
verstehen.
http://www.atmel.com/dyn/resources/prod_documents/doc0936.pdf
also mein Ziel ist es ja,
1. 768 +255 = 1023
2. 1023 * 5 = 5115
3. 5115 / 1024 = 4,9
zu berechnen.
1. Hab ich ja jetzt.
Beim 2. Schritt komme ich nicht weiter.
Ich wüsste zwar, wie ich das mit 8 Bit Registern mache, aber nicht wenn
eine Zahl, hier die 1023 auf 2 Register aufgeteilt ist. Der Link von
Johannes hilft mir leider auch nicht, das dzu verstehen.
Überleg mal, was da jetzt explizit in den beiden Registern steht: Du
hast ein High-Byte und ein Low-Byte. Nimm jetzt an, Du hast ein
Zahlensystem mit der Basis 256 (also eben nicht Zehn wie im
Dezimalsystem, sondern so viel, wie sich mit einem Byte eben darstellen
lässt). In diesem Zahlensystem hast Du jetzt zwei Stellen: Das Low-Byte
sind die "Einer" und das High-Byte die "256er". Für die Zahl 1023 aus
dem Beispiel (0000 0011 1111 1111 in Binärdarstellung) hieße das jetzt,
dass die Einer-Stelle den Wert 1111 1111 (also dezimal 255) hat, und die
256er-Stelle den Wert 0000 0011 (dezimal 3). Daraus folgt
Nur zur Verdeutlichung: Das entspricht der Aufschlüsselung der 1023 im
Dezimalsystem nach Einern, Zehnern, Hundertern und Tausendern (1023 = 1
* 1000 + 0 * 100 + 2 * 10 + 3 * 1), nur dass hier jetzt jede Stelle
nicht 10, sondern 256 Zustände annehmen kann. Und jetzt überlege mal
(mit Schulmathematik), wie man eine Dezimalzahl multipliziert und
versuche, das Schema auf das 256er-Zahlensystem zu übertragen.
Ich muss jetzt leider grad mal weg, schaue aber nach mittag noch mal
rein, wenn ich Zeit hab...
Hi Johannes, danke auch Dir, dass du dir da so eine Mühe machst.
Ich habe dein letztes Posting soweit verstanden.
1023*5 = 5115 im 256er System:
1023 entspricht 3255
5 entspricht 5
also
3255*5
-------
15102525
es entstehen keine Überträge, da 256 nie erreicht wird.
Stimmt das bis hier hin?
Wie wäre diese Zahl zu interpretieren d.h. Wo sind die Einerstellen, die
256er Stellen, die 256^2 Stellen usw?
jochen wrote:
> Hi Johannes, danke auch Dir, dass du dir da so eine Mühe machst.> Ich habe dein letztes Posting soweit verstanden.>> 1023*5 = 5115 im 256er System:>> 1023 entspricht 3255> 5 entspricht 5>> also>> 3255*5> -------> 15102525>> es entstehen keine Überträge, da 256 nie erreicht wird.>> Stimmt das bis hier hin?> Wie wäre diese Zahl zu interpretieren d.h. Wo sind die Einerstellen, die> 256er Stellen, die 256^2 Stellen usw?
Nee, Du musst die einzelnen Stellen separat betrachten! 3255 muss
eigentlich (3 255) geschrieben werden. Das sind nicht
dreitausenzweihundertfünfundfünfzig! Worauf ich hinauswollte, war, dass
Du die 16-Bit 8-Bit-Multiplikation durch die Summe zweier 8-Bit
8-Bit-Multiplikationen ersetzen kannst. Wenn Du im Dezimalsystem 1023
mit 5 multiplizierst, dann rechnest Du
1023 = 1 * 1000 + 0 * 100 + 2 * 10 + 3 * 1
1 1000 5 = 5 * 1000
0 100 5 = 0 * 100
2 10 5 = 10 * 10 = 1 * 100
3 1 5 = 15 * 1 = 1 * 10 + 5 * 1
--------------
5 * 1000 + 1 * 100 + 1 * 10 + 5 * 1 = 5115
Im 256er-System hast Du jetzt
3 256 5 = 15 * 256
255 1 5 = 1275 * 1 = 4 * 256 + 251 * 1
-----------------
19 * 256 + 251 * 1 (= 5115)
Du machst also für das Low- und das High-Byte jeweils eine separate
Multiplikation und addierst die Ergebnisse.
Bsp.:
Ok, danke. Das konnte ich gut nachvollziehen.
Eine Unklarheit hab ich noch.
Ergebnis Multipl. High-Byte 0000 0000 0000 1111 (15) [16 Bit!]
Ergebnis Multipl. Low-Byte 0000 0100 1111 1011 (1275) [16 Bit!]
Es entsteht bei der Multiplikation von 255 mit 4 ein 16 Bit Ergebnis.
Wie setze ich das denn um? Müsste ich dann das high und Low bye jeweils
wieder in ein High und Low byte unterteilen?
jochen wrote:
> Es entsteht bei der Multiplikation von 255 mit 4 ein 16 Bit Ergebnis.> Wie setze ich das denn um? Müsste ich dann das high und Low bye jeweils> wieder in ein High und Low byte unterteilen?
Das ist ja bereits der Fall. Wie weiter oben schon erwähnt, legen die
Multiplikationsbefehle das Ergebnis in zwei Registern ab (r0 und r1),
unter Beachtung der Reihenfolge (niedrigere Adresse -> Low-Byte). Da
musst Du sie dann abholen und weiterbearbeiten.
jochen wrote:
> Wie setze ich das denn um?
Jochen, denke mal an das schriftliche Multiplizieren mehrstelliger
Zahlen in der Grundschule.
Man multipliziert eine Stelle des einen Faktors nach der anderen mit dem
anderen Faktor, schreibt die Zwischenergebnisse stellenversetzt
untereinander und addiert sie anschließend.
Das musst Du doch iin der Grundschule gelernt haben!
Oder hast Du etwa durch den Besitz eines Taschenrechners damals in der
Grundschule bereits geschummelt und Dich somit vor dem Erlernen
wichtigen Grundwissens gedrückt? Dann hat das hier alles keinen Zweck,
dann musst Du nochmal mit der Grundschule beginnen, sorry...
...
P.S.: Langsam nervt die Lernresistenz dieser Jochens und Nick-Simons...
Das spamt das ganze Forum zu...
Hi, danke ich rechne jetzt einfach mal, simuliere im AVR Studio um das
zu verarbeiten. Ich melde mich dann die nächsten Tage nochmal und
berichte von meinen Ergebnissen. Danke!
Wenn es nervt, wieso antwortest du dann?
Das Multiplizieren von Zahlen in anderen Zahlenformaten als dem
Zehnersystem ist Hochschulstoff der ersten Semester. Ist der Unterschied
Hoch und Grundschule klar? Sorry, aber ich finde deinen Einwand einfach
nicht berechtigt.
jochen wrote:
> Wenn es nervt, wieso antwortest du dann?> Das Multiplizieren von Zahlen in anderen Zahlenformaten als dem> Zehnersystem ist Hochschulstoff der ersten Semester.
Das Prinzip ist völlig identisch und unabhängig vom
Zahlensystem.
Jochen, ich glaube, du denkst noch viel zu kompliziert.
Das alles ist viel einfacher als du jetzt vermutest.
Ja ich schau mir das auch morgen in Ruhe mal an und dann denke ich
bekomme ich das Prinzip auch raus. Nur jetzt sagen ich soll in der
Grundschule anfangen finde ich schon ziemlich krass.
Habt ihr damit eigentlich beruflich zu tun oder macht ihr das nur
hobbymäßig? Studiert in diesem Bereich?
Du kennst das Prinzip von Low-Byte/High-Byte schon längst,
nur warst du dir nie darüber bewusst.
Nehmen wir mal das gewohnte Dezimalsystem.
Angenommen du hättest eine 2 stellige 'Maschine'
+---+---+
| | |
+---+---+
Jede Box in dieser Maschine, kann eine Ziffer von 0 bis 9
aufnehmen. zb
+---+---+
| 5 | 6 |
+---+---+
und wir interpretieren diese Zahl als 56 (also 5 Zehner und
6 Einer)
Um da jetzt 18 zu addieren, gehst du wie folgt vor:
du nimmst die rechte Box und addierst die 8: 6 + 8 = 14
Nur gibt es da jetzt ein Problem: Jede Box kann nur Ziffern
von 0 bis 9 aufnehmen. 14 geht nicht in diese Box hinein.
Also gehen wir so vor: In die Ergebnisbox kommt eine 4 und
wir merken uns, dass bei der nächsten Stelle links eine zusätzliche
Eins noch mit dazu addiert werden muss (genau: Das ist der
berühmte Carry).
Die zweite Addition lautet daher 5 + 1 + 1 (wegen dem Carry) = 7
Das Ergebnis ist daher
+---+---+
| 7 | 4 |
+---+---+
und du ahnst es schon: In diesem Beispiel fungiert die linke
Box als 'High-Byte' und die rechte als 'Low-Byte'. Das Prinzip
jedoch ist völlig identisch, egal ob ich jetzt im Dezimalsystem,
oder Hex, oder Binär oder sonst irgend ein Zahlensystem benutze.
Binär ist halt besonders einfach, weil das 'kleine Einmaleins'
der Addition besonders einfach wird.
0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 0 und 1 Übertrag
Aus praktischen Gründen wird allerdings nicht jede einzelne der
Binären Ziffern in einer eigenen Box gespeichert (na ja, eigentlich
schon), sondern jeweils 8 Stück davon werden zusammengefasst und
in ein 'Register' verbannt. Das ändert aber nichts am Prinzip.
Wenn du mit 16 Bit Zahlen operierst, dann sind da erst mal
16 derartige Boxen nebeneinander. Da in ein Register aber nur
8 davon hineinpassen, nimmt man einfach 2 davon her und nennt
das eine das Low-byte und das andere das High-Byte
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| | | |
+---------------------------+ +---------------------------+
High Byte Low Byte
gespeichert in einem gespeichert in einem
Register Register
Das alles ist nur eine ausführliche Beschreibung dafür, was du
in der Grundschule gelernt hast. Und genau so wie man sich
das für Addition überlegen kann, kann man sich das auch für
Multiplikation überlegen. Geh jeden Schritt durch, so wie du
ihn damals gelernt hat.
Multiplikation ist binär wieder ganz besonders einfach, weil
das kleine 'Einmal Eins' besonders einfach ist:
Es gibt nur 2 Möglichkeiten, entweder es wird mit 0 multipliziert,
dann ist das Ergebnis 0 oder es wird mit 1 multipliziert, dann
ist das Ergebnis identisch mit der Ursprungszahl. Der eigentliche
Rechengang ist aver genauso wie du ihn in der Grundschule
für das Zehnersystem gelernt hast, nur dass du dort das kleine
Einmal Eins für alle Multiplikatoren von 0 bis 9 auswendig
können musstest.
10110 * 101
-----
10110 ( weil 10110 * 1)
00000 ( weil 10110 * 0)
-----
101100 ( <- Zwischensumme )
10110 ( weil 10110 * 1)
-------
1101110 ( Endsumme = Multiplikationsergebnis )
Aber genauso, wie man im Dezimalsystem eine Multiplikation
in einfachere Teilmultiplikationen zerlegen kann:
123 * 56 = ( 100 * 56 ) + ( 23 * 56 )
(*)
kann man das auch im Binärsystem. Wenn eine Hardwaremultiplikation
zur Verfügung steht, dann wird man das auch so machen, wenn man
über mehrere Register arbeiten muss.
Hat man das nicht, dann macht man genau das was oben binär
gemacht wurde: Entweder mit 0 oder mit 1 multiplizeren und
aufaddieren. Die Stelle verschieben (ob ich den neu zu addierenden
Term um 1 Stelle nach rechts versetzte oder das Zwischenergebnis
um 1 Stelle nach links, kommt auf dasselbe hinaus) und alle Bits
des Multiplikators durchgehen: Ist er 1, wird der ursprüngliche
Multiplikand dazuaddiert, ist er 0 passiert nicht (weil
ja eine Addition von 0 nichts ändert)
(*) 100 * 56 ist besonders einfach zu rechnen, weil ich das
ja als 1 * 56 rechnen kann und nur darauf achten muss, dass
ich dieses Zwischenergebnis ins Endergebnis um die richtige
Anzahl Stellen nach links verschoben aufaddieren muss. Damit
habe ich aber erreicht, dass ich die Multiplikation einer
3 stelligen Zahl mit einer 2 stelligen Zahl auf 2 Multiplikationen
von jeweils 2 2-stelligen Zahlen, eine entsprechende Verschiebung
und eine Addition zurückgeführt wurde. Wenn ich jetzt einen Menschen
habe, der das kleine 1*1 für alle 2-stelligen Zahlen auswendig
kann, dann kann er mit diesem Kochrezept auch 3-stellige Zahlen
mit 2-stellige Zahlen multiplizieren ohne dass er auf die
ausführliche 'Grundschulmultiplikation' zurückgreifen muss.
Ein µC mit 8-Bit Hardwaremultiplikation ist aber so ein
'Mensch der das kleine 1*1' für größere Stellenzahl auswendig
gelernt hat.
jochen wrote:
> Nur jetzt sagen ich soll in der> Grundschule anfangen finde ich schon ziemlich krass.
Du magst das nicht hören wollen, aber es ist tatsächlich so:
Du hast das 'Prinzip' tatsächlich in der Grundschule gelernt,
nur hat man dir das damals nicht so verkauft.
> Habt ihr damit eigentlich beruflich zu tun oder macht ihr das nur> hobbymäßig? Studiert in diesem Bereich?
Was ich von den regelmäßigen Forenteilnehmern so mitgekriegt
habe: Teils, teils.
> Das Multiplizieren von Zahlen in anderen Zahlenformaten als dem> Zehnersystem ist Hochschulstoff der ersten Semester. Ist der> Unterschied Hoch und Grundschule klar?
Das hat meine Tochter bereits in der 9./10. Klasse (auf dem Gymnasium im
sprachbetonten Zweig) im Informatikunterricht gelernt ... das ist
niemals Hochschulstoff. In der Hochschule/Universität wird erwartet, daß
solche Elementarkenntnisse bereits vorliegen.
Das ist ein Übungsblatt mit Aufgaben zur selbständigen Übung ... keine
Darstellung zum Lehrstoff. Daß man es nochmal üben läßt, um dieses
Wissen z. B. wieder anwendungsbereit bzw. sicher zu machen, heißt noch
lange nicht, daß es nicht vorausgesetzt wird.
Wenn du sagst "das ist niemals Stoff an eienr Universität" meinst du
damit wohl, dass es dort nicht behandelt wird. Sonst wäre es ja Stoff.
Es wird aber sehr wohl behandelt, "Zahlendarstellung und Codierung" ist
ein Oberthema. Somit ist es Hochschulstoff und kein Grundschulniveau.
... Je nachdem auf welcher Schule man ist. Für Otto - Normal-Student
wohl eher nicht, Informatik ist zumindest hier bei den Schulen bei uns
eher nicht Schulfach.
Deswegen ist es auch gut, dass es im ersten Semester nochmal als
seperates Thema auftaucht, da so jeder die Chance hat, klarzukommen und
nicht die Leute die von irgendeiner teschnischen Schule kommen absolut
im Vorteil sind.
jochen wrote:
> Das ist leider falsch>
Das ändert aber nichts an der Tatsache, daß das Prinzip
von Addition, Subtraktion, Multiplikation etc. identisch
ist zu dem in der Grundschule gelernten und unabhängig vom
benutzten Zahlensystem ist.
Ist schon klar, dass man 7-jährige nicht mit binärer Arithmetik
quält, die haben andere Sorgen.
Ich habe jetzt angefangen, die Multiplikation in Assembler umzusetzen.
Dabei bin ich gleich vom allgemeinen Fall ausgegangen, wenn in den AD
Wandler eingelesen wird. Könntet ihr Euch das mal ansehen und mir dann
sagen ob das so effektiv ist und überhaupt stimmt? Das hat leider
ziemlich viele Register beansprucht:
in adlow, ADCL
in adhigh, ADCH
//Multiplikation.
// Anfangswert H Byte: adhigh
// Anfangswert L Byte: adlow
// Multiplikator: 5
ldi r19, 5
//Multiplikation L Byte
MUL adhigh, r19
//Sichere die Register r0 und r1. Das Ergebnis der Multiplikation vom L
Byte ist dann r21 und direkt daran r20 angehängt. Ich schreibe das für
die weiteren Erklärungen dann immer r21#r20
mov r20,r0
mov r21r1
//Genauso Multiplikation H Byte. Ergebnis der Multiplikation vom H Byte
ist dann r23#r22
mul adlow, r19
mov r22,r0
mov r23,r1
//Man hat also
// Ergebnis L Byte: r21#r20 [16bit]
// Ergebnis H Byte: r23#r22 [16bit]
//Multiplikation Ergebis H Byte * 256
// Das Ergebnis dieser Multiplikation ist dann [24bit] und r27#r26#r25
ldi r24,256
mul r20,r24
mov r25,r0
mov r26,r1
mul r21,r24
mov r27,r0
> //Multiplikation Ergebis H Byte * 256> // Das Ergebnis dieser Multiplikation ist dann [24bit] und r27#r26#r25> ldi r24,256
Erstens passt "256" nicht in ein Register und zweitens hatte ich weiter
oben schon mal geschrieben, wie eine Multiplikation mit Zweierpotenzen
durchgeführt werden kann. 256 ist 2^8, also muss einfach nur der Wert um
8 Bits nach links geschoben werden. Und das wiederum bedeutet, dass es
um ein komplettes Byte (also ein Register) verschoben wird (was man
wiederum einfach erreicht, indem man ein weiteres Register mit dem
Inhalt "0" hinten dran hängt).
Johannes M. wrote:
>> //Multiplikation Ergebis H Byte * 256>> // Das Ergebnis dieser Multiplikation ist dann [24bit] und r27#r26#r25>> ldi r24,256> Erstens passt "256" nicht in ein Register und zweitens hatte ich weiter> oben schon mal geschrieben, wie eine Multiplikation mit Zweierpotenzen> durchgeführt werden kann. 256 ist 2^8, also muss einfach nur der Wert um> 8 Bits nach links geschoben werden. Und das wiederum bedeutet, dass es> um ein komplettes Byte (also ein Register) verschoben wird (was man> wiederum einfach erreicht, indem man ein weiteres Register mit dem> Inhalt "0" hinten dran hängt).
Also exakt genauso wie im Dezimalsystem, mit dem einzigen Unterschied,
dass eine "Stelle" eben einen Wertevorrat von 256 (0..255) statt 10
(0..9) hat. Grundschul-Niveau eben...
...
Johannes, ich danke Dir.
Ich hab noch eine Sache, die mir im moment nicht einleuchtend ist.
Wiesoist das Ergebnis dieser Multiplikation dann genau 24 Bit groß?
...und jetzt überleg mal, was wohl passiert, wenn man die 16-Bit-Zahl
(XXXX...) um 8 Bit nach links schiebt (was, wie oben schon gesagt, einer
Multiplikation mit 256 entspricht).
Hallo,
Faustregel: ;)
Stellenzahl bei Multiplikation (gilt auch für alle Zahlensysteme).
Die Anzahl Stellen des Produkts ist maximal gleich der Summe der Anzahl
Stellen der Faktoren.
Dezimal: 9 (eine Stelle) * 9 = 81 -> mehr geht nicht.
99 * 999 = 98901 -> 2 Stellen + 3 Stellen -> maximal 5 Stellen.
Binär 16 Stellen * 8 Stellen -> maximal 24 Stellen
16Bit * 16Bit -> 32 Bit
Gruß aus Berlin
Michael
0000 0000 0001 00, 11 1111 1011
die vier, 00000100, vor dem Komma erkenne ich. Das könnte ich ja dann
auch direkt an einen Treiber und so an eine Segmentanzeige schicken.
Wie mache ich die 9 erkenntlich? Könnte man daraus gar die Zahl 5
erstellen?
Ich habe herausgefunden, dass man 2^-1 + 2^-2 + 2^-3 + 2^-4 + 2^-5 +
2^-6 + 2^-7 für die ersten 8 Bit nach dem Komma rechnen muss.
Gibt es dafür für den Assembler eine Möglichkeit um am Ende dann
wirklich eine 9 an die Anzeige zu senden?
In dem Register wird kein "4,9" stehen. Sondern (wenn du alles richtig
gemacht hast, wird durch die ganzen Divisionen (Bzw nach
rechts-schiebungen) nur noch "4" in deinem Register stehen.
also am Ende, nach den Verschiebungen habe ich
0000 0000 0001 00, 11 1111 1011
die 4 ist dann ja noch 0001 00 (s.o) oder?
müsste dann nicht 11 1111 1011 mit der 9 was zu tun haben?
Ist das die Idee?
Noch mal: Mit den Standard-Operationen kannst Du NUR ganzzahlige
Rechnungen machen! Eine 4,9 gibt es so nicht. Die musst Du Dir selber
erzeugen, indem Du z.B. den Nachkommateil aus dem Rest der Division
selber errechnest. Und das geht tatsächlich genau so, wie beim
schriftlichen Dividieren bzw. Multiplizieren. Und den Rest der Division
durch 1024 bekommst Du, indem Du oder während der eigentlichen Division
die letzten 10 Bit des Ausgangswertes (das ist nämlich genau das, was
bei der Schieberei hinten rausplumpst und was bei Dir hinter dem Komma
steht) sicherst. Das geht z.B., indem Du das Schieben mit ror machst
(was für die höherwertigen Bytes sowieso gemacht werden muss) und das
Carry-Flag wiederum in ein Registerpaar hineinschiebst. Die Rechnung
lautet dann
5115 / 1024 = 4 Rest 1019
Für die Weiterverarbeitung des Restes musst Du dann halt noch ein
bisschen rechnen.
Ach ja, noch was: So falsch ist Deine Vermutung natürlich nicht:
1019 / 1024 = 0,995...
Du musst eben noch den Rest verarbeiten und v.a. korrekt runden! 0,995
ist nicht 0,9...
Für die Weiterverarbeitung des Restes musst Du dann halt noch ein
bisschen rechnen.
Das ist mein Problem, wie ich das anstelle. Ich habe 2 Ideen:
Die erste ist (s.o) ich rechne:
2^-1 + 2^-2 + 2^-3 + 2^-4 + 2^-5 +
2^-6 + 2^-7
die zweite ist wie du schreibst
1019 / 1024 = 0,995.
ich weiß jedoch nicht, wie ich das mit den Standart sachen hinbekomme,
ich kann bis jetzt nur die Sachen die wir besprochen haben. Dividieren
durch 1024 (zweite Mmöglichkeit) könnte ich zwar, jedoch bewege ich mich
dann im Kreis, weil ich dann ja nur die 0 vor dem Komma richtig auslesen
kann.
Jochen, Deine Binärschreibweise verkompliziert die Betrachtung
erheblich. Betrachte die Bytes als "Ziffern" (mit dem Wertevorrat
0..255), das wird übersichtlicher. Und wenn es gar nicht geht, dann nimm
die "komprimierte Binärschreibweise", schreib' also hexadezimal, dann
repräsentiert jede Ziffer 4 Bit, also ein halbes Byte, auch Nibble
genannt...
Zu den (getürkten) Kommazahlen (Festkomma oder Fixpoint):
Man errechnet sich einfach einen Wert, der dem zehnfachen, hundertfachen
oder tausendfachen des anzuzeigenden Wertes entspricht und füge bei der
Ausgabeformatierung an der entsprechenden Stelle (1, 2 oder 3 Stellen
vor Ende der Zahl) ein Komma oder Dezimalpunkt ein.
Schau Dir mal meine Ausgabeformatierungsroutine für 16-Bit-Integerzahlen
an (Anhang), der kann man mitteilen, ob, und an welcher Stelle sie ein
Komma einfügen soll.
In Deinem Fall, wenn Du also bis zu 5 Volt messen willst, bietet sich
an, den 10-Bit-Messwert mit 125 zu multiplizieren, das Low-Byte (der
24-Bit-Zahl) zur Rundung heranzuziehen (wie im ADC-Tutorial) und dann
wegzuwerfen, und nur die beiden oberen Bytes mit 2 Stellen hinter dem
Komma auszugeben. Du erhältst also eine Zahl bis 500, die dann als 5,00
ausgegeben wird. Das geht natürlich auch dreistellig, aber dann passt
der Skalierungsfaktor von 1250 nicht mehr in ein Byte, was die
Multiplikation verkompliziert, ohne wirklich mehr Genauigkeit zu bieten.
...
Nachtrag:
Mein Vorschlag der Skalierung beruht darauf, Divisionen durch "krumme"
Werte zu vermeiden. Es wird nur durch 256 dividiert, was durch Wegwerfen
des niederwertigen Bytes erfolgt. Zuvor wird dieses Wegwerfbyte
allerdings darauf überprüft, ob es größer als 127 (die Hälfte) ist, um
eine Rundung durchführen zu können, da sonst der Wert von 5,00 Volt nie
angezeigt werden könnte.
...
Hannes, deine Lösungsidee gefällt mir sehr gut, aber den Code im Anhang
versteh ich mal überhaupt garnicht. Dennoch würde ich jetzt gerne eine
Möglichkeit haben den angefangenen Weg zum Ende zu bringen, bevor ich
mit einem neuen beginne.
"Für die Weiterverarbeitung des Restes musst Du dann halt noch ein
bisschen rechnen."
In Assembler umsetzen?
also
5115 / 1024 = 4 Rest 1019
die 4 hab ich und den Rest hab ich auch. Aber jetzt müsste ich den Rest
noch so verarbeiten, dass ich eine 9 auf die Anzeige bekomme.
Das bekomm ich leider nicht gelöst. Wie macht man es?
1024 .... 1.0
1019 .... x
1019
x = -----
1024
Da hier jetzt aber eine Zahl zwischen 0 und 1 rauskommt,
wird es wohl sinnvoll sein, da erst mal mit 10 zu multiplizieren.
1019 * 10
---------
1024
Hinweis um mit 10 zu multiplizieren braucht man keine
allgmeine Multiplikation
Zahl * 2 ; * 2
nochmal * 2 ; * 4
original Zahl addieren ; * 5
nochmal * 2 ; * 10
Du ahnst es schon: * 2 ist trivial zu rechnen, einfach alle
Bits um eine Stelle nach links schieben.
@ jochen (Gast)
>5115 / 1024 = 4 Rest 1019>die 4 hab ich und den Rest hab ich auch. Aber jetzt müsste ich den Rest>noch so verarbeiten, dass ich eine 9 auf die Anzeige bekomme.>Das bekomm ich leider nicht gelöst. Wie macht man es?
Nun, dein Rest sind die Nachkommastellen im Festkommaformat. Die
Auflösung ist 1/1024 tel.
Du brauchst aber nur 1/10 tel. Ohne Division kann man einfach
vergleichen
9/10 ~ 922/1024
8/10 ~ 819/1024
...
1/10 ~ 102/1024
Num musst du nur noch vergleichen, ob dein Rest grösser gleich der
jeweiligen Zahl ist und schon hast du deine Nachkommastelle.
MFG
Falk
jochen wrote:
> Das bekomm ich leider nicht gelöst. Wie macht man es?
Wenn in eine Apfelsinenkiste 1024 Apfelsinen passen und
du 5115 Apfelsinen hast, wiviele Kisten kannst du voll
machen, und wieviele Apfelsinen bleiben übrig?
5115 / 1024 = 4 -> Anzahl voller Kisten
Rest( 5115 / 124 ) = 1019 -> soviele Apfelsinen sind
in der letzten nicht vollen
Kiste
Wenn in der nicht vollen Kiste 1019 Apfelsinen sind, zu wieviel
Prozent ist die letzte Kiste voll. (Drücke das Ergebnis als
Zahl zwischen 0 und 1 aus. 1 entspricht 100%)
Besonders bei der letzten Aufgabe werden dir ein paar
Zahlenwerte sehr bekannt vorkommen.
jochen wrote:
> also>> 5115 / 1024 = 4 Rest 1019>> die 4 hab ich und den Rest hab ich auch. Aber jetzt müsste ich den Rest> noch so verarbeiten, dass ich eine 9 auf die Anzeige bekomme.> Das bekomm ich leider nicht gelöst. Wie macht man es?
Wie macht man das dezimal und schriftlich (ohne Taschenrechner)?
Man setzt in Ergebnis ein Komme, holt sich eine Null hinter dem
(fiktiven) Komma des Dividenden herunter und rechnet wie gehabt weiter.
Die bessere Lösung ist allerdings, Divisionen auf dem AVR zu vermeiden
(geht aber nicht immer).
> Hannes, deine Lösungsidee gefällt mir sehr gut, aber den Code im Anhang> versteh ich mal überhaupt garnicht.
Das ist eine Routine zur Umwandlung eines 16-Bit Zahlenwertes (also den
Inhalt zweier Register) in ASCII-Ziffern. Dies geschieht durch
(getürkte) Division durch 10000, 1000, 100 und 10, der Rest ergibt die
Einer. Getürkt deshalb, weil eine Division ja eigentlich nur eine
fortgesetzte Subtraktion ist. Statt
"wieviel ist 90 durch 10?"
kann man ja auch formulieren
"wie oft kann ich von 90 10 subtrahieren, ohne einen Unterlauf zu
erreichen?"
Diese Routine arbeitet allerdings vorwärts und rückwärts, das ich mir
mal bei PeDa abgeschaut habe. Um sie zu verstehen, solltest Du sie in
ein Programm einbinden und im Simulator des AVR-Studios durchspielen.
Beim Skalieren von Werten zur Ausgabe gehe ich meist so vor:
- Ermitteln, welche Werte anfallen können (beim ADC 0..255 oder 0..1023)
- Festlegen, was angezeigt werden soll (bei Dir 0,00..9,99, wobei 9,99
ja nie erreicht wird)
- Festlegen, was bei maximalem Eingangswert angezeigt werden soll
(Skalierung)
Bei Dir würde 1023 am Eingang knapp 5,00 (also 500) an der Anzeige
erzeugen müssen. Du musst also 1024 auf 500 skalieren. Divisionen durch
"krumme Zahlen" sollen dabei vermieden werden, es sollte möglichst nur
durch 256 (1 Byte) oder 65536 (2 Bytes) dividiert werden.
Zum Skalieren muss der Eingangswert mit einem Bruch multipliziert
werden, bei dem der Nenner (wegen der leichteren Division) 256 oder
65536 beträgt.
Nehmen wir erstmal 256 als Nenner an. Dann muss unsere als Ergebnis
gewünschte Zahl bei der Betrachtung erstmal mit 256 multipliziert werden
(500 x 256 = 128000), denn wir wollen sie ja im AVR durch 256 teilen.
Und nun soll 1023 am Eingang 128000 ergeben. Dazu muss der Eingangswert
mit 125 multipliziert werden, denn 128000 durch 1023 ergibt 125,122,
also 125. Unser Bruch zur Skalierung heißt also 125/256. Also
multiplizieren wir den Messwert mit 125 und teilen ihn durch 256 (indem
wir das untere Byte wegwerfen). Vor dem Teilen sollten wir aber runden.
Wie rundet man dezimal und schriftlich?
Man überprüft den Rest und entscheidet danach, ob man das Ergebnis um 1
erhöht. Mann kann aber auch vor dem Dividieren die Hälfte des Divisors
zum Dividenden addieren, das rundet genauso.
Die einfachste Möglichkeit zum Runden ist also das Addieren von 128 zum
24-Bit-Zwischenergebnis. Bei guter Vorbereitung (das Vorhandensein eines
unteren Registers namens null mit dem Inhalt 0 und eines verwendbaren
oberen Registers) ist das ganz simpel und kostet ganze 4 Takte:
ldi tmp,128
add byte0,tmp
adc byte1,null
adc byte2,null
Fertig... - Byte1 und Byte2 werden dann der Integer-zu-ASCII-Routine zum
Fraß vorgeworfen, die daraus Ziffern mit eingeschobenem Komma macht,
Byte0 wird weggeworfen.
...
Hannes, ich hoffe du hast nichts dagegen wenn ich mir deinen Weg nochmal
durch den Kopf gehen alsse und bei Fragen einen neuen Beitrag eröffne.
Dieser hier wird was unübersichtlich.
Auf fertige Routinen zurückgreifen möchte ich nicht, ich möchte es
verstehen.
Ich habe jetzt aber noch eine Frage zu dem alten Weg.
Wie oben geschrieben wurde, rechne ich nun (1019 / 1024) * 10, dann hab
ich vor dem Komma endlich die 9 stehen.
1019 war 1111111011 wenn man das jetzt durch 1024 teilt, verschiebt man
diese Zahl um 10 Stellen (vom Komma) nach rechts. Man erhält also wieder
1111111011 wobei man sich davor ein 0, denkt.
Die Multiplikation mit der 10 habe ich hinbekommen. Dabei habe ich das
0, vernachlässigt und nur den Ausdruck 1111111011 mit 10 multipliziert.
Ich habe das mal schriftlich auf dem Papier gemacht und erhalte als
Ergebnis
10011111001110. Das komma war nach der 8. Stelle von rechts man hat also
1001,1111001110 und vor dem Komma die Zahl 9.
In Assembler sieht es bei mir nun so aus, dass ich die Zahl
1001,1111001110 ohne das Komma in verschiedenen Registern als
r21= 10011111 und r22=00111000 habe. r22 brauche ich nicht mehr und r21
schiebe ich um 4 Stellen nach rechts.
Ok so?
Ich komme aber leider nicht auf die Zahl 1019. Sie entsteht ja als Rest
beid er Division von 5115 durch 1024. Wie aber mache ich das:
000000000001001111111011 ist die Zahl 5115. Wie gesagt wurde, dividiert
man durch 1024, indem man sich ein Komma nach der 10. Stelle von rechts
denkt. Das wäre also
00000000000100, 1111111011
und das Ziel ist es 3 Register zu haben:
erste Register: hier ist die vier vor dem Komma drin: 00000100
zweite Register: hier ist der erste Teil nach dem Komma drin: 11111110
dritte Register: hier sind die letzten beiden Stellen nach dem Komma
drin: 11000000
Wie mache ich diese Aufteilung? Ist der Rest von Weg so okay?
Ich habe es mit dem lsr und dem ror Befehl hinbekommen.
Puhh jetzt denke ich kann ich meine 4,9 auf die Segmentanzeige bringen
morgen versuche ich es. Ich bedanke mich bei allen, die mir geholfen
haben!
Alles klar, das funktioniert einwandfrei, danke nochmal :-)
Es bleibt allerdings das Problem,d ass der AD Wandler an sich manchmal
einfach nicht einliest, wenn ich PC0 auf 5 V lege.
Woran kann so etwas liegen?
GND und AVCC hab ich en die Stromversorgung angeschlossen und zwischen
den beiden einen 100N kondensator. A Ref habe ich nicht beschaltet, wozu
ist das da?
Also er liest nur sehr unzuverlässig ein.
jochen wrote:
> A Ref habe ich nicht beschaltet, wozu> ist das da?
Dort schiebt der Chip die benutzte Referenzspannung raus, damit
der geneigte Elektroniker Massnahmen ergreifen kann, um die
Referenzspannung seinen Anforderungen gemäss zu stabilisieren.
Du solltest ARef als Minimumbeschaltung mit 100nF nach GND
abblocken.
Steht aber auch alles im Datenblatt oder alternativ auch
im AVR-Tutorial
Hab ich jetzt gemacht, das Problem sit aber immer noch nicht so recht
behoben. Wenn es dann nicht geht und ich PC0 dann mit 9V verbinde geht
es kurz danach auch mit 5 V. Das scheint also das Problem kurzzeitig zu
beheben aber das ist ja keine Lösung.
> Wenn es dann nicht geht und ich PC0 dann mit 9V
9V ?!?
Laut Datenblatt darfst du maximal 5.5V draufgeben.
Hast du noch einen zweiten Mega8? Wenn ja: probier den
mal aus.
Hallo,
Du solltest vielleicht mal ins Datenblatt des AVR schauen. Die maximal
zulässige Spannung an allen Eingängen eines AVR liegt nur knapp über
seiner Betriebsspannung. Darüber wird die interne Schutzdiode leitend,
die darf maximal mit 1mA belastet werden.
Dein Verfahren hat also große Chancen, den armen AVR in den
Halbleiterhimmel zu befördern...
Gruß aus Berlin
Michael
> Es bleibt allerdings das Problem,d ass der AD Wandler an sich manchmal> einfach nicht einliest, wenn ich PC0 auf 5 V lege.
Welchen Wert kriegst du den, wenn du dir mal die Werte direkt
vom ADC ausgeben lässt.
wie gesagt, manchmal zeigt sie auch den korrekten Wert 3 an aber da muss
ich schon was an der Sache wackeln und vorher mal auf 9 V legen.
Evtl. ist er dadurch beschädigt worden?
Entweder du hast einen Wackelkontakt oder du hast den
Mega8 geschossen.
(Reden wir eh vom selben: der Wert wird ausgegeben so wie
er vom ADC kommt, ohne Umrechnung oder Sonstiges was zusätzlich
fehlerhaft sein könnte. Die Ausgaberoutine steht ausserhalb
jeglichen Zweifels?)
Ja, die habe ich testweise mal weggelassen und nur das folgende Programm
ganz vom Anfang drauf gespielt. Das haben wir oben ja erarbeitet und
sollte die minimale Funktionsweise sein:
.include "m8def.inc"
.def temp = r16
.def temp1=r17
.def adlow =r20
.def adhigh=r21
.org 0x0000
rjmp main
ldi temp1,(1<<REFS0)
out ADMUX, temp1
ldi temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1)| (1<<ADPS0)
out ADCSRA, temp1
main:
ldi temp, LOW(RAMEND) ;Stackpointer initalisieren
out SPL, temp
ldi temp, HIGH(RAMEnD)
out SPH, temp
sbi DDRB,0
sbi ddrB,1
sbi ddrB,2
sbi ddrB,3
ldi r22, 9
sample_adc:
sbi ADCSRA, ADSC
wait_adc:
sbic ADCSRA, ADSC
rjmp wait_adc
in adlow,ADCL
in adhigh, ADCH
loop:
out PORTB, adhigh
rjmp sample_adc
Wann wird der ADC denn nun initialisiert???
> Da wirst du wohl den µc gegrillt haben.
Das kommt mit hoher Wahrscheinlichkeit dazu. 9V am EDC-Eingang, der
Gedanke ist schon sehr schmerzhaft, nicht nur für den AVR... ;-)
Gruß von der Elbe...
Hannes
Hannes Lux wrote:
> Karl heinz Buchegger wrote:>> Das Programm sieht an und für sich gut aus.>> Das sehe ich anders, sorry...>> Wann wird der ADC denn nun initialisiert???
Ooops. Das hab ich ja völlig übersehen.
Ich hab mich nur auf die Werte in den Registern
konzentriert.
Ist schon gut wenn mehr Augenpaare ein Programm absuchen.
Karl heinz Buchegger wrote:
> Ist schon gut wenn mehr Augenpaare ein Programm absuchen.
Nunja, mit ist halt aufgefallen, dass das recht "komische
Interrupt-Vektoren" sind, darauf habe ich den Rest gar nicht mehr
angesehen und entschieden, erstmal nicht darauf zu antworten. Aber Dein
versehentliches "Absegnen" wollte und konnte ich so leider nicht stehen
lassen.
Übrigens: Ein Programm, das 7-Segment-Anzeigen multiplext, ADC-Eingänge
abfragt und vermutlich später mal noch andere Dinge tun soll, kann ich
mir ohne Timer-Interrupt gar nicht mehr vorstellen.
...
also es klappt auch mit einem neuen AVR nicht. Den Rest habe ich sicher
richtig angeschlossen. Muss ein Widerstand vom AD Eingang auf Masswe?
ich habe 1 kohm, 10 kohm und 100 ohm mal versucht, das ändert alles aber
nicht viel.
Kann es vielleicht daran liegen, dass es nur auf dem Steckbrett
aufgebaut ist?
jochen wrote:
> ich habe das aus dem Tutorial übernommen und wollte das erstmal als> gegeben hinnehmen.
Tortzdem hast du einen Fehler eingebaut.
Hannes hat ihn gesehen.
Wann wird eigentlich der Programmteil
jemals ausgeführt?
davor steht ein
rjmp main
und das Label main ist direkt hinter diesem Programmteil.
Ergo -> der ADC ist nie richtig initialisiert worden.
jochen wrote:
> Ja, jetzt, wenn ich das rjmp main entferne funktioniert es wie> gewünscht. Herzlichen Dank!
Das war die falsche Problemlösung :-)
Denk darüber nach, warum ich wohl zu dieser
Aussage komme.
Ja ich hätte vorher einmal im Schritt für Schritt simulieren können und
hätte spätestens dann gesehen, dass direkt zu main gesprungen wird.
Ich werde das nächste mal bevor ich poste auch soetwas machen.
Das meine ich nicht.
Was ich meine ist:
Jedes (!) Assembler Programm beginnt immer mit
einem Sprung zu main.
Ausser die ganze einfachen ersten beiden für die Anfänger.
Nach main erfolgt als aller erstes immer die Initialisierung
des Stack Pointers. Dadurch stehen ab da dann Unterprogramm
Aufrufe und Interrupt Aufrufe zur Verfügung, ohne das etwas
Schlimmes passiert.
Danach erfolgt die Initialisierung des Rests.
Das können CPU Register sein, das kann Hardware sein,
das können SRAM Zellen sein. Was auch immer.
Halte dich an dieses Schema, und du hast weniger Probleme.
Und jetzt schau mal ob das Ergebnis deiner Problemlösung
in dieses Raster passt.
Danke Karl Heinz.
Dann lasse ich rjmp main stehen und schreibe
ldi temp1,(1<<REFS0)
out ADMUX, temp1
ldi temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1)| (1<<ADPS0)
out ADCSRA, temp1
nachdem der Stackpointer eingestellt wurde.
Als nächstes schau ich mir die Routine von hannes mal an, die scheint
noch besser zu sein als
z.B.
(1019 / 1024) * 10 zu rechnen und so die Zahl vor dem Komma als die
Nachkommatelle der Gesamtzahl zu sehen.
Dann hab ich nämlich nur 4,9 stehen und das ist ja nicht 5, der
eigentlich richtige Wert.
Ich melde mich,falls es Frageb geben sollte, dann aber in einem neuen
Beitrag.
EInen schönen Tag noch
jochen wrote:
> Ja, jetzt, wenn ich das rjmp main entferne funktioniert es wie> gewünscht. Herzlichen Dank!
Fazit:
"RJMP" ist schuld, man sollte RJMP meide wie die Pest...
Hmmm, ääähhh, oder vielleicht doch nicht?
Jochen, es bringt nix, mit Copy und Paste programmieren zu wollen. Da
kommt nur Mist raus. Du musst Dir angewöhnen, den Programmcode auch zu
verstehen. Dazu gehört, dass Du zu jeder Programmzeile ganz genau weißt,
was sie bewirkt, warum Du das so und nicht anders machst und warum sie
an genau dieser Stelle in der Reihenfolge der Anweisungen steht. Das
gilt für selbsterdachten Code genauso wie für "gefundenen" Code.
Ich nutze auch diesen oder jenen Algorithmus, den ich nicht selbst
erdacht habe, sondern den ich irgendwo "gefunden" habe. Aber ich
verwende ihn erst, wenn ich ihn genau verstanden habe.
Auch ich mache Fehler beim Programmieren, mehr als Du vielleicht
glaubst. Aber ich versuche systematisch die Ursache des Fehlverhaltens
des Programms aufzuspüren, wobei ich auch mal ins Datenblatt oder in
andere Quellen schaue, um mich zu informieren. Es gibt viele Dinge beim
AVR, über die ich nicht detailliert bescheid weiß, damit belaste ich
mich momentan auch gar nicht, ich informiere mich aber dann umfassend,
wenn ich Neuland betrete, also wenn ich ein Feature (oder
Peripheriebaustein) erstmalig benutze. Das ist zwar etwas mühsamer und
auch langwieriger als das unverstandene Bebutzen fremder Routinen oder
das unüberlegte Befragen eines Forums, aber es ist ehrlicher und fördert
das Verständnis für das was man tut.
...
Danke für die Tipps.
Also ich greife nicht gerne auf fertige Sachen zurück und möchte auch
alles selber verstehen. Aber so Sachen wie die Initalisierung des Stack
Pointers oder auch des AD Wandlers ist mir momentan egal. Also jetzt
reinweg die Initalisierung betrachtet. Ich würde es zwar gerne
verstehen, ich habe jedoch keinerlei Bezugsquellen und im Internet finde
ich auch nichts. Deswegen belasse ich es jetzt erstmal dabei und mache
lieber was produktives, anstatt mich mit einer Initalisierung zu
befassen. Für das was ich machen will reicht es mir ja erst einmal,
wenn der AD Wandler zur Verfügung steht, wie kann ich aus Zeitgründen
erstmal nicht erarbeiten. Und wenn ich was wie die Pest hasse, sind das
Datenblätter bzw. die Art und Weise, wie dort etwas beschrieben wird.
Ich finde auch keinerlei gute Literatur. Deswegen habe ich mir das my
Avr Starterset für satte 200 Euro gekauft. Das hat mir zwar was die
allerersten Schritte angeht viel geholfen, stößt aber meiner Meinung
nach auch schnell an seine Grenzen, zumal das Programm Sisy, was dort
verwendet wird, nicht so weit verbreitet scheint.
Deswegen würde mich es sehr interessieren, wie ihr angefangen habt,
euch damit zu befassen und woher ihr Eure Informationen erhalten habt.
Ich finde die Sachen an sich sind garnicht schwer, das schwere ist es
einmal eine fundierte Beschreibung zu erhalten. Wenn man die dann
durcharbeitet ist es klar und man wundert sich, wie einfach es doch ist.
So ging es mir jedenfalls bisher bei dem, was ich gelernt habe. Und
klar, man denkt dann als "Insider": "was stellt der denn für blöde
Fragen". Aber wie beschrieben ich habe halt keine gerechten Quellen und
irgendwoher muss man seine Informationen ja bekmmen
Könntet ihr mir Bücher empfehlen?
P.S. Das Tutorial in allen Ehren es hat mir eucht bei vielen Sachen
geholfen.
Aber was den AD Wandler angeht konnte ich es fast nicht brauchen, dort
wurde verwirrenderweise nicht reinweg der AD Wandler beschrieben sondern
noch viel mehr gleich mit und der nur auf den AD Wandler beziehende CODE
(wie "Gast" auch kanz zu Anfang hier in diesem Beitrag meinte) wird
nicht offen sichtlich.
Aber evtl ist das Tutorial ja auch nicht für absolute Neulinge gedacht
und die Kritik ist nicht berechtigt.
jochen wrote:
> Danke für die Tipps.> Also ich greife nicht gerne auf fertige Sachen zurück und möchte auch> alles selber verstehen. Aber so Sachen wie die Initalisierung des Stack> Pointers
Wieso? - Wo ist das Problem? Du musst erstmal verstehen, was Stack ist
und wozu man ihn braucht. Es ist ein als "Stapelspeicher" genutzter Teil
des RAMs, in dem Rücksprungadressen bei Aufruf von Unterprogrammen und
Interrupts gesichert werden und den man auch benutzen kann, um mal
schnell den Inhalt eines Registers zu "parken" (push/pop), damit man das
Register temporär für andere Zwecke frei hat. Vergleiche den Stack mit
einer Art Ablage für Zettel, die so gebaut ist, dass Du immer nur den
zuletzt reingelegten Zettel rausnehmen kannst. Der Stackpointer ist der
Zeiger auf die gerade aktuelle Stack-Adresse im RAM. Er muss zu Beginn
des Programms auf das RAM-Ende gesetzt werden, da der Stack "nach unten
wächst".
> oder auch des AD Wandlers ist mir momentan egal.
Der AD-Wandler ist ansich extrem primitiv. Er arbeitet nach dem Prinzip
der schrittweisen Annäherung. Dabei wird die außen anliegende Spannung
per Sample&hold-Stufe vor Veränderung während der Messung geschützt und
dann schrittweise mit der Spannung einres internen DAC
(Digital-Analog-Converters) verglichen, der die Referenzspannung in 1024
Stufen zerhacken kann. Dabei wird im ersten Schritt geprüft, ob die
externe Spannung größer oder kleiner als die Hälfte der Referenzspannung
ist. Anhand des Ergebnisses wird entschieden, ob im nächsten Schritt auf
die Hälfte des oberen oder unteren Teils geprüft wird. Und so hangelt
sich dieser Klapperatismus vom höchsten bis zum niedrigsten Bit durch.
Dazu braucht er natürlich einen Takt, den man (als Initialisierung) per
Vorteiler einstellen muss. Und damit man diesen ADC effizient nutzen
kann, gibt es einige Schalter für bestimmte Betriebsarten, einen
Multiplexer zur Auswahl der Referenzquelle und Messquelle und eine
Zustands-Anzeige, die in der Lage ist, einen Interrupt auszulösen. Im
einfachsten Fall schaltet man den ADC im Free-Run-Mode ein (aden,
adfr/adate, adpsx) lässt ihn klappern (adsc) und liest gelegentlich
(dann wenn man es braucht) mal den zuletzt ermittelten Wert aus adch und
adcl aus. Man muss nur sicherstellen, dass man erst dann ausliest, wenn
er genug Zeit hatte, eine Wandlung zu schaffen.
> Also jetzt> reinweg die Initalisierung betrachtet. Ich würde es zwar gerne> verstehen, ich habe jedoch keinerlei Bezugsquellen und im Internet finde> ich auch nichts.
Die QAuelle heißt Datenblatt.
> Deswegen belasse ich es jetzt erstmal dabei und mache> lieber was produktives, anstatt mich mit einer Initalisierung zu> befassen.
Das ist keine gute Idee, dabei lernst Du nichts. Du kannst keinen Roman
schreiben wenn Du das Alphabet nicht kennst.
> Für das was ich machen will reicht es mir ja erst einmal,> wenn der AD Wandler zur Verfügung steht, wie kann ich aus Zeitgründen> erstmal nicht erarbeiten. Und wenn ich was wie die Pest hasse, sind das> Datenblätter bzw. die Art und Weise, wie dort etwas beschrieben wird.
Das musst Du umgehend ändern. Datenblätter sind die wichtigste Quelle
für Informationen. Als nächstes kommen die AppNotes
(Anwendungsbeispiele).
> Ich finde auch keinerlei gute Literatur. Deswegen habe ich mir das my> Avr Starterset für satte 200 Euro gekauft.
Gut gemacht, diese Firma will auch leben. Trotzdem ziehe ich das
Original (AVR-Studio und ATMEL-Datenblätter) vor.
> Das hat mir zwar was die> allerersten Schritte angeht viel geholfen, stößt aber meiner Meinung> nach auch schnell an seine Grenzen, zumal das Programm Sisy, was dort> verwendet wird, nicht so weit verbreitet scheint.
Das Programm braucht eigentlich niemand. Im AVR-Studio ist alles drin,
was man für Assembler braucht. Und statt des modifizierten
AN910-Programmers von Sisy (mySmartUSB) sollte man lieber den AVR-ISP
(MKII) benutzen, da kann man wenigstens sicher sein, dass es dafür ein
Firmwareupdate gibt, wenn neue AVR-Typen auf den Markt kommen.
> Deswegen würde mich es sehr interessieren, wie ihr angefangen habt,> euch damit zu befassen und woher ihr Eure Informationen erhalten habt.
Man hat mich vor ein paar Jahren gebeten, eine Schaltung zu bauen, die
durch den Einsatz eines AVRs bedeutend einfacher wird (Platine,
Logikbausteine). Also habe ich mir ein paar AT90S1200 gekauft, mir eine
ATMEL-AVR-CD besorgt und mich mühsam eingelesen. Internet-Zugang und
Forum kam erst später. Einige meiner (anfangs recht primitiven) Projekte
kannst Du Dir hier gern ansehen: http://www.hanneslux.de/avr/index.html> Ich finde die Sachen an sich sind garnicht schwer, das schwere ist es> einmal eine fundierte Beschreibung zu erhalten.
Nein, diese (mundgerechte) Beschreibung wirst Du nicht finden. Das
Wissen (die Informationen) sind wie Puzzleteile verstreut. Du musst sie
schon selbst zusammenfinden (ich habe bewusst das Wort "suchen"
vermieden) und zusammenfügen. Das ist zwar mühsam und dauert seine Zeit,
aber "ohne Fleiß kein Preis". Dazu muss das neu gefundene immer mit dem
bereits Gelernten verglichen und verknüpft werden. Daher auch meine
Hinweise auf "Grundschulwissen". Du hast fast alles schonmasl in anderem
Zusammenhang gelernt, mehr oder weniger motiviert, mehr oder weniger
fleißig, mehr oder weniger ehrlich. Und diese Schummeleien (gute Noten
für unverstandenen Lernstoff) rächen sich jetzt.
> Wenn man die dann> durcharbeitet ist es klar und man wundert sich, wie einfach es doch ist.
Du kannst doch aber nicht erwarten, dass Dir Andere alles mundgerecht
zusammentragen. Wissen muss man erarbeiten, der "Nürnberger Trichter"
funktioniert nunmal nicht. Ich habe auch die Erfahrung gemacht, dass man
einer einzigen Wissensquelle nicht trauen kann. Der Autor ist auch nur
ein Mensch und Menschen irren sich gelegentlich. Man muss also immer
mehrere Wissensquellen gegeneinander überprüfen und sich seine eigene
Meinung bilden.
> So ging es mir jedenfalls bisher bei dem, was ich gelernt habe. Und> klar, man denkt dann als "Insider": "was stellt der denn für blöde> Fragen".
Neenee, das ist meist anders. Oft stellt man beim Lesen der fragen fest
dass der Hilfesuchende das Problem falsch einschätzt. Dabei ist bei
Anfängern oft Selbstüberschätzung im Spiel. Die reale Welt ist nunmal
erheblich komplexer als sie in Lehrbüchern dargestellt ist. Es fehlen
also meist elementare Grundlagen.
> Aber wie beschrieben ich habe halt keine gerechten Quellen und> irgendwoher muss man seine Informationen ja bekmmen
Du wirst keine (mund-)gerechten Quellen finden. Denn jeder Lernende
braucht das etwas anders, der Eine "kopiert" das Wissen (das
Geschriebene), der Andere versteht es und macht es sich zu Eigen,
verknüpft es also mit dem zuvor erworbenen Wissen und kommt zu
Erkenntnissen, die in keiner dieser gelesenen Quellen beschrieben
wurden.
> Könntet ihr mir Bücher empfehlen?
Eigentlich nicht. Ich könnte Dir für ein/zwei Monate das Elektor-Buch
"AVR-Mikrocontroller-Praxis" von S&F Volpe leihen, das beschreibt den
AVR-ASM-Befehlssatz auf Deutschnd enthält ein paar Programmbeispiele mit
Erklärungen. Aber der echte Bringer ist das auch nicht...
> P.S. Das Tutorial in allen Ehren es hat mir eucht bei vielen Sachen> geholfen.
Ein Tutorial kann nur die ersten Schritte begleiten und vor den ersten
Fallstricken bzw. Fußangeln warnen. Unter diesem Aspekt ist das Tutorial
sehr gut gemacht. Man sollte aber in der Lage sein, das Wissen
verschiedener Quellen zu verknüpfen, wer das Tut nur "nachäfft", der
lernt daraus auch nichts.
> Aber was den AD Wandler angeht konnte ich es fast nicht brauchen, dort> wurde verwirrenderweise nicht reinweg der AD Wandler beschrieben sondern> noch viel mehr gleich mit und der nur auf den AD Wandler beziehende CODE> (wie "Gast" auch kanz zu Anfang hier in diesem Beitrag meinte) wird> nicht offen sichtlich.
Das ist jetzt aber unfair. Der Umgang mit dem ADC ist doch kein
Selbstzweck. 99% der ADC-Arbeit besteht aus Warten, die reinen
ADC-Zugriffe sind die Initialisierung und das Auslesen von ADCL und
ADCH. Der Rest des Tut-Programms zeigt die Verarbeitung des eingelesenen
ADC-Wertes. Gut, zugegeben, ich würde das etwas anders organisieren,
aber das Programm ist korrekt und zeigt, wie es funktioniert.
> Aber evtl ist das Tutorial ja auch nicht für absolute Neulinge gedacht> und die Kritik ist nicht berechtigt.
Doch, das Tutorial ist für Einsteiger gedacht. Allerdings setzt man beim
Mikrocontroller-Einsteiger voraus, dass er bereits Ahnung von
allgemeiner Elektronik hat, speziell von Digitaltechnik (TTL- oder
CMOS-Logikschaltungen), dass er weiß was AND, OR, EXOR ist und dass er
mit Bits, Bytes und deren Verknüpfereien Bescheid weiß. Die
Mikrocontroller-Technik ist also nicht der Anfang der
Elektronikbastelei, sondern eher die fortgeschrittene Abteilung. Und man
sollte einen Weg mit dem ersten Schritt beginnen und nicht mit dem
letzten.
...
> Doch, das Tutorial ist für Einsteiger gedacht.> Allerdings setzt man beim> Mikrocontroller-Einsteiger voraus,> dass er bereits Ahnung von> allgemeiner Elektronik hat
Und vor allem wird vorausgesetzt, daß man das Tutorial Schritt für
Schritt durcharbeitet und nicht mittendrin anfängt.
Hannes Lux wrote:
> Man hat mich vor ein paar Jahren gebeten, eine Schaltung zu bauen, die> durch den Einsatz eines AVRs bedeutend einfacher wird (Platine,> Logikbausteine). Also habe ich mir ein paar AT90S1200 gekauft, mir eine> ATMEL-AVR-CD besorgt und mich mühsam eingelesen. Internet-Zugang und> Forum kam erst später. Einige meiner (anfangs recht primitiven) Projekte> kannst Du Dir hier gern ansehen: http://www.hanneslux.de/avr/index.html
echt? Woher hast du denn den AT90S1200 und die CD gekauft, wenn nicht
übers Internet?
WAS? Ihr habt einen lokalen Elektronik Händler?! Unfassbar ;)
Der letzte der hier in der Umgebung war, kam mit seinem Lämpchen,
Schalterchen und kilometerweise Kupferlackdraht nicht so weit. Wenn man
schon (halbwegs) komplexe ICs haben wollte.. No chance. Tja das war wohl
sein Verderben.
Aber Widerstände und Elkos bekam man dort trotzdem.
>WAS? Ihr habt einen lokalen Elektronik Händler?! Unfassbar ;)
Wir haben auch einen freu!
Der (und seine Mitarbeiter) haben echt Ahnung und bestellen auf wunsch
alles machbare! Der hält sich auch schon seit 30 Jahren! Nicht ohne
Grund... :)
Hallo,
@Simon Küppers: Brief, Zeitschriften und Telefon gab es schon vor dem
Internet und CD-Rom...
Inserate bestanden da oft noch aus ziemlich langen Bauteillisten mit
Preisen, nicht nur einer unsinnig bunten Seite, die ein schnelleres
Internet mit einem Pentiom-III versprach.
Da konnte man anrufen und bestellen oder hinschreiben (ja, das ging
wirklich!).
Lokale kleine Elektronik-Händler waren da auch merklich weiter
verbreitet. :)
Allerdings sehe ich im Internet manchmal auch einen Nachteil: man findet
manchmal zu schnell jemanden, der ein Problem schon gelöst, eine
Schaltung schon entwickelt oder ein Programm schon geschrieben hat.
So wird sicher mehr relativ gedankelos nachgebaut ohne am Verständnis
der Zusammenhänge sonderlich interessiert zu sein.
Empfinde ich selbst nicht unbedingt als großen Vorteil.
Gruß aus Berlin
Michael
Hi
>echt? Woher hast du denn den AT90S1200 und die CD gekauft, wenn nicht
übers Internet?
Zum Informieren gibt es Bücher , Zeitschriften und Kataloge (die sollen
sogar Offline funktionieren). Zum Bestellen gibt so ein altmodisches
Teil mit etwas,das man an Ohr und Mund hält und einenem anderen Etwas
mit dem man eine Nummer wählen kann. Wenn man dann noch einer Sprache
mächtig ist, die der oder die am anderen Ende versteht, geht das auch
ohne Internet.
MfG Spess
@Simon Küppers:
Ich bin seit 1990 (oder 91?) Kunde bei Reichelt. Anfangs wurde per Brief
bestellt, gelegentlich per Fax, seit etwa 1995 per CB-Funk. Ja, richtig
gelesen, per CB-Funk in der Betriebsart Packet-Radio (1200 Baud) auf
Kanal 24 oder 25. Dazu wurde einfach eine PR-Mail (Textdatei, ASCII) in
die lokale Box geschrieben, an einen Internet-Gateway (dbo812,
München-Pasing) gesendet, die dann von diesem als E-Mail weitergesendet
wurde. Das funktionierte auch rückwärts. Dieses gut funktionierende
anarchistische Netz wurde leider etwa 2002 von einigen
besserwisserischen Möchtegern-Administratoren durch den Machtkampf
konkurrierender (sich bekämpfender) Vereine zerschlagen. Die Zunahme der
Sonnenfleckenaktivität (11-Jahres-Zyklus) und die Verbreitung des
Internets erledigte dann den Rest.
Meine Funktechnik ist inzwischen abgebaut, die PR-Software (Mailbox mit
S&F, Gateway Kanal 24 <--> 25, Terminalsoft) befindet sich aber noch auf
meinem Fräsen-Rechner.
Aber zwei Elektronikläden hatten wir in Magdeburg auch, sie sollen sogar
noch existieren. Ich war da aber schon lange nicht mehr, habe auch gar
nicht mitbekommen, wohin die umgezogen sind.
...
Interessant eure Beiträge. Klar gibt es auch Kataloge wo man
hinfaxen/anrufen/post hinschicken kann. Aber ich zum Beispiel wäre ohne
das Internet garnicht erst auf Reichelt, csd und und und gekommen...
Aber ich denke mal, die Adressen von solchen Shops stehen/standen in
diversen Elektronikmagazinen (die ja damals fast jeder Elektroniker
hatte, da sie noch was taugten). NichtOder? ;)
Simon Küppers wrote:
> Interessant eure Beiträge. Klar gibt es auch Kataloge wo man> hinfaxen/anrufen/post hinschicken kann. Aber ich zum Beispiel wäre ohne> das Internet garnicht erst auf Reichelt, csd und und und gekommen...>> Aber ich denke mal, die Adressen von solchen Shops stehen/standen in> diversen Elektronikmagazinen (die ja damals fast jeder Elektroniker> hatte, da sie noch was taugten). NichtOder? ;)
Nein, Reichelt war damals ein "Geheimtipp", Völkner (Braunschweig) und
Conrad machten sich durch aggressive Werbung bekannt, Pollin und CSD kam
erst später.
Elektronik-Magazine las ich nie wirklich. Den "Funkamateur" bekam ich
vor der Wende nicht abonniert (da gab es Kontingente), nach der Wende
wollte ich ihn aus Gnatz nicht mehr. Meine E-Grundlagen habe ich
allerdings aus der reichlichen Bastler-Literatur des DMV.
...