Forum: Mikrocontroller und Digitale Elektronik Probleme bei µC Programmierung mit Klassen und Pointer


von Sascha K. (quad2000)


Lesenswert?

Hallo an alle,

ich muss ein Projekt verwirklichen, das die Programmierung eines µC 
(Atmel 89C51CC03) beinhaltet.
Als Compiller verwende ich Kyle µVision 3.
In diesem Projekt muss ich zum ersten mal mit Klassen und Ponter 
Arbeiten.

Wenn ich nun mein Code übersetzen lasse, bringt mir Kyle ein Fehler, den 
ich nicht beseitigen kann.
Hier mein Programm das sehr einfach gehalten ist. Es dient lediglich 
dazu, Klassen und Pointer zu verstehen und anwenden zu können:




#include "at89c51cc03.h"
#include <stdio.h>

class ADC
{
private:

public:
    ADC()                        //Konstruktor
    {
    }

    Berechnung (int *a)         //Funtkion Berechnung
    {
      *a++                      //Wert in a um 1 erhöhen
    }

    ~ADC()                       //Destruktor
    {
    }
};

void main()
{

  while (1)                     //Endlosschleife
  {
   int a;                       //Variable a als int initalisieren
   a=0;

   ADC ADCclass;                //Der Klasse ADC ein Namen zuweisen
   ADCclass.Berechnung(&a);     //Funktion Berechnung aufrufen

   P1=0x33;                     //Wert 33 an Port 1 ausgeben
   P3=a;                        //Wert aus a an Port 3 ausgeben
   }
}




Fehlerbeschreibung laut Kyle:
main.c(7): error C129: missing ';' before 'ADC'
(Klasse ADC wird mit Pfeil angezeigt)

Kann mir jemand bei diesem Problem helfen?
Habe ich die Pointer richtig eingesetzt?

Vielen Dank für die Hilfe.

von Karl H. (kbuchegg)


Lesenswert?

Sascha K. wrote:

> main.c(7): error C129: missing ';' before 'ADC'
  ******

Eine Datei mit der Endung *.c wird von den meisten Compilern
als C-Source Code betrachtet. In C gibt es aber keine Klassen
bzw. was du willst ist eigentlich der C++ Compiler.

-> Im Handbuch des Compilers nachsehen, wie du ihn dazu bringst
das ganze als C++ aufzufassen. Bei vielen Compilern genügt
es die Dateiendung auf *.cpp zu ändern.

> Habe ich die Pointer richtig eingesetzt?

Grundsätzlch ja.

von Andreas K. (a-k)


Lesenswert?

Wenn du nicht Kyle sondern Keil meinst: Von C++ steht da nichts, das ist 
ein C Compiler.

von Peter D. (peda)


Lesenswert?

Sascha K. wrote:
> Als Compiller verwende ich Kyle µVision 3.

Noch nie davon gehört, haste mal nen Link darauf?

Ich kenne nur Keil µVision 3 für 8051.

Und da bin ich mir zu 99,9999% sicher, daß der garkein C++ kann.


Peter

von Sascha K. (quad2000)


Lesenswert?

Danke für die schnelle Antwort.

Ja ich meine Keil µVision3. Habe es falsch geschrieben.

Ok dann wird es klar warum es nicht funktioniert.

Danke nochmal.

von Matthias Kölling (Gast)


Lesenswert?

Mußt Du jetzt mit Klassen arbeiten oder genau diese Entwicklungsumgebung 
verwenden?

von die ??? (Gast)


Lesenswert?

1
  Berechnung (int *a)
2
  {
3
     (*a)++;
4
  }

Semikolon fehlt. Keil µV3 ist eine IDE, welchen Compiler benutzt du?

von Sascha K. (quad2000)


Lesenswert?

Ich schreibe mein Programm in Keil µVision 3 und zur Übertragung auf 
mein AT89C51CC03 verwende ich das Tool Flip von Atmel.

Ich muss nicht unbeding mit Klassen Arbeiten. Funktionen genügen auch.
Ich wollte aber Testen, ob es mit Klassen funktionieren würde damit ich 
ein besseres Verständniss für die ganze Thema bekomme.
Ich wollte wissen, was funktionieren würde und was nicht. Das Keil kein 
cpp kann wusste ich nicht.

Nun habe ich aber eine andere Frage: Kann ich hier überhaupt mit Pointer 
arbeiten?
Der hintergrund sieht so aus:
Der µC hat 8 interne AD Wandler. Die Wandlung wird in einer Funktion 
realisiert.
Ich will nun aus meinem main auf die gewandelten Werte in der Funtion 
zugreifen. Das wollte ich über Pointer machen.
Ist das überhaupt möglich?

Entschuldigung für die vielen Fragen aber ich will das Thema selber 
kapieren und mir nicht die Lösung irgendwo her holen.

@die ???
Danke für Info bezüglich dem Semikolon. Das hat aber auch keine Änderung 
ergeben.

von Carlos (Gast)


Lesenswert?

Hallo Sascha,
Du kannst doch mit Funktionen mit Übergabewert (=Kanal-Nr) und 
Rückgabewert (=Messwert) arbeiten, wenn Du die Kanäle einzeln 
nacheinander wandelst.
Willst Du in der Funktion alle Kanäle auf einmal wandeln, dann nimm 
einfach globale Variablen(Feld) zum Abspeichern der Messwerte. Auf diese 
Variablen kannst Du dann von überall her zugreifen.

Viele Grüße
Carlos

von Peter D. (peda)


Lesenswert?

Sascha K. wrote:

> Der µC hat 8 interne AD Wandler. Die Wandlung wird in einer Funktion
> realisiert.
> Ich will nun aus meinem main auf die gewandelten Werte in der Funtion
> zugreifen. Das wollte ich über Pointer machen.
> Ist das überhaupt möglich?


Pointer sind auch in C möglich.

Du kannst allerdings auch einfach den ADC-Wert als Returnwert von der 
Funktion übergeben lassen.

Dann muß der Compiler nicht umständlich mit Pointern rechnen, sondern 
hat den Wert gleich in Registern (R6,R7).


Peter

von Sascha K. (quad2000)


Lesenswert?

@Peter
Return Wert geht leider nicht weil ich in der Funktion mehrere 
Rückgabewerte habe.

@Carlos
Ich würde gerne die gesammte Wanndlung in einer Funktion haben. Dann 
gestaltet sich die Rückgabe etwas schwerer.
Globale Variablen wären mir am liebsten. Das habe ich auch schon 
getestet aber habe es nicht zum laufen gebracht.

Mein Problem ist, das ich bis jetzt nur in Visual Studio gearbeitet habe 
und Werte über das Ausgabefenster angezeigt habe.
Das Programmieren für µC ist doch etwas anderst. Oft sind es nur 
Kleichnichkeiten aber die machen es eben aus.

So nun mal ein Beispiel von mir zu Pointer das aber so leider
nicht läuft:


#include "at89c51cc03.h"
#include <stdio.h>

unsigned int value_AN3=0x0000;

extern void umwandlung (int);


void main(void)
{
  while(1)
  {
  umwandlung(&value_AN3);
  P3=value_AN3;
  }
}


Nun die Ausgelagerte Funktion (AD Wandlung meines µC)


#include "at89c51cc03.h"
#include <stdio.h>

unsigned int value_converted=0x0000;
bit end_of_convertion=0;

void umwandlung (int *value_AN3){

ADCF = 0xFF;
ADCLK = 0x06;
ADCON = 0x20;
EA = 1;
EADC = 1;

ADCON &= ~0x07;
ADCON |= 0x06;
ADCON &= ~0x40;
ADCON |= 0x08;
while(!end_of_convertion);
end_of_convertion=0;
*value_AN3=value_converted;
}


Diese Funktion ist so vom Hersteller vorgegeben aber ich kann sie an 
meine Ansprüche anpassen.

Den Namen der Funktion umwandlung habe ich selber vergeben.

Die ganze AD Wandlung funktioniert so. Das habe ich schon getestet (ich 
arbeite dann mit Rückgabewert)
Aber sobald ich mit Pointer Arbeite (siehe oben) funktioniert es nicht 
mehr.

von Karl H. (kbuchegg)


Lesenswert?

Sascha K. wrote:

> Ich würde gerne die gesammte Wanndlung in einer Funktion haben. Dann
> gestaltet sich die Rückgabe etwas schwerer.
> Globale Variablen wären mir am liebsten. Das habe ich auch schon
> getestet aber habe es nicht zum laufen gebracht.

? Da muss ich mich aber schon wundern. Globale Variablen sind so
ziemlich das Primitivste was man sich vorstellen kann.

> Mein Problem ist, das ich bis jetzt nur in Visual Studio gearbeitet habe
> und Werte über das Ausgabefenster angezeigt habe.
> Das Programmieren für µC ist doch etwas anderst. Oft sind es nur
> Kleichnichkeiten aber die machen es eben aus.

Nicht wirklich. Die grundlegenden Mechanismen, wie Parameterübergabe,
Werte retournieren funktionieren auf allen C-Systemen gleich. Muss
auch so sein, denn schliesslich ist die Sprache ja genormt.

> Aber sobald ich mit Pointer Arbeite (siehe oben) funktioniert es nicht
> mehr.

Vergleich mal Folgendes:

In main.c steht:
1
extern void umwandlung (int);
Dort wird also behauptet, die Funktion umwandlung bekommt einen int
übergeben.

In deinem 2-ten File steht aber
1
void umwandlung (int *value_AN3)
Die Funktiohn umwandlung will einen Pointer auf int.
Was gilt den nun? Die Funktion kann ja nicht gleichzeitig
wahlweise einen int oder einen Pointer auf int erhalten.

Wenn du deinen Compiler anlügst, darfst du dich nicht wundern ...

Wie kann programmieren, dass man so einen Fehler kein 2-tes mal
macht?
Die Lösung dafür sind Header Files.
Du schreibst den Protoyp nicht direkt in main.c hinein, sondern
ziehst ihn über ein Header File hinein.

Umwandlung.h
************
1
void umwandlung (int *value_AN3);

(Das extern braucht an dieser Stelle kein Mensch)

main.c:
*******
1
#include "at89c51cc03.h"
2
#include <stdio.h>
3
#include "umwandlung.h"  // <---- hier kommt der Protoyp für die Funktion
4
5
unsigned int value_AN3=0x0000;
6
7
void main(void)
8
{
9
  while(1)
10
  {
11
  umwandlung(&value_AN3);
12
  P3=value_AN3;
13
  }
14
}

und ganz wichtig: In deinem File, in dem die Funktion residiert,
ziehst du ebenfalls den Protoypen rein.
1
#include "at89c51cc03.h"
2
#include <stdio.h>
3
#include "umwandlung.h"     // <--- hier ebenfalls der Protoyp
4
5
unsigned int value_converted=0x0000;
6
bit end_of_convertion=0;
7
8
void umwandlung (int *value_AN3){
9
10
ADCF = 0xFF;
11
ADCLK = 0x06;
12
ADCON = 0x20;
13
EA = 1;
14
EADC = 1;
15
16
ADCON &= ~0x07;
17
ADCON |= 0x06;
18
ADCON &= ~0x40;
19
ADCON |= 0x08;
20
while(!end_of_convertion);
21
end_of_convertion=0;
22
*value_AN3=value_converted;
23
}

Dadurch kann der Compiler vergleichen, ob der Protoyp mit der
tatsächlichen Funktion übereinstimmt und gegebenenfalls einen
Fehler melden.

von Peter D. (peda)


Lesenswert?

Karl heinz Buchegger wrote:
> Sascha K. wrote:
>
>> Ich würde gerne die gesammte Wanndlung in einer Funktion haben. Dann
>> gestaltet sich die Rückgabe etwas schwerer.
>> Globale Variablen wären mir am liebsten. Das habe ich auch schon
>> getestet aber habe es nicht zum laufen gebracht.
>
> ? Da muss ich mich aber schon wundern. Globale Variablen sind so
> ziemlich das Primitivste was man sich vorstellen kann.


Auch haben Probleme, vor denen man davonläuft, die unangenehme 
Eigenschaft, einen ständig wieder einzuholen und dabei jedesmal größer 
zu werden.


Globale Variablen müssen funktionieren, das sind Grundlagen ohne die Du 
das Programmieren gleich an den Nagel hängen kannst.

Frag ruhig, wenn Du eine Fehlermeldung nicht verstehst.


Peter

von Sascha K. (quad2000)


Lesenswert?

@ Herr Karl heinz Buchegger

Vielen Dank für ihre Hilfe.
Mit einer Headerdatei funktioniert alles wunderbar.
Vielen Dank für ihre Infos und Tipps.
Ab jetzt Arbeite ich immer mit Header.

@ Herr Peter Dannegger

Ich werde mich an die globalen Variablen machen.
Ich werde ein paar Übungen programmieren um mich damit vertraut zu 
machen.
Aus meinem main konnte ich auf die globalen Variablen zugreifen.
Ich hatte aber Probleme, wenn ich von meinen ausgelagerten Funktionen 
darauf zugreifen wollte.

von Karl H. (kbuchegg)


Lesenswert?

Im Grunde ist das sehr simpel, wenn man eine Regel beachtet:
Es darf immer nur eine Definition einer globalen Variablen geben.
Die muss es dann aber auch geben.
Mittels extern teilt man dem Compiler mit, dass eine Variable
irgendwo anders existiert, aber diesen und jenen Datentyp
hat. So was ist dann eine Deklaration. Und davon darf es beliebig
viele geben.

Bsp:

foo.c
*****
1
extern int Var1;    // Var1 existiert und ist vom Typ int
2
3
void foo()
4
{
5
  Var1 = 5;         // da der Compiler weiß, dass es Var1 gibt
6
                    // geht das auch gut. Var1 existiert (könnte
7
                    // ja auch ein Tippfehler sein) irgendwo anders
8
}

main.c
******
1
int Var1;          // und hier existiert die Variable Var1 tatsächlich
2
3
void foo(void);
4
5
int main()
6
{
7
  Var1 = 0;
8
  foo();           // foo setzt Var1 auf 5
9
}

Auch globale Variablen sind heisse Kandidaten für Header Files
denn eines muss klar sein. Die Definition und die Deklaration
müssen unbedingt im Datentyp übereinstimmen!
In der Praxis macht man das dann so

global.h
********
1
extern int Var1;

foo.c
*****
1
#include "global.h"     // dadurch bekommt man die Deklaration
2
                        // von Var1 hereingezogen
3
4
void foo()
5
{
6
  Var1 = 5;
7
}

main.c
******
1
#include "global.h"     // bringt wieder die Deklaration herein
2
                        // bis jetzt existiert die Variable
3
                        // aber noch nicht. Das wird jetzt
4
                        // nachgeholt
5
int Var1;
6
7
void foo(void);
8
9
int main()
10
{
11
  Var1 = 0;
12
  foo();
13
}

Dadurch, dass in main.c wiederrum beides vorhanden ist, Deklaration
und Definition, gibt man dem Compiler wiedrrum die Möglichkeit zu
überprüfen, ob beides übereinstimmt.

von Sascha K. (quad2000)


Lesenswert?

Das ging aber sehr schnell. Vielen Dank.
Ich hab ein ähnliches Beispiel wie Sie geschrieben mit Header. Jedoch 
ohne das extern bei int Var1.
Aus diesem Grund hatte ich Fehlermeldungen und das Programm lief nicht.
Nach dem ich ihren Beitrag gelesen habe, habe ich einfach das extern 
hinzugefügt und es lief.
Ich möchte mich nochmals bei Ihnen für die schnelle und sehr gut 
beschriebene Hilfe danken.

von Sascha K. (quad2000)


Lesenswert?

Ich habe jetzt einiges an meinem Programm verändert.
Dabei bin ich jetzt noch auf etwas gestoßen.

Beispiel:

header.h
********
extern unsigned int ch0;


main.c
******
#include <header.h>

void main ()
{
    funktion (&ch0)
}

Ich will eine Variable (ch0) im header als globale Variable 
initialisieren.
Im main will ich per Pointer die Variable ch0 an eine Funktion 
weitergeben.
Nun bekomme ich aber ein Warnung und das Programm ist nicht lauffähig.
Ist es überhaupt möglich, eine globale Variable über ein Ponter im main 
an eine ausgelagerte Funktion weiter zu geben?

von Karl H. (kbuchegg)


Lesenswert?

Sascha K. wrote:
> Beispiel:
>
> header.h
> ********
> extern unsigned int ch0;
>
>
> main.c
> ******
> #include <header.h>
>
> void main ()
> {
>     funktion (&ch0)
> }
>
> Ich will eine Variable (ch0) im header als globale Variable
> initialisieren.

Du hast im Header keine Variable definiert. Du hast im Header
lediglich bekannt gegeben, dass irgendwo eine derartige
Variable existieren würde.

Allerdings hast du in deinem Programm anscheinend vergessen,
die Variable auch tatsächlich anzulegen. Es reicht nicht
immer nur zu sagen, dass diese Variable schon irgendwo existieren
würde. Irgendwann muss sie auch tatsächlich erzeugt werden!
Aus Mangel an besseren Plätzen: Warum nicht im main.c

main.c
******
1
#include <header.h>
2
3
unsigned int ch0;
4
 
5
void main ()
6
{
7
    funktion (&ch0)
8
}



> Nun bekomme ich aber ein Warnung und das Programm ist nicht lauffähig.

Es ist schon spät und meine Glaskugel ist schon abgeschaltet.
Verrätst du uns noch den Wortlaut der Warnung?

> Ist es überhaupt möglich, eine globale Variable über ein Ponter im main
> an eine ausgelagerte Funktion weiter zu geben?

Sicher. Warum sollte das nicht gehen. Eine globale Variable ist
auch nur eine Variable. Und als solche hat sie eine Adresse im
Speicher.

von Sascha K. (quad2000)


Lesenswert?

Hallo Herr Buchegger,

das war wirklich das Problem. Ich hatte keine Variable direkt angelegt.
Ich dachte es würde reichen, wenn ich sie im Header anlege.

>Es ist schon spät und meine Glaskugel ist schon abgeschaltet.
>Verrätst du uns noch den Wortlaut der Warnung?

Ich habe mit Absicht keine Fehlermeldung angegeben.
Ich wollte nur die Antwort auf meine obige Frage
(Ist es überhaupt möglich, eine globale Variable über ein Ponter im main
an eine ausgelagerte Funktion weiter zu geben?) und dann selber den
Fehler finden und mein Programm verbessern.
Meine Meinung ist, das man sowas nur richtig lernen und vorallem
versetehen kann, wenn man es selber macht. Wenn man die Lösung von
anderen bekommt, ist der Lerneffekt viel geringer als wenn man es selber
macht.

von Peter D. (peda)


Lesenswert?

Sascha K. wrote:
> Ich habe mit Absicht keine Fehlermeldung angegeben.

Wenn Du diese im Original posten würdest und dazu das File im Anhang,
damit man die Zeilennummer zuordnen kann, dann:

1. bekommst Du schneller und besser Hilfe.

2. lernst Fehlermeldungen selber zu deuten.


Peter

von Johnny Maxwell (Gast)


Lesenswert?

> Ist es überhaupt möglich, eine globale Variable über ein Ponter im main
> an eine ausgelagerte Funktion weiter zu geben?

Natürlich, macht aber wenig Sinn, wenn du immer die gleiche globale 
Variable übergeben willst - die aufgerufene Funktion kann auch einfach 
so darauf zugreifen.

Du hast vorher nur C++ programmiert, oder? Schau dir mal C genauer an.

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.