Hallo zusammen,
ich bin neu hier in diesem Forum und benötige Eure Hilfe !!!
Ich habe im Rahmen einer Projektarbeit folgendes vor:
2 verschiedene, analoge Signale (Messwerte), mit einem MC 80C552 A/D zu
wandeln und einen digitalen Wert dann an eine 2stellige 7- Segment
Anzeige und das andere digitale Signal an LED oder ähnlichem (als
Richtungsanzeige) auszugeben.
Dies stelle ich mir wie folgt vor:
Die Analogkanäle 2 und 4 möchte ich für die Eingangssignale wählen.
die Digitalports 2 und 4 möchte ich als Ausgangsports verwenden.
Ich möchte die Abfrage der Eingangssignale, der A/D Wandlung un der
Ausgabe der Digitalsignal über den internen Taktgeber des MC steuern.
Um die A/D Umsetzzeit zu 'überbrücken', möchte ich jeweils einen
Interrupt setzten.
Die Programmierung möchte ich mit Assembler durchführen und das Programm
mit Keil u Vision 3 schreiben.
Nun meine Fragen an das Forum:
Kann mir jemand sagen, ob ich auf dem richtigen Weg bin ?
Wie kann ich das Interruptsystem geziehlt dazu einsetzen.
- Ganz davon ab, ich bin (noch) nicht der MC- Spezialist !!!-
Ich bedanke mich im Vorraus für Eure Hilfe und warte auf Eure Antworten
!
Grüße,
JoE
JoE schrieb:> Die Programmierung möchte ich mit Assembler durchführen und das Programm> mit Keil u Vision 3 schreiben.
Ich wuerde dir die Programmierung in C empfehlen da du schon den
Compiler dafuer hast.
JoE schrieb:> Um die A/D Umsetzzeit zu 'überbrücken', möchte ich jeweils einen> Interrupt setzten.
Kann man machen, aber einfacher für nen Anfänger ist Pollen.
Oder warte eine feste Zeit.
Dein Programm hat ja nicht viel zu tun.
Schalte den PC aus, nimm Dir Papier und Bleistift und erstelle einen
Programmablaufplan.
Peter
JoE schrieb:> was ist pollen ?
Das regelmaesige Nachfragen ob sich schon was getan hat und wenn ja dann
die Aktion ausfuehren.
JoE schrieb:> leide haben sich unsere Projektlehrer auf diese Prorgammierung> festgelegt,> so dass ich es halt in Assembler machen muss. :-(
Naja die ewig gestrigen Lehrer :=)
Kenne ich auch noch von frueher. Du kannst ja versuchen sie zu
ueberreden.
JoE schrieb:> so dass ich es halt in Assembler machen muss. :-(
Ist auch kein Beinbruch, der 8051 Assembler ist ja sehr komfortabel.
Mit dem DIV Befehl kannst Du den Wert in Einer und Zehner zerlegen.
Und mit MOVC A, @A+DPTR die Ziffer in den 7-Segment Code umwandeln.
Peter
Hallo Peda,
danke aber ich glaube ich habe da irgendwo das Denken eingestellt, bzw.
habe da eine Blockade :-((.
Wie die Befehle sind, weiß ich (glaube ich), aber irgendwie bekomme ich
kein zusammengehöriges, komplettes Programm zusammen.
ich weiß nicht, wie ich die einzelnen Programme verschachtel.
Grüße, JoE
Laaaange her, das sollte gehen. Der AD Wert wird hier auf einem Display
ausgegeben. Dieses wird über ein Schieberegister angesteuert. Damit
solltest du dann schon zurechtkommen.
Hallo JoE,
nimm wie schon weiter oben geschrieben ein Blatt Papier
und zeichne einen Programmablaufplan, "wann soll der µC
was machen, was kommt wann als nächstes".
Ist schon mehr als die Hälfte der Arbeit.
Hier interessier noch nicht mal der Typ des µC besonders.
Dann erst die einzelnen Schritte in C oder Assembler, umsetzen,
die "Dienstvorschrift" schreiben.
Wenn C nicht erlaubt, dann halt Assembler, ist bei derr 8051
Family recht komfortabel, auch das "mischen" von C usd ASM
geht mit dem Keil-Tool sehr gut. (kenne den Vorgänger µVision2)
Hallo Toni,
Du und die Anderen hier im Forum, Ihr schreibt als wäre Assembler zu
programmieren das einfachste der Welt !- Für mich irgendwie nicht :-((
Ich habe da mal ein PDF angenängt, welches zeigt, ei ich mir einen
Ablaufplan vorstelle.
Ws würde mich freuen, wenn Ihr mir weiter helfen könntet.
Grüße,
JoE
Also, habe als Teilprogramme folgendes:
***********Programm 1 = A/D Wandel des ersten Wertes
***********************
Start 1: mov ADCON, #00000001 Rücksetzen des Busy- Flag (ADCS = 0)
mov ADCON, #00001001 Setze Busy- Flag (ADCS = 1), Kanal 1
mov r1,ADCH Digitales Signal an Register 1
ausgeben
************************************************************************
****
******** Binär / BCD- Codierung *******************************
mov r1,a Messwertadresse steht in r1
mov a,@r1 gewählter Messwert steht in a
mov b, #5h skallieren
div ab
r1 a Anzeigewert steht als Dualzahl in a
mob b,#10 Codewandeln in BCD
swap a
orl a,b Anzeigewert steht in BCD in a
mov aus5, a Ausgabe Anzeigewet
********************************Timer 01*******
Start : clr tr0
clr tf0
-----------------------------------------------
mit_t0 anl tmod, # 11110000 b
anl tmod, # 11111100 b
orl tmod, # 00000001 b
mov tl0, # 10101111 b
mov tho, # 00111100 b
----------------------------------------------------------------
set b et0
set b ea0
orl ip1, # 02 h
orl ip0, # 02 h
----------------------------------------------------------------
set b tr0
jmp Start
**************Erstellen Tabelle
*****************************************
; TABELLE
TABELLE:
AJMP stat_00
AJMP stat_08
AJMP stat_10
AJMP stat_18
AJMP stat_20
AJMP stat_28
AJMP stat_30
AJMP stat_38
Fürs erste ist der Ablaufplan schon mal ganz gut.
Einen Fehler habe ich gefunden, die Verzweigung über
"BCD-Zahl Ausgeben".
Bei welcher Bedingung gehts zu "BCD-Zahl Ausgeben",
wann zum Rest des Ablaufs?
Die Teil-Programme sind für mich schon etwas konfus..
Wenn du schon Keils µVision verwendest solltest du mal
in die Beispiele für die 8051 schauen.
Bei der µVision2 (auch in der Demo-Version) sind sehr
viele gute Beispiele dabei.
Beim Programieren sollte man schon wissen was der Befehl
im einzelnen "tut". Besonders bei Assembler.
Ich gebe zu, daß ich auch immer mal wieder nachsehe,
wenn ich mir bei einem Detail nicht ganz sicher bin
(trotz > 25 Jahre Erfahrung).
Nimm ein einfaches Beispiel wie "LED einschalten"
Was passiert das alles hintereinander?
Ruhig mal auch mit Papier und Bleistift "nachspielen"
das erleichtert das Verständnis ungemein.
no_bit_9: mov adc_high_byte,b ;save BIT 9 & 10 in adc highbyte
16
mov adc_low_byte,a ;save BIT 8-2 in adc lowbyte
17
mov a,adcon ;read adcon BIT 0 & 1
18
anl a,#11000000b ;get BIT 0 & 1
19
rl a ;move them to LSB position
20
rl a ;
21
orl a,adc_low_byte ;move them together with BIT 8-2
22
mov adc_low_byte,a ;save adc lowbyte
23
ret ;
2. Berechnen des ADC Wertes:
1
bin_bcd: mov r4,#16d ;16 bit to convert >24<
2
bin2bcd: mov r0,#41h ;get data @ adress 42h,>42h<,40h
3
mov r3,#02h ;3 bytes to convert >03h<
4
clr c ;
5
sort: mov a,@r0 ;
6
rlc a ;red marked values are
7
mov @r0,a ;variables / change them if
8
dec r0 ;you like to make a 16/24/32 bit
9
djnz r3,sort ;routine
10
mov r0,#32h ;result adress 33h-30h >33h<
11
mov r3,#03h ;loop count 8x digits >04h<
12
mul_x2: mov a,@r0 ;
13
addc a,@r0 ;use blue values for a 24 bit
14
da a ;routine
15
mov @r0,a ;
16
dec r0 ;
17
djnz r3,mul_x2 ;
18
djnz r4,bin2bcd ;
19
20
; sort packed bcd result to seperate memory locations
21
22
mov r0,#30h ;load r0 with adress of BCD
23
mov r1,#40h ;load r1 with result adress
24
mov r2,#03h ;loop count 4x digits >04h<
25
bcd_to_ram: mov a,@r0 ;get BCD
26
swap a ;low Nibble <-> high Nibble
27
xchd a,@r1 ;
28
inc r1 ;
29
swap a ;
30
xchd a,@r1 ;
31
inc r0 ; 1000 in " " 45
32
inc r1 ; 100 in " " 44
33
djnz r2,bcd_to_ram ; 10 in " " 43
34
ret ; 1 in " " 42
Nun steht dein Wandlerergebnis im internen RAM an Speicherstelle 45 - 42
in einzelne Ziffern aufgedröselt und das in 10 BIT, 4 Ziffern.
Diese gibtst du nun an ein Display aus. Das kann dein 7-Segement oder
ein beliebeiges anderes sein.
Deine Sprungtabelle kannst du nun dazu nutzen jede einzelne Zahl nach 7
Segment zu codieren.
Noch ein Tipp, dein PAP sollte eine große Schleife sein und das ist auf
deinem Bild nicht so, da gibt es einen Abzweig. Willst du den 2ten Kanal
messen dann gehört das mit in den endless loop.
moin moin,
>>Du und die Anderen hier im Forum, Ihr schreibt als wäre Assembler zu>>programmieren das einfachste der Welt !- Für mich irgendwie nicht :-((
@JoE
nicht verzagen, das ist reine Übungs- und Gewohnheitssache.
Meine Fräsensteuerung ist in MacroAssembler geschrieben und das sind so
ca. 20kB binär. Durch die Macros sind auch 10.000 Zeilen (nicht an einem
Tag geschrieben) noch gut lesbar. Da das selbe Programm auch in Delphi
existiert, kann man auch experimentieren.
Du könntest das Programm ja "erstmal" in C schreiben und testen. Als 2.
Schritt übersetzt DU das Programm in Assembler. Das ist einfacher als
gedacht. Mit einer solchen Vorlage (in C) geht das wirklich gut.
Mit Gruß
Pieter
Mit Keil's µVision geht C->ASM kinderleicht:
Man muß nur den ASM-Output "anfordern".
Wenn es nicht verboten ist liefere den ASM Code so,
sage es aber auch dazu.
Achtung:
Der entstandene ASM-Code wird sofort als aus
"C" entstanden erkannt, weil
- Sprungmarken/Labels einfach durchnumeriert sind
ein Programmierer nimmt "sprechende" Labels
- der ASM Code machmal sehr seltsam ist, es kann am
optimieren liegen, muß aber nicht.
Beispiel: Der 8051 kennt jump-Befehle auf Flags,
"jbs label". In ASM kein Problem. Der Compiler
(wenigstens bei dem µVision2) macht unnötigerweise
daraus: mov c,bit
jc label
Copiert das Bit ins Carry und springt dann.
Will damit sagen, daß man sehr wohl erkennen kann
woher der ASM-Code stammt.
JoE, an Deiner Stelle würde ich jetzt warten, bis Bernd N. das Programm
fertig hat ...
;-)
Folgende Anmerkungen habe ich noch zu dem Ablaufplan - siehe Bild.
Gruß
Jobst
Mahlzeit,
ich habe mich nun entschlossen, die ganze Geschichte über abfragen zu
machen.
Jetzt stehe ich vor dem Problem, wie teile ich dem AD Wandler mit, dass
das analoge Signal z.B. 2,5 V und 1,5 V betragen und er diese mit zwei
Wertebereichen vergleichen soll.
Das unten stehende Programm ist für zwei analoge eingangswerte gedacht.
Eins möchte ich über P4 an einer 2fache 7 Segmentanzeige anzeigen und
ein Signal über 2 LEDs.
moin moin,
>>Jetzt stehe ich vor dem Problem, wie teile ich dem AD Wandler mit, dass>>das analoge Signal z.B. 2,5 V und 1,5 V betragen und er diese mit zwei>>Wertebereichen vergleichen soll.
wo steht den im DB das man dem ADW so etwas mitteilen kann?
Der wandelt bloss. Vergleichen musst Du schon selber.
************Timer************/
Timer: clr tr0
clr tf0
mov tmod, #0001b
mov tl0, #10101111b
mov th0, #00111100b
setb tr0
ret
/************Warte*******************************/
Pause: call timer
der Timer wird eventuell gestartet, ich sehe mal nicht nach ob das so
geht...
...nur der wird nicht warten, denn da fehlt eine Abfrage ob er hat
fertig.
so wie
JB RunTimer0, $
ist dann aber auch nur ein Hammer zum Zeit-tot-schlagen.
Überarbeite erstmal Deinen PAP und gehe dann in die Programmierung.
Mit Gruß
Pieter