hat jmd zu dem thema informationen, links. da ich nun den wert vom adc einer tabelle zuordnen mag sodass er mir dann die temperatur letztendlich schreibt die werte für die tabelle sind atm uninteressant. also meine bisherige recherche ergab das ich am anfang die anfangsadresse der tabelle setze und dann immer den wert den der adc ausließt dazuzählt. somit dann in der richtigen zelle ist (diesen Wert ausließt und meinetwegen in ein register ausgibt) aber wie kommt er in die richtige zelle er muss ja spalte und zeile auswählen. ich würde mich über ein bspprog freuen gruß Peter PS: Programmierung erfolgt in Assembler (AVR-Studio 4), Microcontroller wird der atmega8 verwendet
Stimmt, vielleicht waere es einfacher wenn der OP in Englisch schreibt. Schliesslich koennen ja fast alle die sich mit Etechnik beschaeftigen auch Englisch und es ist ja auch keine Schande wenn man als Auslaender noch kein Deutsch kann. Olaf
hm wo hast probleme was verstehst net, ich erkläre gern genauer. die grundproblematik: ich habe ein poti am adc Port eines Atmega8 hängen kann die register ADCL ADCH schon wunderbar auslesen und auf ein lcd ausgeben (binär). und nun möchte ich eine Datenbank anlegen die zu jedem Wert den der ADC Port liefert einen bestimmten Datensatz besitzt. und dieser Datensatz soll dann in ein register geschrieben werden und später auf dem lcd ausgegebn werden. ADC bekommt signal ---> atmega8 schaut nach Datensatz ---> schreibt den passenden Datensatz in ein Register ----> atmega8 gibt dieses register auf ein LCD aus ---> ich bin zufrieden gruß peter
Tja, ein bisschen mehr Mühe mit Grammatik, Rechtschreibung (Deine Shift-Taste scheint Ausfallerscheinungen zu haben) und Formulierung solltest Du Dir schon geben. Ich weiß nicht, ob Du Dir vorstellen kannst, dass es einem eventuell vorbeischlendernden Hilfswilligen absolut keinen Spaß macht, sich das Geschreibsel überhaupt durchzulesen...
Es tut mir leid, ich bin es vom Chatten so gewöhnt und schreibe meistens ohne Punkt, Kommata und alles klein wenn ich im Internet unterwegs bin. Aber ich werde mich bemühen. gruß Peter
Du meinst also 'indirekte Adressierung' bzw. eine Lookup-Table. Was verstehst Du unter 'Datensatz'? Wie viele Werte sollen da pro Index abgelegt sein?
ich denke ein Wert pro Index würde für den Anfang erstmal reichen, um zu lernen wie so eine "Lookup-Tabelle funktioniert. @ jonny m. (wie du aus meinem letzten Thread weißt, bin ich noch blutiger Anfänger und muss noch sehr viel lernen)
So richtig verstanden habe ich dich immer noch nicht. Möchtest du jedem ADC-Kanal einen Platz im Array reservieren und die Augenblickswerte der Eingänge an verschiedenen Positionen des LCDs anzeigen? Möchtest du nur einen ADC-Kanal abfragen und die Werte in zeitlicher Reihenfolge im Array (Tabelle) ablegen, um Tendenzen zu erkennen? Möchtest du nur einen ADC-Kanal abfragen und dessen Wert am LCD ausgeben? (dann brauchst du keine Tabelle/Array) Dann würde sich eine Mittelwertbildung anbieten, um die Anzeige etwas zu beruhigen. Zum Deutsch: Es ist schwer, solches Kauderwelsch zu lesen, die Hilfsbereitschaft sinkt dadurch kollossal. Schlimmer jedoch ist, dass man dadurch die Zusammenhänge nicht erkennt und nicht versteht, was du meinst. Rechtschreibung und Grammatik helfen bei der Strukturierung der Sätze und schaffen die Möglichkeit, Zusammenhänge eindeutig und unmissverständlich zu beschreiben. Gelegentlich passierende Rechtschreibfehler oder Buchstabendreher kritisiere ich ausdrücklich nicht, das passiert Jedem mal. Aber wenn man Hilfe möchte, sollte man schon vernünftige, unmissverständliche Sätze schreiben. ...
> ...zu jedem Wert den der ADC Port liefert einen bestimmten > Datensatz besitzt. Sieht mir nach einer klassischen Lookup-Table aus. Du willst also nicht den ADC-Wert direkt ausgeben, sondern einen anderen Wert (z.B. Kennlinien-Linearisierung o.ä.). Dazu musst DU zunächst im Programmspeicher (FLASH) eine Tabelle von Bytes oder Words anlegen, die für jeden Wert, den der ADC liefern kann, einen Wert enthält. Das macht man z.B. so: .cseg ADWerte: .db 0x01, 0x02, 0x03, ... Auf diese Werte kannst Du dann mit Hilfe des Z-Pointers und des lpm-Befehls zugreifen. Ich muss jetzt kurz weg und hab deshalb grad keine Zeit für weitere Erklärungen. Kannst ja in der Zwischenzeit schon mal schauen, ob Du mit den Infos weiterkommst...
Ok ok ich werde mich bemühen. Ich lege an meinem ADC Eingang (ADC0 ein Eingang) eine Spannung, die im Moment durch ein Poti500 verändernt werden kann (später PT100 mit Opto davor) an. Nun möchte ich diesem Wert der an ADC0 anliegt einlesen (was auch funktioniert) und diesem einen entsprechenden Wert aus einer Tabelle zuordnen. Dieser Wert aus der Tabelle soll dann auf ein LCD-Display (dessen Anstteuerung auch schon klappt) ausgegeben werden. gruß der bemühte Peter
Das heißt also, dass deine Tabelle im Flash liegt und zu jedem möglichen Messwert einen (der Charakteristik des Sensors entsprechenden) Anzeigewert enthält. Dann schau mal hier: http://www.hanneslux.de/avr/mobau/uiwa/uiwa.html Es handelt sich zwar nicht um Anzeigewerte, sondern um (eine Art) "Fehlerpunkte", aber das Prinzip ist das gleiche. Man setzt den Z-Pointer auf den Anfang der Tabelle, addiert als Offset den gemessenen Wert dazu, und liest dann per LPM den entsprechenden Tabellenwert aus. Beim Setzen des Pointers bitte beachten, dass der Adressraum im Flash wordorientiert ist (16 Bit), LPM aber byteorientiert zugreift. Die relevante Programmsequenz findest du ab Label "tim01b:". Viel Erfolg... ...
also nu mal ehrlich. Ich weiß nich, was eure ersten unqualifizierten Antworten sollten ! Ich hab keine zwei Anläufe gebraucht um zu verstehen, was er meint. Und wenn dann Posts kommen wie "Schreib doch bitte in Englisch" oder "Achte auf Groß und Kleinschreibung" dann hättet ihr euch die auch sparen können. Wenn ihr unbedingt auf solch eine Klugsch*****-Art antworten müsst, dann tretet dem "Verein der Wahrung Deutscher Sprache" bei. Die suchen immer solche Leute wie euch ! Also johnny.m, Glückwunsch für deine ersten Posts. Die sind mindestens 2 Klassen besser als Kindergartenniveau. Mensch ! Hier kommen leute her, die Fragen zu einem Thema haben und sich nich über etwaige Schreibfehler zurechtweisen lassen wollen ! Und jetz nich schonwieder einen Streit in diesem Thread losbrechen ! So. Nun zurück zum Thema. Du legst mittels ".org 0xE00" eine Addresse im FLASH-ab. Hinter diese schreibst du deine Wertetabelle (1024 Bytes für 10 Bit). Wenn du den ADC ausgelesen hast, machst du folgendes : ldi ZH,0x1C ; Byteaddresse des ersten Tabelleneintrages ldi ZL,00 add ZL,reg_ADCL adc ZH,reg_ADCH lpm reg_out,Z jetzt hast du in reg_out den Tabellenwert für deinen ADC-Wert. Willst du 16 bits lesen passt du das folgendermaßen an : ldi ZH,0x18 ; Doppelter Speicherbedarf ldi ZL,0 add ZL,reg_ADCL adc ZH,reg_ADCH add ZL,reg_ADCL adc ZH,reg_ADCH lpm reg_out_L,Z+ lpm reg_out_H,Z+ und in der Tabelle steht dann zuerst das LOW, dann das HIGH-Word. kannst du aber einfach durch vertauschen der LPMs umdrehen ... Beide Tabellen sind so ausgerichtet, dass sie am Ende des FLASHs liegen und 1024 Einträgeumfassen.
@Christoph: Möglicherweise bist Du ein ganz schlauer, wenn Du aus dem Kauderwelsch am Anfang sofort mehr als nur Vermutungen rausgelesen hast. Aber ich habe versucht ihm zu helfen, und wenn Du meinst Du kannst das besser, dann bitte sehr... Ob dem Opener das jetzt was bringt sei dahingestellt, aber Deinen Kommentar über meine Postings hättest Du Dir auch getrost schenken können, zumal Peter ja auch korrekt drauf reagiert hat!
ich stimme dir scho zu, dass das kein Text is, mit dem man ne Prüfung bestehen kann aber der Inhalt kommt trotzdem durch ... am Anfang will er, dass der ADC Wert in eine Temperatur übersetzt wird und was er in der Mitte schreibt ist, was er bisher fand (was einer Lookup-Tabelle entspricht) ... solchen Zynismus kann man sich dann aber trotzdem sparen : "Deine Shift-Taste scheint Ausfallerscheinungen zu haben" "2 Klassen besser" nu ja. ich hab wohl auch deutlich übers Ziel mit dem Post hinausgeschossen ... tschuldige für den zu scharfen Schreibstil ... lassen wirs dabei ...
> Genau. Kein Streit...
Nagut, dann fühle ich mich eben nicht angegriffen...
;-)
...
so Jungs da is man mal kurz weg um was zu erledigen und scho gehts hier ab wie Harry g !!! Is scho in Ordnung ich kann scho mit Kritik leben und wenn des hier so gewünscht ist (groß und Kleinschreibung und halbwegs geordnete Sätze), dann richte ich mich auch danach. Schließlich will ich etwas von euch und net Ihr von mir. Kann ja in anderen Foren und Chats weiterhin klein schreiben. aber trotzdem danke christoph Ich schau mir jetzt mal die letzten Posts genauer an. danke soweit gruß Peter
@Peter:
> Schließlich will ich etwas von euch und net Ihr von mir...
Bravo, Das ist die richtige Einstellung! Und ich glaube, auch Christoph
hat verstanden, dass es mir eigentlich nur darum geht, dass viele sich
sichtlich überhaupt keine Mühe mit der Formulierung ihres Problems
geben, andererseits aber erwarten, dass andere sich die Mühe machen,
aus dem Geschreibsel schlau zu werden. Es ist jedem selbst überlassen,
ob er sich diese Mühe über einen gewissen Punkt hinaus macht (wie
Christoph es offensichtlich getan hat) oder nicht.
Ich finde es auch nicht i.O., wenn manch einer nur kritisiert, aber
nichts Konstruktives zu vermelden hat. Wenn ich sehe, dass meine Kritik
fruchtet, dann bin ich auch durchaus bereit, 'sachdienliche' Hinweise
zu geben. Wenn nicht, dann halte ich das Maul.
In Deinem Fall hat die Kritik ja was gebracht, und deshalb habe ich
dann auch versucht, Dir ein paar konstruktive Hinweise zu geben,
nachdem Du Dein Problem etwas präziser erläutert hast.
Es geht eben nicht darum, dass in diesem Forum irgendetwas besonders
gewünscht ist, sondern eher darum, dass die Chancen, Hilfe zu erhalten,
signifikant besser liegen, wenn man gleich von Anfang an mit den
richtigen, vollständigen und verständlichen Infos rausrückt und eine
kleinschreibung ohne punkt und komma trägt eben nicht unbedingt zur
lesbarkeit bei...
Wenn ich irgendwo derartige Kritik anbringe (und das ist nicht wirklich
böse oder zynisch gemeint), dann auch nur, wenn das Thema des Threads
mich wirklich interessiert und ich mich auch an der Diskussion
beteiligen möchte. Andernfalls halte ich meine Finger von der Tastatur
fern...
so hab mir jetzt mal die Lösungsvorschläge angeschaut, des von Christoph mit dem zeiger setzten und Position Errechnen is mir nun klar. Doch wie springt er an die position (ich versteh net wie ich diese Tabelle aufbauen muss). hanneslux des bsp Programm is nicht schlecht, blos du setzt den Zeiger wieder ganz anders als Christoph ldi zl,low(uerrtab*2) ;Pointer auf ldi zh,high(uerrtab*2) ;Spannungs/Error-Tabelle warum eine subroutine mit 2 multiplizieren ein zeile mit 10 datensätzen oder 16 und wie viele zeilen brauch ich bei 16 wären des theoretisch 64. (wie gesagt einen 10 bitwandler der adch und adcl auswirft (2x8 bits insgesam word mit 16 bits) aber nur 10 sind belegt). Für eine kleine Erklärung wie diese Tabellen strukturiert sein sollen wäre ich dankbar. gruß Peter
Es wird keine subroutine multipliziert. uerrtab ist die Adresse (Marke) des ersten Elements der Fehlertabelle. Das mit dem Multiplizieren mit 2 liegt daran, dass der Speicher Wortorganisiert ist, lpm aber auf einzelne Bytes zugreift. In der Korrekturtabelle sind an jeder Programmspeicheradresse zwei Bytes hintereinander abgelegt. Um auf diese Bytes zuzugreifen, besitzt der Befehl lpm die Möglichkeit, mit dem LSB des Adresszeigers (also Z) auf die einzelnen Bytes zuzugreifen. Dazu wird die Wortadresse um ein Bit nach links geschoben (was einer Multiplikation mit 2 entspricht). Wenn das LSB jetzt 0 ist, wird auf das erste Byte zugegriffen, wenn es 1 ist, dann auf das zweite. So lässt sich der Programmspeicher byteweise belegen.
also kuckt euch des jetzt mal bitte an ob ich des richtig verstanden habe. .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 <<<< DS 1 (adc Wert0) .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 <<<< DS 2 (adc Wert1) .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0 <<<< DS 3 (adc wert2) .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0 <<<< DS 4 (adc wert3) .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0 <<<< DS 5 (adc wert4) .db 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0 <<<< DS 6 (adc wert5) .db 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0 <<<< DS 7 (adc wert6) .db 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0 <<<< DS 8 (adc wert7) und wenn ich jetzt ADHL und ADCH einlese und insgesamt den wert 5 hat, so springt er in die 5 zeile und gibt mir 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0 aufgeteilt in high und lowbyte zurück. Stimmt das jetzt soweit ? gruß Peter
Wenn Du nach wie vor nur eine Zahl für jeden ADC-Wert ausgeben willst, dann nicht! Vielleicht nochmal zur Erläuterung: Im Programmspeicher legst Du ein Segment an, in dem Du einzelne Bytes speichern willst (Jedes durch Kommata getrennte Element in einer mit .db eigeleiteten Zeile ist ein ganzes Byte!). Da der Programmspeicher wortorganisiert ist (die dort i.d.R. abgelegten Befehle sind entweder 16 oder 32 Bit lang, weshalb eine Byte-Organisation keinen Sinn macht), könnte man im Prinzip an jeder Adresse nur ein Byte ablegen, was mit einer Speicherausnutzung von 50% sehr ineffizient wäre. Der lpm-Befehl ermöglicht es aber, einzeln auf Low- und High-Byte der Worte zuzugreifen, indem er die Adresse künstlich verlängert und 'rechts' vom LSB ein zusätzliches Bit einfügt, mit dem er entscheidet, ob das Low- oder das High-Byte angesprochen werden soll. Auf die ursprüngliche Wort-Adresse bezogen hieße das, es werden 'Halbschritte' eingefügt, also im Prinzip zwischen den Wortadressen (es folgen aus der Luft gegriffene Beispiele) 1265 und 1266 eine '1265,5', die dann nur die letzten 8 Bit der Adresse 1265 anspricht. Wenn man jetzt den Z-Pointer auf das erste Element der Tabelle zeigen lässt (das LSB des Z-Pointers ist 0), erhält man mit lpm genau dieses erste Element, welches den höheren 8 Bit des Wortes an der Stelle entspricht. Erhöht man den Z-Pointer jetzt um 1 (das LSB von Z ist jetzt 1), dann erhält man die 8 LSB des Wortes. Und noch mal 1 dazuaddiert (dann ist das LSB des Z-Pointers wieder 0 und der Rest von Z um 1 höher als am Anfang) und man erhält die 8 MSB des nächsten Wortes. Für Deine Anwendung heißt das zunächst, dass Du den Z-Pointer auf den Anfang der Tabelle zeigen lässt, wie es oben beschrieben ist. Anschließend musst Du nur noch den Wert aus dem ADC zum Z-Pointer dazuaddieren und Du erhältst mit lpm den Wert an der entsprechenden Stelle. Wenn der ADC also z.B. den Wert 200 liefert, dann addierst Du die 200 zu dem Z-Pointer hinzu und Du erhältst das 201. Byte (Das erste hat die Nummer 0!) von der Ursprungsadresse an gezählt. Ich hoffe, das ist nicht zu viel auf einmal und hilft Dir weiter...
hm komm grad ganz schön ins schwitzen ^^, aber so wollen wir das ja. Ich steh scheinbar voll auf dem schlauch. dann sind praktisch bei meinem bsp immer 16 bytes in einer zeile oder ? aber wie spring ich da von einem byte auf des nächste nach rechts ? indem ich zu dem Z-Pointer 1 hinzuaddiere ? und wenn ich am Ende der Zeile bin dann springt er in die nächste und zählt weiter ? dann ist die Tabelle praktisch aufgebaut wie folgt (die zahlen geben die Werte des ADC's an 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32 33,34...... gruß Peter
Die Zeilen haben keine programmtechnische Bedeutung. Die Tabelle ist von der ersten Adresse fortlaufend, Byte für Byte. Du musst nur immer drauf achten, dass in jeder Zeile eine gerade Anzahl Bytes steht, weil bei einer ungeraden Anzahl das letzte in einem eigenen Wort gespeichert wird, auch wenn die nächste Zeile wieder mit .db beginnt. Konkretes Beispiel: .cseg uerrtab: .db 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 .db 8, 8, 8, 9, 9, 9, 10, 10, .... ;usw... ; Z-Pointer initialisieren, auf erstes Element von uerrtab zeigen ldi zl,low(uerrtab*2) ;Pointer auf ldi zh,high(uerrtab*2) ;Spannungs/Error-Tabelle ;...ADC auslesen (gehe mal von 8 Bit Auflösung, left adjusted aus) in r16, ADCH ldi r17, 0 add zl, r16 adc zh, r17 ;in zh und zl steht jetzt uerrtab*2 + ADCH drin lpm r18, z ;lade Wert aus Tabelle in r18 Wenn der ADC z.B. den Wert 15 geliefert hat, dann steht in r18 am Ende eine 7 drin (oben nachzählen, das 16. Element in der Tabelle, also das mit der Nummer 15, ist eine 7). Wenn Du mit jedem ADC-Wert zwei Bytes ansprechen willst, dann musst Du den ADC-Wert, bevor Du ihn zum Z-Pointer dazuaddierst, mit 2 multiplizieren (also um ein Bit nach links schieben) und in zwei Schritten die beiden dazugehörigen Werte aus der Tabelle holen (beim zweiten einfach den Z-Pointer um 1 erhöhen). Bei mehr Werten entsprechend, allerdings wird dann irgendwann der Speicher knapp...
so bin jetzt weg, geh jetzt nach Hause. Vielleicht schau ich heute Abend noch mal vorbei, sont hald morgen wieder. Danke für eure Hinweise bis jetzt. Bis denn Peter
ahhh jetzt hab ichs, ich glaubs zumindest gecheckt. Dann versuch ich morgen mal, des an einem Experiment auszuprobieren. Ich seh scho, ich muss nächstes mal echt klarer formulieren. Der letzte Post von jonny m. der war der entscheidende. gruß Peter
Nochmal zu meinem Beispiel... Ich lese nur ADCH aus, weil ich in ADMUX linksbündige Ausrichtung eingestellt habe und mir in dieser Anwendung die Auflösung von 8 Bit genügt. Jedes Element der Tabelle enthält nur ein Byte, die komplette Tabelle enthält also 256 Einträge je 1 Byte. Das Addieren von 0..255 zum Z-Pointer (der auf Tabellenanfang steht) adressiert dann ein beliebiges Byte der Tabelle. Lass dich nicht von der zweiten Tabelle irritieren, die Auswahl, welche der beiden Tabellen benutzt wird, erfolgt woanders und hat mit der eigentlichen Funktion der Tabelle nichts zu tun. Du erwähntest den Begriff "Springen". Hier wird eigentlich nirgendwohin "gesprungen", es wird nur der Z-Pointer auf ein bestimmtes Byte innerhalb der Tabelle positioniert, damit der Befehl LPM den Inhalt dieses Bytes nach r0 kopiert. Schau dir dazu mal die Befehlsbeschreibung zu LPM an. Auch die Beschreibung der Speicherarten und Adressierungsarten, die in jedem Datenblatt (recht weit vorn) zu finden sind, sollztest du dir mal näher anschaun. Vielleicht hilft das ja zusammen mit unseren Erklärungen zum Verständnis. ...
Als Anmerkung : Mit solchen Tabellen kannst du auch flugs Strings auf dem Display ausgeben : PRINT: lpm value,Z+ ; Lädt Byte aus FLASH (Z-Addresse zählt autimatisch weiter) cpi value,0 ; ist das Byte 0 ? breq PRINT_EXIT ; ja - Null-terminierter String zu ende. rcall LCD_DATA ; ansonsten sende das Byte zum LCD rjmp PRINT ; und wiederhole von vorne. PRINT_EXIT: ret Angesteuert wird das dann einfach per : STRING: .db "Hello world",0 ; 0 zeigt das Ende des Strings an. ldi ZH,HIGH(STRING*2) ldi ZH,LOW(STRING*2) rcall PRINT Das ist soweit die einfachste und effizienteste Methode um ein LCD zu beschreiben und verdeutlicht am besten das lpm-Prinzip.
Kleine Ergänzung zu den letzten Postings: Wenn der ADC mit höherer Auflösung als 8 Bit betrieben werden soll und die auszugebenden Werte größer werden als mit 8 Bit darstellbar, dann kann man (vorausgesetzt im Flash ist genug Platz dafür) die Werte auch als 16-Bit-Worte ablegen und mit lpm in jeweils zwei Schritten Low- und High-Byte laden. Dazu die Tabelle nicht mit .db sondern mit .dw aufstellen. Das hat den Vorteil, dass man die 16-Bit-Werte (wie bei .db auch in Dezimalschreibweise, also z.B. 654, 1376...) direkt eingeben kann und nicht mit irgendwelchen Halbbytes rumspielen muss.
Ah hübsch, ich versuche im moment mir eine Routine zu schreiben mit der ich dann, eine 3 stellige Dezimalzahl auf das Display ausgeben kann. Das ich nur noch in meiner Tabelle eine Dezimalzahl hab und diese dann auf dem Display ausgegeben wird. Weil die LCD routine die ich geklaut habe dort kann man nur einzelne Zeichen ausgeben. Danke für die vielen Antworten. gruß Peter
Stop! Die Möglichkeit der Eingabe als Dezimalzahl bezieht sich nur auf die Schreibweise bei der Programmierung! Gespeichert werden die Zahlen binär (hexadezimal) und müssen vor der Ausgabe als Dezimalstellen selbstverständlich erst in BCD oder ASCII (je nach Art der Ausgabe) umgewandelt werden!
...Zusatz: Wenn Du eine dreistellige Ausgabe im ASCII-Format benötigst, solltest Du die Zahlen als gepackten BCD-Code speichern (im Prinzip als Dezimal-Zahl eingeben, aber mit 0x davor). Dann musst Du in der Ausgaberoutine die Bytes reinholen, der Reihe nach die Halbbytes (die ja den Dezimalstellen entsprechen) extrahieren und in ASCII umwandeln (also 0x30 dazuaddieren). Eine Tabelle sähe dann z.B. so aus: tabelle: .dw 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 .dw 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 ;... .dw 0x96, 0x97, 0x98, 0x99, 0x100, 0x101, 0x102, 0x103b ;...usw... Dann hast Du in der Tabelle gleich die Dezimalstellen stehen. Wenn Du allerdings nur 8-Bit-Werte vom ADC hast (also Dezimalwerte von 0..255), musst Du beachten, dass diese Variante doppelt so viel Speicher benötigt, wie die Abspeicherung der Hexadezimal-Werte (ein Wort, also 16 Bit pro Wert anstatt 8 Bit!). Dann ist es sinnvoller, die weiter oben angesprochenen Varianten zu verwenden und die Umwandlung in Dezimalstellen softwaremäßig in der Ausgaberoutine zu machen.
Peter, schau dir mal an, wie andere Leute Daten an das LCD ausgeben. (M)Ein Beispiel findest du hier: http://www.hanneslux.de/avr/stopuhr/index.html Alle LCD-spezifischen Routinen liegen in der Datei 'LCD_8x24a.inc', alle Routinen zur formatierten Ausgabe liegen in der Datei 'LCDprinta.inc'. Diese beiden Dateien werden vom Hauptprogramm per .include eingebunden. Werden nicht alle Ausgabeformen benötigt, so kann man die nicht benötigten Macros und Routinen löschen. Sas mache ich aber erst, wenn es im Flash eng wird, was im Beispielprogramm nicht der Fall ist. Anhand der vorigen Beiträge sehe ich, dass dir noch einige Basics fehlen. Schau dich doch einfach mal in der Hilfe zum AVR-Studio um. Über Menüpunkt help, tools, avr-assembler2, directives (oder so ähnlich, habe jetzt nicht nachgeschaut) findest du die komplette Auflistung und Erklärung zu allen zugelassenen Operatoren und Directiven des Assemblers, ganz in der Nähe findest du den kompletten Befehlssatz und noch vieles anderes Wissenswerte. Einfach mal etwas in der Hilfe herumschmökern, die investierte Zeit amortisiert sich schnell. ...
Auch Johnys Vorschlag ist ok. Allerdings müsste jetzt erstmal definiert werden, welchen Zahlenbereich du überhaupt benötigst. Auch müsste ermittelt werden, welcher Bereich am ADC überhaupt gemessen werden kann. Es macht keinen Sinn, eine Tabelle mit 1024 Elementen je 2 Bytes zu erstellen, wenn der 'ADC-Messbereich' (also die vom ADC messbaren Werte in Abhängigkeit von der externen Beschaltung und dem Temperaturgang des Sensors) nur z.B. von 400 bis 600 geht. In diesem Falle wäre es 'billiger', einen festen Offset (z.B. 400) zu subtrahieren und nur 200 Elemente in die Tabelle aufzunehmen. Brauchst du nur eine dreistellige Zahl, so schau dir die untere und obere mögliche Zahl an und überprüfe, ob es nicht mit einem Byte und einem festen Offset geht. Es kommt also immer auf die Anforderungen an. Sicher kann man das alles auch in 16-Bit- oder 32-Bit-Arithmetik machen, aber das wäre schon Verschwendung von Ressourcen. Und ich nehme mal an, dass dein AVR etwas mehr tun soll, als nur ein simples Thermometer. Da könnte es durchaus sein, dass du noch Ressourcen für andere Zwecke brauchst. ...
also mir fehlen noch jede Menge Basics, ich hab gerade Abitur gemacht und mach jetzt ein Praktikum (eig als Informatiker), aber der Informatikchief is gerade auf Montage. Deshalb bin ich jetzt in der Elektroabteilung und da hab ich hald ein Breadboard gefunden und einen Atmega8. Und jetzt probier ich hald bisschen was mitzunehmen (wenn ich scho net in der Informatikabteilung bin (da hatte ich mich bis jetzt eben mit vb beschäftigt)). und mein atmega8 soll atm net mehr machn als einen Wert (Spannung zwischen 0 und 5 V) über den ADC einlesen und dann auf ein Display umgerechnet ausgeben. Im zum versuch hab ich ein Poti am ADC hängen, der später mal einem PT100 weichen soll. (Hypothese: vor den PT100 muss ich warscheinlich noch einen Operationsverstärker hängen, da die veränderungen zu schwach sind oder) gruß Peter
Mit PT100 habe ich keine Erfahrung, ich weiß nur, dass der Temperaturgang sehr gering ist. Nimm doch erstmal einen Heißleiter als Sensor, oder besser drei Dioden 1N4148 in Reihe und die interne ADC-Referenz des Mega8. Die Dioden kommen mit der Kathode an GND, Anode an ADC-Pin und ein Widerstand 1k von Anode nach Vcc. Der ADC misst den Spannungsabfall an den Dioden, der stark temperaturabhängig ist. Ich habe gerade etwas Ähnliches mit Mega48 und einer Diode gemacht, allerdings ohne LCD-Ausgabe (wurde nicht gewünscht), nur als Thermostat. Tip... Analysiere doch erstmal ASM-Programme anderer Leute und versuche, jede Zeile (und den Zusammenhang aufeinanderfolgender Zeilen) zu verstehen. Viele offene Fragen beantwortet bereits Datenblatt und Befehlssatz, weitere Fragen kannst du gerne hier stellen. Dies gibt dir das erforderliche Knowhow, eigene Ideen umzusetzen. Auf meiner HP findest du noch einige andere Programme, die relativ einfach gehalten sind und meist recht üppig kommentiert. Zum Einstieg (allerdings mit Tiny15) empfehle ich: http://www.hanneslux.de/avr/divers/index.html Da werden einige Grundlagen an verschiedenen Versionen eines Melodiegenerators vermittelt. ...
Wie der PT100 zu beschalten ist, hängt von den Gegebenheiten ab. Zunächst mal muss der (temperaturabhängige) Widerstandswert in einen Spannungswert umgewandelt werden, damit er überhaupt vom ADC erfasst werden kann. Das geht entweder über einen Spannungsteiler oder gar eine Brückenschaltung (u.U. mit nachgeschaltetem Differenzverstärker, dann kann man auch gleich den Messbereich an den des ADC angleichen). Aber das mit dem Poti auszuprobieren ist sicher erst mal die beste Idee. Ich habe genauso angefangen, meine ersten ADC-Schritte zu machen (Allerdings gab es damals noch keine AVRs...). Das wichtigste ist erst mal, den ADC ans Laufen zu bekommen und das Prinzip der Werte-Umwandlung über die Tabelle zu verstehen, der Rest sind Details, die sich irgendwann (fast) von selbst ergeben. Wenn es mit einfachen Werten und 8 Bit Auflösung klappt (und das solltest Du als erstes ausprobieren, auch wenn die Versuchung groß ist, gleich mit Nachkommastellen und Begleittext rumzuspielen), dann sind es nur noch kleine Schritte, das ganze zu verfeinern. Ansonsten ist Hannes' Website sicher die erste Adresse für Dich, was Beispiele zum Nachvollziehen und Ausprobieren angeht. Also: Gucken, wie andere es machen, verstehen und dann an die eigenen Bedürfnisse anpassen / erweitern.
so ne art tongenerator bei mir warens 4 LED's hab ich scho gemacht läuft auch. einmal hab ichs mit Tasten gemacht. Und dann hab ich ein LED "Nightriderlichtchen" (des teil des Kid im Kühler hatte) gebaut. und nun wollte ich mich eben an so ein Thermometer wagen. Und vll habt ihr es ja in meinem letzten thread gelesen mit dem ADC einlesen des funktioniert ja schon ausgebn auf dem Display auch, hald als Binärzahl. Nun müsst ich eben den Wert einer Temperatur zuordnen (so ein PT100 verhält sich ja relativ linear). Dies wollte ich eben mit so einer Tabelle machn. Der PT100 muss eben auch skaliert werden, bei 0° C hat er 100 Ohm. Und verändert dann seinen Widerstand eben. Aber die genaue skalierung ist im Moment noch uninteressant. Ich möchte ja nur mal einen dezimalen Wert dem Messergebnis des ADC zuordnen und dezimal Ausgeben. Und leider endet mein Praktikum am Fr. Ab Mo Ferienarbeit für 4 Wochen (--> heißt keine Zeit für mikrocontroller, erst danach wieder). Und es wäre eben hübsch wenn ich bis dahin den Thermometer noch fertig bekäme (bis Fr). gruß Peter
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.