Forum: Mikrocontroller und Digitale Elektronik 8051er und Keil


von Oliver D. (smasher)


Lesenswert?

Hallo,

folgendes Problem. In der Schule haben wir vom BK Recklinghausen eine 
8051er Schaltung nachgebaut. Sie arbeitet mit einem IO Warrior für USB 
und ich habe passend dafür einen Downloader, der mir mit beiligernder 
DLL datei den code auf den AT89S52 schreibt.

Mein Problem ist die Programmiersoftware. Ich komme mit Keil absolut 
nicht klar.
Ich habe eine neue Projekt datei angelegt und dann erstellt er mir 
automatisch eine STARTUP.A51.
Vorher habe ich natürlich unter Atmel meinen Prozi ausgewählt.
Naja...
Jedenfalls will ich in C ein einfaches programm schreiben, welches ich 
dann als hex oder bin file rausbekomme.
Daran haperts. Ich habe nämlich keine ahnung worauf ich dafür klicken 
muss...

Achja,
mein Code beispiel währe dazu:
at 0x80 sbit led0;
main
{
for (;;)
led0=0;
}
}

Damit wird eine der LEDs die auf dem Board sind angeschaltet.

Es währ echt cool wenn mir einer hilft, weil schon allein bei meinem 
quellcode fehler angezeigt werden.
Auch kommt oft die Nachricht cant read file.

Naja, vielleicht kennt ihr ja ein einfacheres tool für meine 
programmierarbeit!

Danke!

von Eddy C. (chrisi)


Lesenswert?

Ohne Keil zu kennen, sage ich da fehlt mindestens eine geschweifte 
Klammer und noch ein wenig mehr:

at 0x80 sbit led0;  // Keine Ahnung

void main(void)
{
  for (;;)
  {
    led0=0;
  }
}

von mein Name ist Gast (Gast)


Lesenswert?

Wie wäre es vorher mit einem kleinen C-Kurs,
bevor man die Leute auf uP-Programmierung losjagt?

Ich schlage vor, eines oder zwei der Demo-Applikationen
aus der Keil-Sammlung zu analysieren und daran zu lernen.

von Oliver D. (smasher)


Lesenswert?

mein Name ist Gast wrote:
> Wie wäre es vorher mit einem kleinen C-Kurs,
> bevor man die Leute auf uP-Programmierung losjagt?
>
> Ich schlage vor, eines oder zwei der Demo-Applikationen
> aus der Keil-Sammlung zu analysieren und daran zu lernen.

Ja natürlich. Wie gut, dass auch bei den programmbeispielen der Lehrer 
dieser Fehler bei mir erscheint:
Build target 'Target 1'
compiling test3.C...
TEST3.C(1): error C129: missing ';' before '0x80'
Target not created

Aber die Schüler sind natürlich immer schuld...

Wie währs mal mit konstruktiver hilfe, warum dieser fehler erscheint und 
wie ich ein hex file erzeuge passend für meinen AT 89 S 51

von Peter D. (peda)


Lesenswert?

Oliver D. wrote:
> Mein Problem ist die Programmiersoftware. Ich komme mit Keil absolut
> nicht klar.

Um mal die Begriffe klar zu stellen:

Keil ist der Compiler und der läuft rein auf der Kommandozeile.

Was Du meinst, ist die IDE (µVision), die den einzelnen Programmen die 
entsprechenden Argumente beim Aufruf übergibt.

Man kann entweder die Schalterzeichen direkt eingeben oder aus den 
Optionen auswählen.

Und irgendwo in den Compilereinstellungen hast Du die Einstellung für 
das Ausgabeformat.

Einfach mal durchklicken.

Man kann sogar noch sein eigenes Programmiertool mit eintragen, wenn man 
es gleich nach dem Compilieren in den Chip brennen lassen will.


Peter

von mein Name ist Gast (Gast)


Lesenswert?

Nein, Dein Problem fängt schon viel früher als
bei dem Programmierwerkzeug an.
Es fängt schon bei der Programmierung in C an,
sonst wären Dir die grundlegenden Fehler, auf
die man Dich oben hingewiesen hat, nicht unter-
laufen.

Noch wesentlich gravierender aber, dass der
Lehrer Dich nicht ordentlich in die Nutzung
des Werkzeuges einweist. Klingt so nach "da
hast Du es, mach was draus". Man sollte er-
warten können, dass der Lehrer wenigstens ein
Beispielprogramm beherrscht und schon mal
angesehen hat.

So - jetzt aber zur Sache. ;-)
Schau mal unter
"Projekt" -> "Options for Target ..." -> "Output"
nach und dort
"Create HEX File" markieren.

von Peter D. (peda)


Lesenswert?

mein Name ist Gast wrote:

> Schau mal unter
> "Projekt" -> "Options for Target ..." -> "Output"
> nach und dort
> "Create HEX File" markieren.

Nützt in diesem Fall nichts, der Compiler sagt ja eindeutig:
"Target not created"


Peter

von Oliver D. (smasher)


Lesenswert?

Danke schonmal für das Hex file :)

Das hier ist ein Code beispiel:
/* Quadrat.c: Ausgabe des Quadrats des an den DIP-Schaltern
(Port 2) eingestellten Wertes auf den LEDs (Port 0)
11.2.07 E.Ofenbach */

at 0x80 sfr  P0;           // Adresslage von Port 0
at 0x80 sfr  P2;           // Adresslage von Port 2

void main()
{
code char quadrat[16]={0,1,4,9,16,25,36,49,64,  // Konstante mit 16 
Werten
                   81,100,121,144,169,196,225};  // im Codespeicher
  while(1)
  {
    P2=0xFF;      // P2 vor Auslesen auf H-Pegel
    P0=~quadrat[P2%16];    // Auslesen der Tabelle mit den
            // untersten 4 Bits der DIP-Schalter
  }
}


So habe ich es erhalten und so soll es auch lauefn!

Das Problem in uVision 3 ist aber, das er mir den fehler ausgibt, das er 
ein ";" vor der 0x80 erwartet.

von Peter D. (peda)


Lesenswert?

Oliver D. wrote:

> at 0x80 sfr  P0;           // Adresslage von Port 0
> at 0x80 sfr  P2;           // Adresslage von Port 2

> Das Problem in uVision 3 ist aber, das er mir den fehler ausgibt, das er
> ein ";" vor der 0x80 erwartet.

Da hatter recht, das ist keine standard C-Syntax.

Warscheinlich ist das Programm für nen anderen Compiler geschrieben.
Versuch mal statt dessen:
1
#include<reg51.h>

Dann kennt der Keil die Ports P0...P3 (und alle anderen SFRs).


Peter

von Horst Gschwandtner (Gast)


Lesenswert?

at 0x80 sfr P0;            ?????

habe ich noch nie versucht, schein mir aber etwas komisch formuliert zu 
sein. Ich arbeite seit Jahren mit Keil C51, schreibe aber immer

sfr P0 = 0x80;

Ich bin mir eigentlich sicher, dass dies die einzig richtige 
Schreibweise ist.

mfg
Horst

von Oliver D. (smasher)


Lesenswert?

TEST.C(4): error C129: missing ';' before '0x80'

Der fehler bleibt trotz der neuen weiter bestehen.

Muss ich vielleicht noch irgendwo anders im Keil etwas umstellen?

Einfache Programme wie z.b. Print f erkennt er ja einwandfrei.
Nur ebenhalt das mit den special function registern nicht.

von Horst Gschwandtner (Gast)


Lesenswert?

bei sbit funktioniert es wie folgt:

sbit LED_XY = P1^1;

von mein Name ist Gast (Gast)


Lesenswert?

@Peter
Die Sache mit dem Huhn und dem Ei.
Ohne die Konfiguration gibt es auch mit fehlerfreiem
Quelltext keinen Hex-Output.

@Oliver:
zum C-Code mit der LED...
An welchem Port hängt die LED und ist sie gegen Masse
oder gegen VCC verdrahtet?
Port P0 ist eine nicht unbedingt glückliche Wahl.

Wenn die LED z.B an Port P0 Bit 0 hängt, würde ich bei
"gegen Masse" so codieren:

#define LED0 = 0x01;

void main(void)
{
  for (;;)
  {
    P0 |= LED0;
  }
}

Wenn gegen VCC dann:

    P0 &= ~(LED0);

Wobei P0 in der Device-include-Datei definiert ist.

von mein Name ist Gast (Gast)


Lesenswert?

sri, #define ... natürlich ohne das Semikolon am Ende ;-)
bevor hier wieder Steine geworfen werden

von mein Name ist Gast (Gast)


Lesenswert?

Dieses "at sfr ..." solltest Du ersatzlos weglassen
können, denn die Ports sind in der Regel in der
Device-include-Datei vordefiniert.

Was Du definieren musst, ist LED0.
Entweder wie in meinem Beispiel mit
#define und einer "Bitmaske"
oder alternativ durch direkte Bit-Zuordnung mit
sbit LED0 = P0^0;
Dann aber dort wieder mit Semikolon am Ende. ;-)

Die Variante mit "sbit" läuft meines Wissens nur bei
bit-adressierbaren Registern. P0 ist bitaddresierbar.

Dein Beispiel mit Quadrat.c legt die Variante mit
Bitmaske - also #define LED0 = 0x01 - nahe.

von Oliver D. (smasher)


Lesenswert?

Also folgenes.
Die LEDs sind an Port 0 angeschlossen und liegen an VCC and und gehen 
über einen Widerstand an Port 0.

Wie ich gerade beim lesen der Help function in Keil festgestellt habe, 
ist die schreibweise:
at 0x80 sfr led0;
wohl falsch zum definieren des ports.
Das hier ist laut handbuch die richtige:
sfr P0 = 0x80; (wie mir ja schon jemand anderes nettweise geschrieben 
hat :) )


Nun denn,
mich würde interessieren wie denn ein Programm code auszusehen hat, der 
funktioniert und einfach an 0x80 eine 1 schreibt.

Welches .h dateien muss ich per include laden?

ansonsten ja:

sfr P0 = 0x80;
main (void)
{
for (;;)

PO=0;
}

Wobei eigentlich das Void unsinn ist, denn auf dem MC ist kein 
betriebssystem oder anderes programm, an das rückgabewerte gegeben 
werden können. Ebenso muss das ganze laut meinem lehrer in eine 
schleife, weil wohl sonst immer der gesamte speicher durchlaufen wird 
uns mist rauskommt.

Also, währ das code beispiel so ok? Achja, muss es P0 (Null) oder PO 
(Buchstabe O) heissen?

von mein Name ist Gast (Gast)


Lesenswert?

Es handelt sich um P "Null", also P0, P1, P2 usw.

Um das Bit Null in Port PNull auf "1" zu setzen:

P0 |= 0x01;

Dein Beispiel setzt das komplette Port P0 auf "0".

Es geht auch
 P0 = 0x01;
Aber dann werden die restlichen 7 Bits des Ports auf "0"
gesetzt.
Die Variante oben manipuliert nur das Bit Null im Port Null.

von Oliver D. (smasher)


Lesenswert?

Also grad blick ich garnicht mehr durch.

Die LEDs sind am P0.0-P0.7 angeschlossen gegen VCC.

So,
nun will ich gerne mal ein komplettes Programmbeispiel haben.
Laut lehrer ist es ein SFR und einzelne Bits sind mit sbit anzusprechen.
Alle beispiele die ich bisher ausprobiert habe funktionierten nicht. 
Beim schreiben auf den MC brach die software immer ab, wobei programme 
ohne sfr funktionieren.

Also mal bitte ein komplettes beispiel. Die adresse des SFR ist übrigens 
0x80 bzw. 0x81, 0x82...

von mein Name ist Gast (Gast)


Lesenswert?

Für dieses Mini-Programm braucht Du keine Header-Datei.
Auch ein include der sfr-Dateien des Prozessors ist
nicht erforderlich, da Du den Prozessor-typ in der
Projektumgebung schon festgelegt hast.
In der STARTUP-Datei stehen die Prozessor-typischen
Definitionen schon drin. Nach meinen Erfahrungen leider
nicht immer fehlerfrei und auch nicht vollständig.
So tief in die Materie dringt Dein Beispielprogramm
jedoch nicht, dass man darauf ein Auge halten müsste.

von Oliver D. (smasher)


Lesenswert?

Also sieht der code nur so aus :


sbit led = 0x80;

void main(void)
{
  for (;;)
  {
   led=0;
  }
}

krass, es funktioniert.


Kannst du mir vielleicht erklären, warum gerade lehrer, die alles 
sinvoll und einfach und verständlich gestalte sollen, so einen scheiss 
verzapfen?

Das Programm funtkioniert gerade einwandfrei bei mir. Led 0 leuchtet 
freu

Gibts vielleicht ne seite wo alles ordentlich erklärt ist, mit den 
aktuellen C standards und ohne fehler?

von mein Name ist Gast (Gast)


Lesenswert?

sfr P0 = 0x80; // kann eventuell entfallen

main (void)
{
  P0 = 0xFF;   // alle I/Os an P0 auf high (= LEDs aus)
  for(;;)
    P0 = 0xFE; // P0.0 = low  (= LED0 an)
}

von mein Name ist Gast (Gast)


Lesenswert?

ja, Oliver - Deine Variante geht auch
allerdings "floaten" die anderen 7 LEDs dann wegen der
weak pullups an P0
daher vor dem "for(;;)" noch einfügen:
P0 = 0xFF; // Port 0 auf Output

von mein Name ist Gast (Gast)


Lesenswert?

Ja, solche Lehrer habe ich auch "gefressen".
Kennen das Werkzeug nicht, haben es nicht einmal vorher
ausprobiert ob es läuft und sind aber in der Lage, die
Arbeit dann zu bewerten...
Trifft man mehr und mehr.
Das Übel fing an mit der Umwandlung von Informatik-Kursen
in Internet-Kurse; von sachkundigen Grundlagen in "bunte
Bilder klicken".

von Oliver D. (smasher)


Lesenswert?

Hmm,

also mal ne andere frage,

wieso schreibt ihr noch:
P0 = 0xFF;   // alle I/Os an P0 auf high (= LEDs aus)
bzw.
P0 = 0xFF; // Port 0 auf Output

mit in den code?
Bei mir gehts auch ohne das.
Ich lege einfach nur
sbit led0 = 0x80;

void main(void)
{
  for (;;)
  {
   led0=0;
}
}

Und das Programm läuft.
Könnt ihr mir das noch erklären ?


Achja, zu den Lehrern...auf meiner Realschule hatte ich so einen "bunte 
bilder" klicken lehrer. Ausser Word und Excel lernt man da eigentlich 
garnix. Er wollte dann mit uns PHP anfangen, allerdings scheiterte 
dieses vollkommen ;)

von mein Name ist Gast (Gast)


Lesenswert?

Falls Du noch "spielen" willst, die Werte für die anderen
LEDs sind

0x81, 0x82, 0x83, 0x84, 0x85, 0x86 und 0x87

Also die Basis-Adresse des Port P0 mit 0x80 plus den
Werten 0x00..0x07 für die I/O-Anschlüsse des Port P0.

Es ist eine kleine Übung, mit diesen Adressen in einer
Schleife ein Lauflicht zu erzeugen.

von mein Name ist Gast (Gast)


Lesenswert?

Das mit dem P0 = 0xFF ist eine 8051-spezifische Sache.
Die Ports bei den 8051-Prozessoren arbeiten i.d.R. in
beide Richtungen. Für Eingangsignale haben sie intern
einen "schwachen" Pull-Up-Widerstand. Will man die
Ports für Ausgang nutzen, empfiehlt der Hersteller,
mit 0xFF in den Port-I/Os einen "starken" Pull-Up-
widerstand zu aktivieren.
Ohne dieses 0xFF "lavieren" die Ausgangsspannungen der
Ports. Zum Beispiel kann man dann die LEDs durch
Finger-Berührung schon von außen zum Leuchten bekommen;
mal so blind behauptet - ausprobiert habe ich es nicht
und hängt wohl auch vom Prozessor ab.

Mit jeder Zeile mehr riskiere ich, von den Anderen
gesteinigt zu werden - es geht ein wenig rüde zu in
diesem Forum. Daher soll das genügen. ;-)

von Peter D. (peda)


Lesenswert?

mein Name ist Gast wrote:
> Das mit dem P0 = 0xFF ist eine 8051-spezifische Sache.
> Die Ports bei den 8051-Prozessoren arbeiten i.d.R. in
> beide Richtungen. Für Eingangsignale haben sie intern
> einen "schwachen" Pull-Up-Widerstand. Will man die
> Ports für Ausgang nutzen, empfiehlt der Hersteller,
> mit 0xFF in den Port-I/Os einen "starken" Pull-Up-
> widerstand zu aktivieren.

Nenn mir mal den Hersteller, der so einen Unsinn empfiehlt.

Der P0 hat kein Pullups, der floatet immer, wenn er high ist.

Und es gibt auch keine trinäre Logik im 8051, d.h. die Pullups an P1..P3 
werden nicht "upper", wenn man nochmal 0xFF reinschreibt.

Nach dem Reset sind alle Ports 0xFF und gut is.


Peter

von Oliver D. (smasher)


Lesenswert?

Hmm, werden denn die Ports wirklich als ausgang genutzt? Also messen
will ich damit natürlich nix.
Ich brauche nur eine logische 0 an den ports, wo es leuchten soll, damit 
von VCC über die LEds und den widerstand ein strom fliesst. Wenn ich 
also eine
1 am Port habe, dann leuchtet nix.
(denn dann währe der potentialunterschied ja 0V)
Egal,
hauptsache ich bin schonmal soweit das sich was tut ;)


Gibts denn irgend ne Seite wo das alles so beschrieben ist?
Mit programmbeispielen?
Oder irgend ein gutes buch?

von mein Name ist Gast (Gast)


Lesenswert?

Wo Peter Recht hat, hat er Recht.
Ein starker Pull-Up wird nur bei einem 0-auf-1-Übergang
für kurze Zeit zugeschaltet und das auch nur bei Ports
wie P1, P2 und P3. Bei Port P0 - dass dieser ein Sonder-
fall darstellt hatte ich schon angedeutet - werden
mit Ausgabe 0xFF die Open-Drain-Ausgänge auf "floaten"
geschaltet.

Die Anweisung P0 = 0xFF ist entbehrlich.
Es ist Geschmacksache - ich würde sie trotzdem einfügen,
alleine, um bewusst Port P0 in einen definierten
Zustand zu setzen (Kommentar "alle LEDs aus") und nicht
auf Annahmen zu bauen. Profis brauchen solche Gedanken-
stützen natürlich nicht; für Anfänger würde ich argumen-
tieren "es schadet nicht".

Es darf gemäkelt werden.

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.