Forum: Analoge Elektronik und Schaltungstechnik Benötigen Hilfe bei 8051: Schulprojekt Spannungsmesser


von Dave und Ray (Gast)


Angehängte Dateien:

Lesenswert?

Guten Morgen,

wir möchten uns erst einmal vorstellen.
Wir sind Schüler auf dem Technischen Gymnasium in Sigmaringen und
müssen ein Projekt in Informationstechnik durchführen, dessen Teil die
Programmierung eines 80c51 Microcontrollers ist.
Die Programmierung soll in Assambler erfolgen.

Sachziel: Realisierung eines Programms zur Messung einer anliegenden
Spannung und Ausgabe auf einem LCD Display.
Die Spannung soll von 0-5V in 0,1V Schritten angezeigt werden.

Unsere Problematik ist, dass wir die Kombination des LCD Displays mit
dem AD/DA-Wandler nicht realisiert bekommen. Im Unterricht wurden
solche Problemstellungen nicht hinreichend behandelt, somit haben wir
keine Ahnung, wie das gehen soll!

Wir bitten um möglichst schnelle Hilfe, da es sich nur um eine
Teilaufgabe handelt und der Abgabetermin immer näher rückt.


Anbei haben wir die uns zur Verfügung gestellten Mittel hochgeladen.
Es handelt sich dabei um Datensätze für den ADDA-Wanndler und das
LCD-Display.


Viele Grüße
David und Renè

von Manos (Gast)


Lesenswert?

"Unsere Problematik ist, dass wir die Kombination des LCD Displays mit
dem AD/DA-Wandler nicht realisiert bekommen."

Hm... also Ihr habt Probleme vom Anfang bis zum Ende? Wo genau liegt
denn das Problem? Wisst Ihr nicht wie Ihr die Analogwerte einlesen
sollt, wisst Ihr nicht wie man Text auf dem LCD ausgeben kann oder
was?
Fehlen die Grundlagen um aus dem Ergebnis der A/D-Wandlung einen
Spannungswert zu errechnen - oder wollt Ihr einfach nur die
Hausaufgaben gemacht bekommen?

von Dave und Ray (Gast)


Lesenswert?

Ehrlichgesagt, ja, wir haben Probleme vom Anfang bis zum Ende.

Ein paar Grundlagen sind schon vorhanden, aber wir haben in der Schule
noch nie etwas mit AD-Wandlern oder LCD Display gemacht.
Wir haben nur so einfache Dinge, wie Zähler, Ausgabe auf
Segment-Anzeigen oder Lauflichter programmiert..

Wir programmieren Assambler erst seit diesem Jahr und sind noch nicht
wirklich fit, desshalb bitten wir hier um Hilfe.

von Schoasch (Gast)


Lesenswert?

Sorry, ich kann kein ASM, aber theoretisch würde ich es so angehen.

Zuerst würde ich mal einen Timer akivieren und den halt durchlaufen
lassen. Wenn der mir einen Interrupt erzeugt,setzt den Timer zurück und
startet die AD-Wandlung und warte bis diese abgeschlossen ist(da gibts
ein Flag das du nur abfragen musst ob es gesetzt ist).
Wenn die Wandlung abgeschlossen ist, dann sollen die Daten ans LCD
ausgegeben werden. Es ist vl sinnvoll, wenn du in der Interrut-routine
ein Flag setzt, welches du dann im Main abfragst und danach die
AD-Wandlung und die Ausgabe aufs LCD machst(danach das Flag
zurücksetzen)

Du musst halt nur den Timer-Überlauf so gross machen, dass die
AD-Wandlung und die Ausgabe ans LCD fertig sind ehe der Interrupt
kommt.(Üblich sind glaube ich 2 mal pro Sekunde messen).

von Stephan H. (stephan-)


Lesenswert?

na denn schaut doch mal im Codebereich nach 3fach Strom Spannungsanzeige
von mir. Da könnt Ihe jede Menge davon nutzen.
Und Schaltpläne waren auch bei.
Nix fertiges für Euch aber genug um was draus zu machen.

So denn los gehts

von Rahul (Gast)


Lesenswert?

"Das Mikrocontroller Kochbuch" von Andreas Roth...
Dann gliedert Ihr Eure Aufgabe in Teilaufgaben auf und schon ist das
Problem gelöst.

von Schoasch (Gast)


Lesenswert?

Vielleicht könnte dir folgende Seite etwas helfen bei den Grundlagen zum
AD-Wandler.
http://www.humerboard.at/navi/f_anwendung.htm

von The Daz (Gast)


Lesenswert?

Ich verstehe nicht, wieso ihr da nicht weiterkommt. Im IT.zip sind ein
paar Word-Dateien, die die Funktionsweise und Ansteuerung des
AD-Wandlers und des LCDs sogar mit Beispielen beschreiben. Dort steht
sogar, dass fuer die I2C-Hardware Bibliotheken zur Verfuegung stehen
und keine Detailwissen um das Hardwareprotokoll zwischen den Chips
noetig ist. Mit dem Beispiel code kann man doch schon die Werte vom
AD-Wandler abholen und mit dem LCD-Beispiel Text ausgeben. Ihr muesst
also nur noch in einer Schleife die AD-Wandler Werte abholen, in Text
umwandeln und ans LCD schicken.

von Xenu (Gast)


Lesenswert?

Wie Daz schon sagte, es ist doch sowieso alles dabei.
Vielleicht solltet Ihr einfach mal genauer lesen,
z.B. das hier "ausAnalog-Digital-Umsetzung8252.doc":

"Weder die Funktion des Busses noch die Funktion des ICs muss man
verstehen, da fertige Unterprogramme zur Verfügung stehen."

von Pieter (Gast)


Lesenswert?

moin moin,

das programmieren fängt beim verstehen an. Und da hat man euch wohl
nicht viel beigebracht. Oder doch?

Die Aufgabe ist doch ganz einfach:

0. Einrichten das AD-Wandlers und der Anzeige
1. Wert von AD-Wandler holen
2. Wert zur Anzeige bringen
3. weiter bei 1.

Das ist das das ganze Programm.
Nun schreibt mal zu den einzelnen Punkten was noch zu beachten und zu
tun ist dazu. Nur mit Worten, noch ganz ohne eine Programmiersprache.
Wenn diese Beschreibung fertig ist und alle Möglichkeiten erfasst, habt
Ihr einen PAP (ProgrammAblaufPlan) und der wird dann in eine
Programmiersprache umgesetzt.

Mit Gruß
Pieter

von Dave und Ray (Gast)


Lesenswert?

Vielen Dank schonmal für die zahlreichen Antworten.

Wir wissen, dass uns eigentlich schon fast alles gegeben ist,
allerdings liegt unser Problem darin die Informationen zu verstehen und
umzusetzen.

Wo im AD-Wandler Beispielprogramm steht der Wert, den wir an das LCD
bringen müssen?

an Pieter:
Was genau verstehst du unter "0. Einrichten das AD-Wandlers und der
Anzeige"?
Wie würdest du den PAP aufteilen?


Gruß
David und Rene

von Dave und Ray (Gast)


Lesenswert?

Also hab das jetzt gefunden.
Der Digitale Wert wird da ja an P2 (Auf unserer Platine sind das LEDs)
ausgegeben.

Ist das richtig, dass wir jetzt eigentlich nur den Wert nicht an P2,
sondern auf das LCD Display übergeben müssen?
Und diesen Wert dann noch dem entsprechenden Text (0,1V; 0,2V; ....)
zuweisen?


Gruß
David Und Rene

von Manos (Gast)


Lesenswert?

Naja "zuweisen" wäre wohl auch eine Möglichkeit, aber ich würde es
versuchen zu rechnen. Wenn der AD-Wandler 8Bit hat dann ist ein AD-Wert
von 255 ($FF) 5.0V, ein Wert von 0 ($00) 0.0V. Der Rest liegt irgendwo
dazwischen.

von Pieter (Gast)


Lesenswert?

moin moin,

als Anzeige soll per LCD erfolgen, diese muss zuerst initialisiert
werden. Dazu sollte es in der beiliegenden Software so etwas wie
InitLCD geben. Auch beim ADU kenn eventuell etwas einzustellen sein.

Der PAP um fragen erweitert:
0.1 InitLCD
0.2 InitADU
1. Wert vom ADU holen
  -muss und wie wird der ADU gestartet?
  -wie feststellen ob ADU fertig (Signal oder Zeit)?
  -wie Wert auslesen?
  -wo Wert speichen wenn notwendig?
2. Wert zur Anzeige bringen
  -muss eine Umwandlung erfolgen,
   wenn ja wie (z. B. binär -> dezimal? )
3. Sringe zu 1.

Diese Fragen mit den beiliegenden DOCs beantworten und aus den Fragen
Anmerkungen mit dem wie realisieren machen. Immer schön
stückjenweisen.

Mit Gruß
Pieter

von Karl heinz B. (kbucheg)


Lesenswert?

Wenn ich auch noch meinen Senf dazugeben darf:
Ich bin ein Verfechter der 'Schritt-Für-Schritt' Methode.
Wenn du weder vom ADC noch vom LCD Ahnung hast, dann würde
ich die beiden Bereiche einfach mal trennen. Anstatt sich
um die komplette Aufgabenstellung zu sorgen, definiert euch
mal 2 eigene Ziele:
* Wie kann man am LCD was ausgeben
* Wie kann ich vom ADC was einlesen

So und jetzt kümmert ihr euch momentatn nur um das LCD.
Euer Ziel ist es, dass am LCD ein Text eurer Wahl ('Hallo Welt'
ist ein beliebter Text) einfach nur angezeigt wird. Sonst nichts.
Wichtig: nicht einfach nur sagen das sei simpel denn da existiert
ja vielleicht in Beispiel. Tut es. Nehmt die konkrete Hardware,
schreibt das Program, verbindet es mit der vorgefertigten Bibliothek
die die eigentliche Ausgabe macht und lasst es laufen!

Ist die Ausgabe soweit erledigt, dann legt ihr die einfach mal
beiseite und kümmert euch um den ADC. Sieviel ich gelesen habe,
gibt es da ein Beispiel, dass den ADC Wert auf LED's ausgibt.
Super. Gebt das mal ein und lasst es laufen. Wieder: nur das
Vorgefertigte übernehmen, was auch im Endprogram enthalten sein
wird: also die eigentliche Einleseroutine. Das drumherum selber
schreiben, auch wenn es bereits ein fix&fertiges Beispiel dazu
gibt.

So. Jetzt seid ihr hoffentlich in dem Zustand, dass ihr versteht
wie das LCD angesteuert werden muss und wie man vom ADC Werte
bekommt. Als nächstes verbindet man die beiden Einzelteile.
Also wird ein neues Programm geschrieben, in dem beide Welten
zusammengeführt werden. Wieder: Macht euch die Dinge so einfach
wie möglich! Vergesst erst mal, dass ihr Volt anzeigen wollt.
Das erste Ziel sollte sein, einfach nur den Zahlenwert vom
ADC, und zwar so wie ihn der ADC liefert auf dem LCD anzuzeigen.
Nicht mehr! Ihr werdet dabei zum Beispiel feststellen, dass ihr
den Zahlenwert in eine Zeichenkette verwandeln müsst. Das Erkennen
dass so eine Funktion notwendig ist und deren Implementierung haben
schon so manchen Neuling in den Wahnsinn getrieben.

Der nächste Schritt wäre dann, das ganze in eine Schleife
zu packen. Ob das jetzt eine tatsächliche SChleife ist, oder
die Wiederholung über Interrupts realisiert werden, ist fürs
erste erst mal nebensächlich. Wichtig ist nur, dass wenn sich
die Eingangsspannung am ADC ändert, sich auch der angezeigte
Zahlenwert am LCD ändert.

Erst dann, wenn das alles läuft, wird der Zahlenwert vom ADC
in eine Spannung umgerechnet

Der nächste Schritt ....  Uuuups es gibt keinen nächsten Schritt
mehr. Die Aufgabenstellung wurde gelöst.

Also:
 Nicht alles auf einmal machen.
 In kleinen Schritten arbeiten
 Wenn man von etwas keine Ahnung hat, dann ein eigenes Testprogramm
   dafür aufsetzen, indem man nur diesen Teilaspekt abklärt.
 In kleinen Schritten arbeiten
 Nicht davor zurückschrecken, auch mal ein Beispiel abzutippen
   anstatt es einfach nur zu assemblieren. Beim Aptippen fallen einem
   hunderte Dinge auf, die man sonst nie gesehen hätte
 In kleinen Schritten arbeiten
 Vorgegebene Beispiele analysieren, wie sie arbeiten, damit
   rumspielen und auch mal verändern
 Hab ich schon gesagt? - In kleinen Schritten arbeiten

von Dave und Ray (Gast)


Lesenswert?

Ihr wart uns eine große Hilfe.

Hab das jetzt, wie Karl Heinz geschrieben hat, in kleinen Schritten
gemacht.
Erstmal mit dem LCD bisschen rumprobiert, dann mit dem Wandler.
Jetzt bin ich mittlerweile so weit, dass ich das, was vom Wandler kommt
auf dem Display ausgeben kann.

Nur die Spannung stimmt noch nicht ganz, aber das ist jetzt kein großes
Problem mehr.
Ich hab grad mehr das Problem, dass das Programm (RIDE IDE), das wir
von der Schule bekommen haben nur eine Shareware version ist.
Dadurch ist die Größe des codes etwas beschränkt und ich schaffe es
nicht darunter zu bleiben.

Aber vielleicht kann man da einfach die Dinge, die nicht aus der Datei
vom Wandler und Display benötigt werden, löschen. Sollte reichen.


Vielen Dank nochmal.

Gruß
Dave und Ray

von Dave und Ray (Gast)


Lesenswert?

Also angeblich liegt das doch nicht an "Ride IDE", sondern an unserem
Programm.

Es kommt der Fehler:
Error 130: Code space overlap at adress: 0000

Was genau bedeutet dieser Fehler und wie kann ich ihn beheben?
Ich denke,d ass zwei Programme auf die "adresse 0000" (?)
gleichzeitig zugreifen wollen. Wie kann ich das verhindern?

Gruß

von Olivia (Gast)


Lesenswert?

CSEG weiter nach hinten verschieben? Ansonsten dürften
Interrupt-Einsprung-Adressen überschrieben werden.

von Dave und Ray (Gast)


Lesenswert?

Leider sagen mir CSEG und Interrupt-Einsprung-Adressen nicht viel.

Könntest du das bitte auch für Schüler übersetzen? ^^

von Olivia (Gast)


Lesenswert?

Wenn Du keine Start-Adresse in Deinem Quellcode definierst, wird Dein
Programm ab 0000H geflasht. Da in diesem niedrigen Bereich (keine
Ahnung bei 8051) auch die Interrupteinsprungadressen liegen, wird bei
Auslösen eines Interrupts wild in das Programm gesprungen und
unkontrolliertes Verhalten ist garantiert. Du solltest testweise vor
dem Hauptprogramm mal .ORG 0x0100 einbauen. Bei AVR könnte es z.B. so
aussehen:

.CSEG

.ORG  0x0000
                   rjmp main

.ORG  0x0001
       rjmp int0_handler

.ORG  0x0005
      rjmp timer1_handler

.ORG  0x0006
      rjmp timer0_handler

.ORG  0x0020


main:


bei 0x0000 wird nur der Sprung nach main veranlasst. Anschließend
werden die Ziele für 3 Interrupts definiert und dann beginnt main ab
0x0020. Dürfte beim 8051er sehr ähnlich sein. Probier zur Sicherheit
0x0100.

von Dave und Ray (Gast)


Angehängte Dateien:

Lesenswert?

Hi,

wir sind inzwischen so weit, dass wir nur noch den Wert vom
Potentiometer (0-255) auf 0,1 - 5,0V umrechnen müssen.

Das stellte sich allerdings als riesen Problem raus.
Zuerst versuchten wir die Stelle vor dem Komma und die danach seperat
anzuzeigen. Das haben wir dann aber nach ner Weile aufgegeben.

Dann kam uns die Idee den Wert vom Wandler einfach durch 5,1 zu
dividieren.
255/5,1 = 50 Zustände (0,1-5,0V)
Wie dividiert man durch 5,1 oder auch nur durch 5 in Assambler?
Durch 2 ist ja kein Problem.. Einfach mit RR die Bits nach rechts
durchschieben.

Oder fällt euch noch eine ganz andere Möglichkeit ein?#

Anbei liegt unser Hauptprogramm. Hoffe ihr kommt damit klar.

Gruß

von Joe (Gast)


Lesenswert?

Na, dann sucht mal nach div, das kann der 8x51.

von Weinga-Unity (Gast)


Lesenswert?

Hallo!

Hier mal ne Seite, die für Anfänger recht interessant sein kann:

http://www.erikbuchmann.de/

Und der dort vorgestellte Code-Generator für 8051er (z.B. LCD-Treiber)
http://wwwiti.cs.uni-magdeburg.de/~buchmann/privat/generator.htm

Das ZIP-File, was du beigestellt hast, is eh sehr hilfreich. AD-DA
Wandler sollte ja gar kein Problem sein und LCD auch nicht so wirklich.
Es hilft oft viel, einfach nach den Beizeichungne der Bauteile + 8051 zu
googlen. Gib eh recht viel Code dafür.

mfg Weichinger Klaus

von Rahul (Gast)


Lesenswert?

Divisionen kann man auch Subtraktion und Schleifen erzeugen...

von Stephan H. (stephan-)


Lesenswert?

Jungs, nicht durch 5,x Dividieren !!!
Subtrahiert einfache ganze Volts !!!!
Bei 8 Bit und 5 Volt Vref habt ihr 20mV pro Step.
Wieviele Steps braucht man für 1 Volt ????
Genau , die zieht Ihr vom Wandlerwert ab und zählt die Anzahl der
ganzen Volts mit. Dann denn Rest aus ner Tabelle lesen.
zB Rest ist 3h also 0,06V.
oder Rest ist 30h macht na....0,96Volt.
Damit könnt Ihr die Ergebnisse wuderbar runden und müßt Euch nicht mit
der Mittelwertbildung rumschlagen.....
so mache ich das jedenfalls.
Wie gesagt Codesammlung...3fach Anzeige


Und ... alles klar ???

von Pieter (Gast)


Lesenswert?

moin moin,

ein 8Bit-ADU hat doch 256 Zustände. Da gibt es noch einen Denkfehler.
Die Umrechnung ist also so: Uref / 256 * Wert_ADU. Da Uref in diesem
Falle 5V ist also so : 5/256*Uref.
Durch einfaches Umformen der Gleichung erhält man:
5*Wert_ADU / 256 =
(Wert_ADU+Wert_ADU+Wert_ADU+Wert_ADU+Wert_ADU)/256

Da Wert_ADU ein 2Byt-Wert ist, ist die Division /256 das höherwertige
Byt. Ist letztendlich nur der Ladebefehl.
Bleibt als Aufgabe nur die 2Byt Addition in Assembler.

Mit Gruß
Pieter

von Stephan H. (stephan-)


Lesenswert?

Hallo Pieter....the Error is my !!
wie Recht Du doch hast...
natürlich 256 Zustände.... wären die Jungs aber auch drauf gekommen
oder nicht ???? Denken schadet doch nicht....

ÜBRIGENS....
ist ne Mail für Dich da...

PS.: Der ADU Wert ist bei 8 Bit ein EIN Byte WERT !!!!
Oder ist Byt = Bit ???
Machs nicht so kompliziert. Das ist was für uns ......
Die Jung lernen noch.

Der Unterschied macht aber nur 100uV aus... Ich denke für nen
Schulprojekt mehr als ausreichen.... mit Fehler !!!

von Bernd (Gast)


Lesenswert?

256 Zustände sind doch gerade 0-255.
also bei 5V -> 255.
Dann muss es doch heißen
5*Wert_ADU / 255, oder nicht?

von Rahul (Gast)


Lesenswert?

Die Diskussion wieder...

von Bernd (Gast)


Lesenswert?

???

von Stephan H. (stephan-)


Lesenswert?

ich habs geahnt........und nichts gesagt !!!! :- ))

von Stephan H. (stephan-)


Lesenswert?

NACHTRAG....

Jungs wie ich schrieb, Schulprojekt !!!!
Wir reden von 100 uV !!!!!!!!!
Laßt es sein !

von Rahul (Gast)


Lesenswert?

Wenn man 256 benutzt, muß man mit 16Bit rechnen, wenn man 255 benutzt,
braucht man nur 8...

von Stephan H. (stephan-)


Lesenswert?

deswegen schrieb ich
"Bei 8 Bit und 5 Volt Vref habt ihr 20mV pro Step."

also ist bei 0FFh Feierabend.
Nix 16 Bit. Allerhöchstenfalls 8 Bit Plus Signum !!!

jetzt geh ins Bett...

Stephan

von Pieter (Gast)


Angehängte Dateien:

Lesenswert?

moin moin,

der ADU liefert natürlich 1 Byt. Um das Ergebnis der Multiplikation mit
5 zu speichern braucht man 2 Byt.
Nun mein Schnellschuss: Division durch 256 bringt das Ergebnis als
gebrochene Zahl.

Beispiel:
2,34V -> ADU liefert 120

120*5 = 600  -> 258H, die 2 ist 2, V

600 div 256 -> 2
600 mod 256 -> 88 (Divisionsrest)

88*100 -> 8800 -> 2260H
8800 div 256 -> 22H = 34D

In Assembler ist das dann so:

    mov   a, Wert_ADU  ;120
    mov   b,#5
    mul   ab        ;b=2H , a=58H
    xch   a, b      ;das ist div 256!
    add   a, #'0'   ;umwandlung in Ziffer
    call  ausgabe_char ;2 ausgeben
    mov   a, #'.'
    call  ausgabe_char  ;. ausgeben
    ;b hat noch den Wert 58H!
    mov   a, #100
    mul   ab        ;a=60H , b=22H
    mov   a,b
    call  ausgabe_dezimal ; 22H -> 34


So sollte die Umrechnung und Ausgabe funktionieren.


@David und Renè
So ein ähnliches Prog schreibe ich zur Zeit auch, nur auf 3 Rechner
verteilt.Labornetzteil, am PC wird Spannung und Strom eingestellt, der
sendet das per COM an einen 8051, der macht die Anzeige und Umsetzung
auf SPI an einen potentialgetrennten 8051 und der steuert AD und DA
Wandler.

@Stephan
Hatte auf arbeit heute keine Zeit, sonst hätte ich das gif gemehlt.

Mit Gruß
Pieter

von Stephan H. (stephan-)


Lesenswert?

@Pieter,
Netzteil...pc gesteuert .... geht standalone ???
Will meins umbauen, deswegen 3fach Anzeige.....
Interessant.....

Code...beeindruckend.......aber für Schüler ???
Deswegen mein 1 Voltabziehschleifenvorschlag... GEILES WORT !!!
ist für die Jungs einfacher zu verstehen....
Kein 16 Bit Wert, keine MUL....völlig EASY.


Also bis denne und guck in Deine Post,
da wartet was mit signierten 12 Bit .

von David und Rene (Gast)


Lesenswert?

Wir sind dann gestern Mittag komplett fertig geworden.

Ich habe den Vorschlag von Pieter benutzt für die Umrechnung.
Ist mir echt ein Rätsel, wie man auf so eine Rechnung kommt.

Vielen Dank nochmal..
David und Rene

von Stephan H. (stephan-)


Lesenswert?

jaja sowas kann Pieter und noch bessere Sachen, da muß auch ich manchmal
überlegen... :-)

von Karl heinz B. (kbucheg)


Lesenswert?

>     call  ausgabe_dezimal ; 22H -> 34
>
> So sollte die Umrechnung und Ausgabe funktionieren.

Stellt aber sicher, dass bei einem Wert von sagen wir
mal 2, die führende 0 auch wirklich mit ausgegeben wird.
Ansonsten wird euch ein Wert von 3.09 als 3.9 ausgegeben
und das ist ganz was anderes.

von Pieter (Gast)


Lesenswert?

moin moin,

>> Ist mir echt ein Rätsel, wie man auf so eine Rechnung kommt.

Bin schreib-faul ;-))

Mit Gruß
Pieter

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.