Hallo ich muss für die Schule eine Präsentation über den 8051 machen und
soll dafür diesen source code erklären:
Da wird das Thema erst heue angefangen haben weiß ich nur sehr wenig
darüber, ich habe schon Erfahrungen mit cpp gemacht und kann daher den
code auch lesen aber was die Funktion von dem code ist verstehe ich
nicht.
Wenn ich den code in in Keil einfüge und ausführen lasse, dann
wiederholt sich die schleife(ist auch eine Endlosschleife ) und geht
nicht weiter als P2
Eigentlich so gut wie alles.
Aber ich versuche es mal herunter zu brechen.
1. was macht die Funktion warte ? Denn sie wird ja eigentlich nie
aufgerufen, da nach dem ersten P2 in der main while schleife schon
schluss ist.
2.Was für einen Sinn hat es diese werte auf null zu setzen wenn ich sie
nicht benutze ?
P0M1=0;
P0M2=0;
P2M2=0;
P2M1=0;
3.Was passiert wenn ich P2 0x01 zuweise und danach die warte Funktion
aufrufe ?
4.Haben die Zuweisungen für P2 eigentlich irgendeinen Sinn oder sind sie
zufällig gewählt worden ?
Sry für die unangenehmen fragen.
Da hast du 2 Möglichkeiten. Das Keil Handbuch zu deren C Erweiterungen
durcharbeiten und hoffen, das dort alle Details beschreiben sind. Oder
im REG932.h nachschauen, wie P0M1 definiert ist und dann im Datenblatt
des Prozessors nachschauen, was diese Zuweisung bewirkt.
Tim B. schrieb:> 2.Was für einen Sinn hat es diese werte auf null zu setzen wenn ich sie> nicht benutze ?> P0M1=0;> P0M2=0;> P2M2=0;> P2M1=0;
Nun, wenn Du Ports benutzen willst, solltest Du erstmal den
entsprechenden Mode einstellen.
Genaueres zu den Ports steht im Usermanual:
https://www.nxp.com/docs/en/user-guide/UM10109.pdf
4.1 Port configurations
Naja irgendwie werde ich nicht schlau aus all den ganzen Tipps, könnt
ihr mir vielleicht einen alternative Quellcode schicken den man als
Anfänger gut verstehen kann ?
So etwas in der Art, jedoch ist das etwas zu simple:
1
#include<reg52.h> // special function register declarations for 89s52
2
#include<stdio.h> // prototype declarations for I/O functions
3
4
sbitLED=P1^0;// defining pin P1^0 as LED
5
6
voiddelay(void);//delay function prototype declaration
Tim B. schrieb:> void warte(int count)> {> while (count--);> }
So ein Unfug wird in der Schule gelehrt? Wie kommt der Lehrer auf das
dünne Brett daß diese Funktion überhaupt Zeit benötigt, daß sie
überhaupt ausgeführt wird? Immerhin hat diese Funktion keinerlei
erkennbare Wirkung, also wird er sie komplett weglassen. Der 30 Jahre
alte Keil-Compiler vielleicht noch nicht aber jeder moderne Compiler
schon!
Solltest besser umgekehrt anpacken.
Zuerst mal ein Tutorial durcharbeiten, wie SFRs überhaupt funktionieren,
warum eine Variable ein IO-Pin ist. Dann die Besonderheiten des Keil
Compilers wie diese Bit-Variablen.
Musst halt lernen, wie du aus Peters Unsermanual die nötigen
Informationen zusammen suchst.
Und warum hat dein Prof diese Themen nicht durch genommen, bevor er so
eine Aufgabe stellt?
Tim B. schrieb:> Wenn ich den code in in Keil einfüge und ausführen lasse,
.. hättest Du eigentlich eine metrische Tonne Warnings bekommen sollen.
Denn da stimmt so einiges nicht im Code.
Beipielsweise passt 60000 nicht in eine Variable vom Typ "int" auf einem
8051. Stichwort: Vorzeichenbehafteter 16-Bit Wert.
Das mit 00011111 sieht auch eher verdächtig aus (Hint: Was macht ein C
Compiler bei führender Null)?
Das Ganze versteht man am Besten wenn man sich mal ein Buch über die
8051 Architektur durchliesst. Vielleicht findest Du was in der
Bibliothek.
Ein Blick in ein C Grundlagen Buch kann auch nicht schaden...
Zunächst mal es gibt einen 8051 Simulator mit dem Du alles laufen lassen
und testen und die Register ansehen kannst:
https://www.edsim51.com/Tim B. schrieb:> 1. was macht die Funktion warte ? Denn sie wird ja eigentlich nie> aufgerufen, da nach dem ersten P2 in der main while schleife schon> schluss ist.
Da ist nicht Schluss: while(1) {} bedeutet alles was da drin ist läuft
endlos.
> 2.Was für einen Sinn hat es diese werte auf null zu setzen wenn ich sie> nicht benutze ?> P0M1=0;> P0M2=0;> P2M2=0;> P2M1=0;
Das sind Register damit werden bei diesem 8051LPC932 für die Pins
zwischen "Open-Drain" und "Push-Pull" Output umgeschaltet. Wenn man das
nicht macht gehen die LEDs nicht.
Den LPC932 gibt es aber schon lange nicht mehr.
Sag doch Deinem Lehrer er soll entweder den 8051 Simulator nehmen oder
einen neuen 8051 z.B.
https://www.silabs.com/products/mcu/8-bit/efm8https://www.silabs.com/products/development-tools/mcu/8-bit/slstk2022a-efm8-busy-bee-starter-kit
Also Dein Codebeispiel ist ja eine theoretische Übung. In der Praxis
würde man das so nicht programmieren...
Hier Dein Code, mit ein paar Kommentaren versehen:
1
// Einbinden der Header-Datei "REG932.h"
2
// Das ist eine Controller-spezifische Datei,
3
// die einen Haufen Definitionen zu Ports,
4
// Special-Function-Registern, etc. enthält.
5
// Wenn Du die Keil Software hast, kannst Du Dir den Inhalt ja anschauen.
6
#include<REG932.h>
7
8
9
// Hier geben wir dem Bit/Pin 0 von Port0 einen Namen.
10
// Damit können wir diesen Pin ab jetzt mit S1 im Programm abfragen.
11
// So wird hauptsächlich der Code lesbarer.
12
sbitS1=P0^0;
13
14
15
16
// Wasserbehälter ohne Warteschleife
17
// Schön, wenn sich die Dozenten solche Analogien einfallen lassen.
18
// Aber eine Schleife gibt es hier trotzdem...
19
// Egal - die Funktion nimmt den übergeben Integer "count" und zählt ihn
20
// runter auf 0. Solange blockiert Dein Programm. Also eine simple
21
// Warteschleife.
22
// Wie lange die Schleife wirklich braucht, hängt von der Taktfrequenz
23
// Deines Controllers ab. Ich meine mich dunkle zu erinnern, dass der 8051
24
// 12 Takte für jede Operation benötigt. Sollte aber in der Keil-Doku stehen
25
voidwarte(intcount)
26
{
27
while(count--);
28
}
29
30
31
32
// Beginn Deiner Hauptfunktion. Diese wird aufgerufen, wenn alle
33
// Initialisierungen oben abgeschlossen sind.
34
voidmain()
35
{
36
// Port 0 konfigurieren
37
// Meiner Meinung nach müsste es P0M0 und P0M1 sein, nicht 1+2, aber egal
38
// Damit wird der gesamte Port0 als quasi-bidirektionaler Port konfiguriert.
39
// Im Grunde werden hier interne Pull-Up Widerstände geschaltet.
40
P0M1=0;
41
P0M2=0;
42
43
// Port 2 konfigurieren
44
// Siehe oben...
45
P2M2=0;
46
P2M1=0;
47
48
// Hier wird der gesamte Port2 auf 0 gesetzt. Die Schreibweise könnte man
49
// verschönern, wenn man es binär als P2 = 0b00000000 notieren würde.
50
// Es wird als jedes der 8 Bits (=Pins) des Ports auf 0 gesetzt.
51
P2=0;
52
53
54
// Beginn der Hauptschleife, in der der Controller verweilen wird,
55
// bis das Programm beendet wird... was jedoch nur im Fehlerfall
56
// geschieht und ohne weitere Maßnahmen den Controller in Trance versetzen würde.
57
//Er liefe, würde aber nix mehr tun.
58
while(1){
59
60
// Hier wird das oben definierte SBit gelesen.
61
// Also geprüft, ob der Pin 0 von Port 0 auf 0 gezogen wurde (z.B. Taster gedrückt)
62
if(S1==0){
63
64
// Wenn ja, dann spielen wir ein bisschen mit Port 2 und
65
// und geben dort ein Muster aus:
66
// 1: 00000000 (+kurze Wartezeit)
67
// 2: 00000001 (+kurze Wartezeit)
68
// 3: 00000011 (+kurze Wartezeit)
69
// 4: 00000111 (+kurze Wartezeit)
70
// 5: 00001111 (+kurze Wartezeit)
71
// 6: 00111111 (+kurze Wartezeit)
72
// 7: 01111111 (+kurze Wartezeit)
73
// 8: 11111111 (+kurze Wartezeit)
74
P2=0x00;
75
warte(60000);
76
P2=0x01;
77
warte(60000);
78
P2=0x03;
79
warte(60000);
80
P2=0x07;
81
warte(60000);
82
P2=0x0F;
83
warte(60000);
84
P2=00011111;
85
warte(60000);
86
P2=0x3F;
87
warte(60000);
88
P2=0x7F;
89
warte(60000);
90
P2=0xFF;
91
warte(60000);
92
93
}
94
else{
95
// Ist der Pin0 von Port 0 jedoch auf 1, wird der gesamte Port 2
96
// auf 1 gesetzt... also binär 0b11111111.
97
P2=0xFF;
98
}
99
}
100
}
Wenn Du das in Deinem Keil-Simlator ausführst, solltest Du also mal das
Monitorfenster für Port0 und Port2 öffnen und schauen, wie sich das
Programm verhält, wenn Du das Häkchen in Port0.0 setzt, bzw. rausnimmst.
Irgendwo gibt es da auch eine Einstellung für den Takt, der simuliert
werden soll. Wenn Port2 also nur flackert, dann setz den simulierten
Quarz Takt mal runter...
Aber wie gesagt - in der Praxis würde man das so nicht programmieren.
Übersehen:
In Deinem Port2-Muster gibt es unter anderem diese Anweisung:
1
warte(60000);
2
P2=00011111;
Das ist syntaktisch nicht korrekt. Glaube ich...
Der Compiler dürfte daraus den Integer Wert 11111 machen, was nicht in 8
bit passt und damit zu einem Überlauf führt.
Es kann aber auch sein, dass der Keil Compiler tatsächlich eine
Binärnotation unterstützt. In dem Fall müsste das aber eigentlich
irgendwie kenntlich gemacht werden. Also z.B. durch 0b00011111 oder
0001111Y
Yanek schrieb:> Das ist syntaktisch nicht korrekt. Glaube ich...
Stimmt
> Der Compiler dürfte daraus den Integer Wert 11111 machen, was nicht in 8> bit passt und damit zu einem Überlauf führt.
Die Compiler die ich kenne interpretieren Zahen mit führender Null als
Oktal-Zahl. Scheint bei Keil auch so zu sein:
http://www.keil.com/support/man/docs/uv4/uv4_db_exp_constants.htm
Yanek schrieb:> // Wie lange die Schleife wirklich braucht, hängt von der Taktfrequenz> // Deines Controllers ab. Ich meine mich dunkle zu erinnern, dass der> 8051> // 12 Takte für jede Operation benötigt. Sollte aber in der Keil-Doku> stehen> void warte(int count)> {> while (count--);> }
Ob die Schleife überhaupt ausgeführt wird und Zeit > 0 braucht hängt in
erster Linie von der jeweiligen Mondphase im Land der Zukunft ab.
Nirgendwo im C-Standard ist garantiert daß das überhaupt irgendein
Verhalten zeigen muß oder bewirken soll, es ist 100% undefined weil 100%
wirkungslos!
Letzten Monat bekam ich Code aus China geliefert von einem namhaften
Halbleiterkonzern und die lernen dort anscheinend den selben Schrott, da
war eine ähnliche Schleife drin ohne jegliche Vorkehrungen und mein
Compiler hat sie einfach vollständig eliminiert weil es nämlich seine
Aufgabe ist(!) unnötig Zeit verbrauchenden Code zu verschlanken und
schneller zu machen!
Also hört endlich auf im Lehrbetrieb mit arglosen Schülern solchen
hochgradig undefined Code kommentarlos zu verwenden als wäre das
akzeptabler Code. Das ist vollkommen inakzeptabel und an Ende gewöhnt
sich der Schüler das noch an und 8 Jahre später fällt es ihm auf den Fuß
und verursacht Millionenschäden!
Tja, so unterschiedlicher Ansicht kann man da sein.
Wenn Du Deinen Compiler stumpf alles vermeintlich überflüssige
wegoptimieren lässt, hattest Du auch nicht gerade den besten Lehrer.
Und auch wenn Du ein so unglaublich geiler Typ bist, dass Du die
Entwickler eines namhaften Halbleiterkonzerns locker in die Tasche
stecken kannst, weil Du Deinen Optimizer so gut konfiguriert hast, gönne
einem Schüler doch bitte auch einen Einstieg in die Materie.
Was soll denn dieses ganze Gedisse immer? Du gehst doch auch nicht in
den Kindergarten und ätzt die Kinder an, weil sie ihre Bauklotzhäuschen
nicht gescheit verfugt haben. Wenn von denen eine(r) mal Maurer wird,
kommt das Thema sicher nochmal auf.
Yanek schrieb:> Wenn Du Deinen Compiler stumpf alles vermeintlich überflüssige> wegoptimieren lässt, hattest Du auch nicht gerade den besten Lehrer.
Es gibt nichts "vermeintlich" überflüssiges. Es ist genau definiert was
das Programm zu tun hat, alles andere ist definitiv überflüssig weil
undefined behavior. Das kann man nicht einsetzen und das bringt man auch
nicht seinen Schülern bei! Wenn Du von "undefined behavior" noch nichts
gehört hast dann hattest Du nicht gerade den besten Lehrer.
Bernd K. schrieb:> Yanek schrieb:>> Wenn Du Deinen Compiler stumpf alles vermeintlich überflüssige>> wegoptimieren lässt, hattest Du auch nicht gerade den besten Lehrer.>> Es gibt nichts "vermeintlich" überflüssiges. Es ist genau definiert was> das Programm zu tun hat, alles andere ist definitiv überflüssig weil> undefined behavior. Das kann man nicht einsetzen und das bringt man auch> nicht seinen Schülern bei! Wenn Du von "undefined behavior" noch nichts> gehört hast dann hattest Du nicht gerade den besten Lehrer.
Bernd du arbeitest doch auch mit dem Keil.
Ich bin mit sicher dass dir ganz genau bekannt ist dass Keil C51 die
delayschleife nicht wegoptimiert. Das mag auf anderen Compilern anders
sein und ich gebe dir prinzipiell auch recht.
Aber der TO ist Anfänger und Schüler. Es bringt also nichts auf solche
Details einzugehen. Viel wichtiger sind die zu grossen Parameter oder
der fehlerhafte Binär Value. Alles andere ist erst mal Spiegelfechterei.
Thomas
Vielleicht liegt der Sinn dieser loop gerade darin, die Schüler auf die
Nebenwirkungen des Optimizers stoßen zu lassen. Sie sollen das Problem
erkennen und eine bessere Lösung finden.
Stefanus F. schrieb:> Vielleicht liegt der Sinn dieser loop gerade darin, die Schüler auf die> Nebenwirkungen des Optimizers stoßen zu lassen. Sie sollen das Problem> erkennen und eine bessere Lösung finden.
Nicht in diesem Land, das kannst du absolut vergessen. Hier geht es nur
um den absolut einfachsten Stumpfsinn.
Hallo,
eigentlich ganz einfach.
Das sieht für mich aus, als ob die ganze Sache mit einem Input Pin
am Port P0 gestartet wird (das ist die Zeile mit sbit S1 ... P0 Dach 0).
Vermutlich negative Logik, da mit if(S1==0) abgefragt wird.
Solange die Taste nicht gedrückt wird, wird der else Zweig mit P2=0xFF
aufgerufen.
Die vielen Zeilen mit P2= ... werden nacheinander ausgeführt.
Das sieht aus wie ein Zähler (erst 0x00 dann 0x01, 0x03 ... ) da werden
vielleicht LEDs an einem Ausgangsport P2 angesteuert (man sollte
vielleicht
einen Schaltplan haben!)
Die Funktion "warte" ist einfach eine Verzögerungsfunktion (die 60000
sind
vermutlich ca. 1 Sekunde - je nach Taktfrequenz).
Gruß, Trossino
Also nochmal zusammengefasst und klargestellt, damit es deutlich wird,
von oben nach unten:
1. Achtung das ist kein cpp code sondern c-code
2. Die Zeile sbit S1 ... deklariert eine Variable mit Namen S1 auf die
Bitadresse des ersten bits, des Ports P0. Beim 8051 geht das, weil der
einen bitadressierbaren Speicher hat. Andere Controller haben das nicht.
Achtung, dieser Code ist daher aber nicht ANSI code konform, d.h. kann
nicht so ohne weiteres auf einen anderen Controller übertragen werden,
aber das spielt für dieses Beispiel ja keine Rolle.
3. Die Funktion warte() ist durchaus sinnvoll. Für Testcode habe ich das
schon oft gemacht, wenn man kein Betriebssystem hat und eine
Wartefunktion braucht, die eine bestimmte variable Zeit (das wird hier
über den Parameter count bestimmt) wartet. Der Compiler optimiert hier
gar nichts weg! Und wenn, dann kann man das über compiler options /
controlls, bestimmen, bis zu welchem Grad die Optimierung geht. Fertig!
Alle anderslautenden Aussagen sind Quatsch!
Allerdings sollte man wissen, mit welcher Taktrate der Controller
getaktet wird, bzw. man sollte sich mal den entstandenen Assembler-Code
ansehen (der 8051 Compiler kann asm files daraus generieren) oder
einfach mal mit dem Oszi messen (Port an-/ausschalten – so mache ich das
immer) wielange die Funktion wartet, bei welchem „count“ Wert. Oder
einfach wie schon vorgeschlagen mal mit dem 8051 Simulator ausprobieren.
4. Die main Funktion ist einfach eine Dauerschleife, die in Abhängigkeit
von dem oben deklarierten Portbit P0.0 zwei Dinge tut: erstens bei P0.0
== 1 nicht viel – da wird nur der P2 Port auf 0xFF gesetzt (alles auf 1)
oder zweitens bei P0.0 == 0 wird eine Kettenreaktion ausgeführt – immer
nacheinander ein Bit des Ports P2 mehr anschalten als zuvor (da hängen
wahrscheinlich LEDs dran an dem Port P2, damit man auch was sieht von
aussen – allerdings wäre es schon sinnvoll, wenn man einen Schaltplan
von dem ganzen hätte! – auf was für einem board läuft das denn?).
und dazwischen ist immer die warte Funktion, vermutlich so ca. 1
Sekunde, sonst würde man nämlich nix sehen ausser allen hell
angesteuerten LEDs
Die Beschreibung von Yanek(Gast) ist gut und auch korrekt!
Ist diese Aufgabe vielleicht die Einserbremse bzw. das Sieb um die
Übergescheiten rauszufiltern ?
Oder wird da geprüft ob man fähig ist geeignete Hilfe zu suchen bzw.
kräftig nachzuforschen ?
Da war ein Artikel (Paywall) wo stand dass jeder zweite Abitur haben
soll - möglicherweise muss da stärker selektiert werden :-)