Forum: Mikrocontroller und Digitale Elektronik Verwendung von Ein-/Ausgängen in C-Unterfunktion


von Bastian B. (hobby-pic)


Lesenswert?

Hallo,

ich möchte in einer C-Unterfunktion wechselnde Ein-Ausgangswerte 
verarbeiten.

Definiert ist z.B. ein Eingang im main.c
1
#define  IN2      PORTAbits.RA1

Diesen möchte ich in einer Funktion für eine Operation abfragen.

"25:Error [1105] symbol 'IN2' has not been defined" ist die Antwort beim 
Übersetzen. IN2 ist demnach nur im Main definiert.

Ist es gundsätzlich nicht möglich einen Eingang in einer Unterfunktion 
zu nutzen?

Danke,
Basti

von Peter D. (peda)


Lesenswert?

#define gehören in der Regel in ein *.h.
Und jeder, der es benutzen will, includet es.

Peter

von heinz (Gast)


Lesenswert?

Wo steht denn deine Unterfunktion - wahrscheinlich in einer anderen 
c-Datei? Und was meinst du mit Unterfunktion überhaupt?
Als Stichwort für google: Headerfile


Grüße

von Hubert (Gast)


Lesenswert?

Also ich habe es genauso gemacht wie du: Eingänge am Anfagn der main.c 
definiert und ich kann sie später in jeder Unterfunktion beliebig 
abfragen...

LG Hubert

von Bastian B. (hobby-pic)


Lesenswert?

Wahnsinn. Danke. DIe Eingänge werden erkannt.

Ja, die Funktion steht in einer anderen Datei.


Aber was mache ich mit globalen Variablen? Die sind nun das Problem. Die 
Funktion kennt die nicht.

von horst (Gast)


Lesenswert?

Bastian B. schrieb:
> Aber was mache ich mit globalen Variablen?

versuchen, ohne sie auszukommen
der funktion als parameter übergeben
versuchen, sie nur in einer *.c-Datei zu benötigen und dort als static 
deklarieren
dich mit "extern" auseinandersetzen

von Bastian B. (hobby-pic)


Lesenswert?

hm. das klingt schwierig.

Ich möchte nämlich eine globale Variable verwenden, die aus meiner 
Interrupt-Routine hervorgeht... also der Timer Takt.

von Karl H. (kbuchegg)


Lesenswert?

Bastian B. schrieb:
> hm. das klingt schwierig.

Ist es aber nicht.
Du musst dich nur ein wenig mit den Grundlagen auseinandersetzen.

Die erste und wichtigste Grundlage lautet:

# wenn der Compiler ein *.c File übersetzt, dann übersetzt er auch
  nur dieses eine File.
  Was in anderen *.c Files steht, ist zu diesem Zeitpunkt völlig
  uninteressant und kümmert den Compiler nicht die Bohne.

# daraus folgt:
  jedes *.c File muss für sich alleine gesehen in sich vollständig
  sein.

# Jedes *.c File wird von oben nach unten compiliert.
  Daraus folgt: Bevor etwas verwendet werden kann, muss es dem
  Compiler bekannt gemacht werden.
  Es gibt dafür 2 Möglichkeiten
  + Definition
    Eine Definition veranlasst, dass auch im Speicher dafür
    Platz reserviert wird. Eine Variablendefinition ist daher
    dasjenige, welches dafür sorgt, dass eine Variable auch
    tatsächlich erzeugt wird.
  + Deklaration
    Eine Deklaration teilt dem Compiler zur geschätzten Kentnisnahme
    mit, dass etwas woanders existiert und wie es aussieht.
    Eine Deklaration sorgt nicht dafür, dass dafür Speicherplatz
    reserviert wird. Das muss durch eine Definition geschehen

# Aus dem letzten folgt wiederrum
  Alles, auch Variablen, darf nur einmal definiert werden. Man
  kann sich aber mit beliebig vielen Deklarationen darauf beziehen.

# Eine (gloable) Variable wird definiert, indem man sie ausserhalb
  einer Funktion als Variablendefinition, zb
1
    int MeineVar;
  hinschreibt.

# Eine Variablendeklaration wird gebildet, indem man einer gedachten
  Definition das Schlüsselwort 'extern' voranstellt.
  Um sich also aus einem anderen *.c File auf die soeben definierte
  Variable mittels einer Deklaration zu beziehen, schreibt man
1
    extern int MeineVar;

Lies dir in der >>> FAQ <<< die entsprechenden Abschnitte durch:

Punkt 8: Globale Variablen über mehrere Dateien
Punkt 9: Was hat es mit volatile auf sich
Punkt 6: Header File, wie geht das?

von horst (Gast)


Lesenswert?

dann mußt du dich auch noch mit "volatile" außeinandersetzen

horst schrieb:
> versuchen, sie nur in einer *.c-Datei zu benötigen und dort als static
> deklarieren
> dich mit "extern" auseinandersetzen

ist immer noch aktuell

vermutlich nicht so praktikabel in dieser situation sind named pipes als 
alternative zur parameterübergabe

von Bastian B. (hobby-pic)


Lesenswert?

ok.  Das habe ich gemacht.

Jetzt gibt es nurnoch ein Problem mit dem Rückgabewert der Funktion.

Der Compiler bringt dieses jedoch in Zusammenhang mit der 
Interruptvariable meines Timers

"Error [1521] This feature is not implemented in compiler. There may be 
a definition of external symbol 'timer' found instead of its 
declaration"

Meine Interruptvariable ist jetzt im Main als
1
volatile unsigned char timer=0

und in der .c Funktion als
1
extern volatile unsigned char timer=0

die Rückgabevariable habe ich schon versucht als alles mögliche zu 
definieren.
1
return x

von Grml! (Gast)


Lesenswert?

Bastian B. schrieb:

> Meine Interruptvariable ist jetzt im Main als
> volatile unsigned char timer=0
> und in der .c Funktion als
> extern volatile unsigned char timer=0
> die Rückgabevariable habe ich schon versucht als alles mögliche zu
> definieren.
> return x

Ist das hier die "kleine Horrorshow der C Programmierung"? Brrr lern 
doch mal anständig programmieren das ziehts einem ja die Schuhe aus.

von Karl H. (kbuchegg)


Lesenswert?

Bastian B. schrieb:

> und in der .c Funktion als
>
>
1
extern volatile unsigned char timer=0
>

Du hast im Link etwas überlesen (oder nicht darauf geachtet).
Sobald eine Initialisierung vorhanden ist, wird aus einer Deklaration 
eine Definition.

(ABer das hat nichts damit zu tun, worauf sich der COmpiler in der 
Fehlermeldung bezieht. Da kann man nur raten, weil wir ... KEINE 
HELLSEHER SIND! Zeige deinen Code, dann kann man auch was dazu sagen)

von Bastian B. (hobby-pic)


Lesenswert?

hier der ganze kram in gekürzter Form...
1
//globale Variablen
2
volatile unsigned char timer=0, i=0, sekunde=0;
3
//Funktionen
4
void intcounter(void);              // Aufruf des Serviceroutinenprogramms
5
int Empfang (void);
6
//Interrupt
7
8
#pragma code Timer=0x0008      // Interrupt to CPU Vector to Location 0008h (DB S.98)
9
void High (void)                 
10
{
11
 _asm goto intcounter _endasm       // 
12
}
13
14
//Interrupt-Routine
15
16
#pragma code                     // System Codebereich
17
#pragma interrupt Test        // Kennwort interrupt veranlasst
18
19
void Test ()
20
{
21
    PIR1bits.TMR1IF=0;
22
  timer=1;
23
  if (i==76)
24
  {
25
    sekunde=1;
26
    i=0;
27
  }
28
  else
29
    i++;   
30
}
31
32
33
//Main
34
35
void main (void)
36
{
37
38
  TRISA=0b11100111;     //PORTA Ein-/Ausgänge
39
  PORTA=0;      //PORTA ausschalten
40
  ADCON1=0x0F;               //Alle Port Pins digital
41
  TRISB=0;       //PORTB - Ausgang
42
  PORTB=0;      //PORTB ausschalten
43
        CMCON = 0x07;         //Komparatoreinänge deaktivieren
44
  T1CON=0b10000001;    //Timer1 - 16bit - kein Voteiler - aktiv
45
  TMR1H=0;            //Timer1 - Highbyte = 0
46
  TMR1L=0;      //Timer1 - Lowbyte = 0
47
  INTCON=0b11000000;    //Interrupts zulassen
48
  PIE1=0b00000001;          
49
50
51
  while (1)
52
  {  
53
    if       (IN1==1)  //definierter Eingang in defines.h
54
      PORTB=Empfang();
55
  }
56
}

und nun die Funktion. ist erstmal egal was die macht. Ich will 
nurverstehen, warum es keinen rückgabewert gibt.
1
#include <p18f2550.h>
2
#include "defines.h"
3
4
extern volatile unsigned char timer=0;
5
6
int Empfang (void)
7
{
8
  unsigned int Zyklus=0;    //Zeitwert der Zeitmerssung
9
10
11
12
  while (Sender==1)
13
  {
14
          if (timer==1)   //Synchronisationsbitlänge messen (Zyklus)
15
    {
16
      timer=0;
17
      Zyklus++;
18
    }
19
  }
20
return Zyklus;
21
}

Vielen Dank

von Karl H. (kbuchegg)


Lesenswert?

Bastian B. schrieb:

> extern volatile unsigned char timer=0;


Fehlermeldung

"Error [1521] This feature is not implemented in compiler. There may be
a definition of external symbol 'timer' found instead of its
declaration"

Bei nochmaligem Drüber-Nachdenken könnte das trotzdem stimmen (Ich hatte 
den GCC im Hinterkopf).
Der Compiler beschwert sich, dass du versuchst in einer Deklaration eine 
Initialisierung zu machen.

Schmeiss die Initialisierung weg, so wie das in C vorgesehen ist.

von Bastian B. (hobby-pic)


Lesenswert?

Damit ist die Fehlermeldung schonmal weg.

Dafür gibt es eine Neue.

Error - could not find definition of symbol 'intcounter' in file 
'./main.o'.
Errors    : 1

von Karl H. (kbuchegg)


Lesenswert?

Bastian B. schrieb:
> Damit ist die Fehlermeldung schonmal weg.
>
> Dafür gibt es eine Neue.


Wird das jetzt ein Ratespielchen:

Ich programmiere und ihr sucht in meinem Code nach den Fehlern, die mir 
der Compiler meldet.

> Error - could not find definition of symbol 'intcounter' in file
> './main.o'.

Was bedeutet die Fehlermeldung, welche Wörter kommen vor, wovon ist die 
Rede.
Danach gehst du in deinen Code und siehst nach wo spezfische Wörter aus 
der Fehlermeldung (intcounter) vorkommen und wie das mit deiner 
Rohübersetzung der Fehlermeldung zuammenhängt.

von EGS_TI (Gast)


Lesenswert?

Is ja logisch, weil du diese Funktion nicht definiert (Implementiert) 
hast.

von EGS_TI (Gast)


Lesenswert?

Bastian B. schrieb:

> void High (void)
> {
>  _asm goto intcounter _endasm       //
> }

> //Interrupt-Routine
>
> #pragma code                     // System Codebereich
> #pragma interrupt Test        // Kennwort interrupt veranlasst
>
> void Test ()
> {
>     PIR1bits.TMR1IF=0;
>   timer=1;
>   if (i==76)
>   {
>     sekunde=1;
>     i=0;
>   }
>   else
>     i++;
> }

Siehst du den Fehler??

von Bastian B. (hobby-pic)


Lesenswert?

jepp. hatte ihn auch gerade gefunden. ziemlich bescheuert.

ich mache mal schluss für heute :-)

"Test" sollte "intcounter" heißen.

Vielen Dank

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.