Uhrzeit Stellen/ externe Variablen im Struct

OP #2548148
Lesenswert?

Hallo,
ich möchte die Uhrzeit in meiner main.c einstellen. Der Code für die Uhr 
befindet sich in einer externen Datei RTC.c.
Ich vermute mal, dass es mit "extern" funktionieren sollte, aber 
irgendwie bekomme ich es nicht hin bei dem "struct".
Ich würde mich freuen, wenn mir jemand helfen könnte.
1
C-Code
2
//RTC.c
3
typedef struct
4
{
5
    volatile unsigned char Sekunden;
6
    volatile unsigned char Minuten;
7
    volatile unsigned char Stunden;
8
} datestruct;
9

10
 volatile datestruct Uhrzeit;
1
C-Code.c
2
//main.c
3
Uhrzeit.Minuten = EinstellwertMinuten; //usw.

Grüße, Tobi
#2548317
Lesenswert?

Das wichtigste Prinzip ist wohl das hier:

 C an sich, hat keine Projektverwaltung!

Wenn sich der Compiler eine C-Datei vornimmt, dann interessiert ihn 
nicht, was in anderen C-Dateien steht. Jede C-Datei wird für sich und 
unabhängig von allen anderen übersetzt. Jede Datei muss in sich 
vollständig sein.

Da der Compiler bei diesem Quelltext
1
int main(){
2
{
3
  Uhrzeit.Minuten = 5;
4
}

weder jemals irgendetwas von einer Variable 'Uhrzeit', noch deren 
Aufbau, noch dass sie einen Member 'Minuten' hat gehört hat, setzt es 
einen Fehler.

Also musst du ihm erst mal klar machen, dass es eine Variable Uhrzeit 
gibt. Du brauchst eine Deklaration dafür
1
extern volatile datestruct Uhrzeit;
2

3
int main(){
4
{
5
  Uhrzeit.Minuten = 5;
6
}

Tja. Alles schön gut. Aber was ist jetzt wieder ein 'datestruct'?

Da der Compiler das nur durch betrachten dieses Textes nicht wissen 
kann, muss man ihm das mitteilen
1
typedef struct
2
{
3
    volatile unsigned char Sekunden;
4
    volatile unsigned char Minuten;
5
    volatile unsigned char Stunden;
6
} datestruct;
7

8
extern volatile datestruct Uhrzeit;
9

10
int main(){
11
{
12
  Uhrzeit.Minuten = 5;
13
}


Und jetzt ist man in der unschönen und unglücklichen Lage, dass man in 2 
C-Files dieselbe Strukturdefinition hat. Das will man auf alle Fälle 
vermeiden!
Die Lösung: Man verbannt die Strukturdefinition (und die extern 
Deklaration gleich mit) in ein Header File

rtc.h
*****
1
typedef struct
2
{
3
    volatile unsigned char Sekunden;
4
    volatile unsigned char Minuten;
5
    volatile unsigned char Stunden;
6
} datestruct;
7

8
extern volatile datestruct Uhrzeit;

wird dieses in main.c inkludiert
1
#include "rtc.h"
2

3
int main(){
4
{
5
  Uhrzeit.Minuten = 5;
6
}
dann ist alles paletti. Durch den include wird die Definition von 
'datestruct' hereingezogen und auch gleich noch die extern-Deklaration 
von Uhrzeit.

Und in rtc.c mach ich (fast) dasselbe
1
#include "rtc.h"
2

3
volatile datestruct Uhrzeit;
4

5
void foo()
6
{
7
}

Damit hab ich erreicht, dass es die Strukturdefinition nur einmal in 
Textform gibt und somit ist sichergestellt, dass sie an allen Stellen 
gleich aussieht.


Eigentlich ganz einfach.
OP #2548672
Lesenswert?

Wenn ich es so mache wie oben beschrieben, bekomme ich 4 Fehler vom 
Compiler:
Drei für die datei rtc.h:
Error  1  conflicting types for 'datestruct'
Error  2  previous declaration of 'datestruct' was here
Error  3  conflicting types for 'Uhrzeit'
und eine für rtc.c:
Error  4  previous declaration of 'Uhrzeit' was here

Kann damit jemand mehr anfangen als ich?
#2548681
Lesenswert?

> Kann damit jemand mehr anfangen als ich?


> Error  1  conflicting types for 'datestruct'
Es gibt eine 2-te Definition für datestruct, nicht nur die auf die in 
der Fehlermeldung verwiesen wird.

> Error  2  previous declaration of 'datestruct' was here
Nämlich hier ist sie. An der Stelle, auf die diese Fehlermeldung 
verweist.

> Error  3  conflicting types for 'Uhrzeit'
Das ist dann ein Folgefehler, weil datestruct ein Problem hat.

und eine für rtc.c:
> Error  4  previous declaration of 'Uhrzeit' was here
Ebenfalls ein Folgefehler
OP #2548727
Lesenswert?

Ihr seit ja wirkich unglaublich schnell! :-)

Also hier nochmal die relevanten Teile der einzelnen Dateien:

rtc.h:
*****
c]C-Code
typedef struct
{
    volatile unsigned char Sekunden;
    volatile unsigned char Minuten;
    volatile unsigned char Stunden;
} datestruct;


extern volatile datestruct Uhrzeit;
[/c]

rtc.c
*****
c]C-Code
#include <avr/io.h>
#include <avr/interrupt.h>
#include "rtc.h"
#define fosc 12288000
/*
typedef struct
{
    volatile unsigned char Sekunden;
    volatile unsigned char Minuten;
    volatile unsigned char Stunden;
} datestruct;
*/
 volatile datestruct Uhrzeit;


void init_Timer1(void)
{
  OCR1A = 0xBB7F;       // TOP = 47999
  TIMSK |= (1<<OCIE1A); // CTC-Interrupt zulassen
  TCCR1B = (1<<CS12) | (1<<WGM12); // Mode 4 (CTC; OCR), Timer starten 
PSC = 256
}


// Uhrzeit-Timer-Interrupt
#pragma vector = TIMER1_COMPA_vect
//Anmerkung 1) Heir gibt der Compiler eine Warnung aus: "ignoring 
#pragma vector"
void TIMER1_COMPA_Interrupt(void)
{

  if (++Uhrzeit.Sekunden >59)
  {
    Uhrzeit.Sekunden = 0;
    if (++Uhrzeit.Minuten > 59)
    {
      Uhrzeit.Minuten = 0;
      if (++Uhrzeit.Stunden >23)
      {
        Uhrzeit.Stunden = 0;
      }
    }
  }
}
[/c]

main.c
*****
c]C-Code
#include <avr/io.h>
#include <avr/interrupt.h>
#include "rtc.c"
#include "rtc.h"
//#include "pid.c"

  unsigned char EnterUhrzeit = 0;
  unsigned char EnterUhrzeitMin;
  unsigned char EnterUhrzeitStund;



int main( void )
{
  init_Timer1();
  sei();
  while(1)
  {
    if(EnterUhrzeit)
    {
     Uhrzeit.Minuten = EnterUhrzeitMin;  //Uhr einstellen
     Uhrzeit.Stunden = EnterUhrzeitStund;
    }

  return 0;
}
[/c]


Ich habe jetzt alle nicht relevanten Teile der main.c gelöscht.

Das ist jetzt natürlich OT, aber wo wir schon dabei sind...in der rtc.c 
gibt es noch eine warnung (Anmerkung 1)) und ich vermute mal, dass die 
Uhr so noch nicht ganz funktioniert. Hat dazu noch jemand einen Tip?
#2548745
Lesenswert?

Ein Fest a. schrieb:
> Doch, ich habe da eine #include "rtc.c"
> wenn ich das nicht darf, müsste ich einiges umbauen ;-(

musst du nicht.

Du musst nur nach den Regeln spielen und nicht jeder scheinbaren 
Vereinfachung nachlaufen, die du irgendwo siehst.

Bau dir als erstes mal eine vernünftige Projektstruktur auf. Sonst 
brauchst du erst gar nicht damit anfangen, Dinge in einzelne C-Files zu 
verpacken, wenn du dann sowieso alles wieder mittels #include in einen 
Topf wirfst.

Die C-Files werden (im AVR-Studio) zum Projekt hinzugefügt!
Und nicht alle mitsammen in ein C-File per #include hineingezogen.

FAQ Punkt 7
#2548754
Lesenswert?

Ein Fest a. schrieb:

> Das ist jetzt natürlich OT, aber wo wir schon dabei sind...in der rtc.c
> gibt es noch eine warnung (Anmerkung 1)) und ich vermute mal, dass die
> Uhr so noch nicht ganz funktioniert. Hat dazu noch jemand einen Tip?

1
#pragma vector = TIMER1_COMPA_vect
2
//Anmerkung 1) Heir gibt der Compiler eine Warnung aus: "ignoring
3
#pragma vector"
4
void TIMER1_COMPA_Interrupt(void)
5
{
6

7
  if (++Uhrzeit.Sekunden >59)

Ja. Klau nicht Code, welcher mit dem IAR Compiler gemacht wurde. Und 
wenn du das tust, dann pass die Nicht-Standard Syntax der Interrupt 
Vektoren vom IAR Compiler auf die Nicht-Standard-Syntax vom GCC an.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren