Forum: Mikrocontroller und Digitale Elektronik Variable ohne Funktion


von P. F. (pfuhsy)


Lesenswert?

Hallo, irgendwie frag ich mich wie das sein kann und komme einfach nicht 
auf die Lösung. Vielleicht sehe ich auch den Wald vor lauter Bäumen 
nicht.

Ich habe ein RFM12 an den eine Präamble und ein paar weitere Sachen 
gesendet werden damit das Teil einen Interrupt auslöst:
1
RFM_SEND(0xAA);
2
RFM_SEND(0xAA);
3
RFM_SEND(0X2D);
4
RFM_SEND(0xD4);

Funktioniert wunderbar.

Wenn ich jetzt das ganze in eine Variable schreibe, reagiert der RFM12 
nicht.
1
uint8_t PREAMBLE0 = 0xAA;
2
uint8_t PREAMBLE1 = 0xAA;
3
uint8_t SYNC0 = 0x2D;
4
uint8_t SYNC1 = 0xD4;
5
...
6
...
7
RFM_SEND(PREAMBLE0);
8
RFM_SEND(PREAMBLE1);
9
RFM_SEND(SYNC0);
10
RFM_SEND(SYNC1);

Hat jemand eine Idee ??

Noch was.
Ich arbeite mit AVR Studio v4.irgendwas. Manchmal hab ich beim debuggen 
das Phänomen, dass er bestimmte Varibalen bei Druck von F11 "Schritt für 
Schritt" einfach überspringt. Ich sehe also gar nicht welche Werte diese 
haben. Beispielweise habe ich in einer Header
1
uint8_t ADR = 0;
deklariert. Wenn ich jetzt in den Haupschleife
1
ADR = 1;
schreibe, überspringt er beim debuggen die Variable einfach und landet 
schon bei der nächsten Anweisung. In der Watchlist ist "ADR" immernoch 
bei Wert "0". Den Optimizer habe ich testweise mal auf "O0", mal auf 
"Os".
Hat dabei jetzt eine Idee ?

von Frank (Gast)


Lesenswert?

Mach mal ein
const uint8_t PREAMBLE0 = 0xAA;
daraus!?
Vllt ändert das was.

Und wegen dem Debuggen, wenn du auf-O0 stellst hätte ich auch erwartet 
das er es richtig macht.  Hast du parallel schon mal den ASM dazu 
angeschaut?

von Ben S. (theben)


Lesenswert?

Könnte vielleicht sein das du nen Syntax Fehler in deinem Code hast und 
die Fehler Meldung ausgeschaltet hast?
Das hatte ich mal. Der hat dann einfach nicht kompiliert und immer mit 
der letzen Version die funktioniert hatte gearbeitet.
1
uint8_t PREAMBLE0 = 0xAA;
2
uint8_t PREAMBLE1 = 0xAA;
3
uint8_t SYNC0 = 0x2D;
4
uint8_t SYNC1 = 0xD4;
5
...
6
...
7
RFM_SEND(PREAMBLE0);
8
RFM_SEND(PREAMBLE1);
9
RFM_SEND(SYNC0);
10
RFM_SEND(SYNC1);

bei deinen .... Pünktchen kann noch viel passieren den Code musst du 
schon mit an geben damit man dir besser helfen kann

von HopeIHelped (Gast)


Lesenswert?

Setzt du die Variablen im Hauptprogramm, rufst aber die Routine 
RFM_SEND() in einem Interrupt auf?

Möglicherweise wurden die Variablen dann vom Compiler "wegoptimiert". 
Deklariere die Variablen mal als volatile uint8_t, oder kompiliere 
explizit im Debugmodus (= keine Optimierung).

von Edi R. (edi_r)


Lesenswert?

Peter F. schrieb:
>
1
> RFM_SEND(0xAA);
2
> RFM_SEND(0xAA);
3
> RFM_SEND(0X2D);
4
> RFM_SEND(0xD4);
5
>

Üblicherweise schreibt man Konstanten in Großbuchstaben. Nachdem 
"RFM_SEND" in Großbuchstaben geschrieben ist - ist das vielleicht ein 
Makro, das keine Variablen als Parameter will?

Peter F. schrieb:
>
1
> uint8_t PREAMBLE0 = 0xAA;
2
> uint8_t PREAMBLE1 = 0xAA;
3
> uint8_t SYNC0 = 0x2D;
4
> uint8_t SYNC1 = 0xD4;
5
>

Sowas müsste aber auf jeden Fall klappen:
1
#define PREAMBLE0  0xAA
2
#define PREAMBLE1  0xAA
3
#define SYNC0  0x2D
4
#define SYNC1  0xD4

von P. F. (pfuhsy)


Lesenswert?

Edi R. schrieb:
> #define SYNC0  0x2D
> #define SYNC1  0xD4

Das funktioniert. Ich versteh aber nicht genau warum das andere nicht 
geht.
Ein Teil des Codes sieht folgendermaßen aus:
main.c
1
int main(void) //Hauptprogramm
2
{
3
  initPorts();    //Ports deklarieren
4
  uint8_t commando[6] = {"######"};
5
  
6
  /* Der Interrupt des UARTs stört den Timer und bricht das Porgramm
7
  einfach ab. Wahrscheinlich registriert er einen High Pegel und 
8
  bleibt dann in der Zeile hängen. Deswegen erstmal auskommentieren
9
  bis ich ihn wirklich brauche. */
10
  initUART();      //UART initialisieren
11
12
  //RFM einschalten
13
  RFM_ON();
14
  _delay_ms(1000);  //TODO durch Zeitbabis ersetzten
15
  initRFM_Ports();  //Ports für RFM initialisieren
16
  initRFM();      //RFM initialisieren
17
  //initTimer();    //Timer initialisieren
18
  
19
  //Hauptschleife
20
  while(true)
21
  {
22
    //ADR
23
    ADR = 0x31;    //Teilnehmer-Adresse 1    
24
    //FKT
25
    SEND_BEF();    //Sende befehl
26
    ANF_REED();    //Anfrage Reed-Kontakt
27
    ANF_BAT();    //Anfrage Batterie-Status
28
    //STA
29
    HAA_ON();    //Anlage aktiv
30
    ALARM_LOW();  //kein Alarm in Basis
31
    //Laufvariable
32
    LF = 0x01;      //Laufvariable
33
    //SW
34
    SW = 0x30;    //SW-Version 3.0
35
36
    commando[0] = ADR;
37
    commando[1] = FKT;
38
    commando[2] = STA;
39
    //commando[3] = WRT0;
40
    commando[4] = LF;        
41
    commando[5] = SW;
42
43
    DATEN_SENDEN(commando);
44
    _delay_ms(3000);    //Zu Testzwecken
45
46
  } 
47
}


rfm12.h mit Funktion DATEN_SENDEN:
1
#define SYNC0  0x2D
2
#define SYNC1  0xD4
3
//funktioniert nicht
4
//uint8_t SYNC0 = 0x2D;
5
//uint8_t SYNC1 = 0xD4;
6
....
7
8
//Kommandos schreiben als Sender
9
unsigned int RFM_CMD_SENDER(unsigned int aCmd)
10
{
11
  int i = 0;
12
  unsigned int temp;
13
14
  LOW_SCK();
15
  LOW_SEL();
16
17
  for(i=0;i<16;i++)
18
  {
19
    temp<<=1;
20
    if(SDO_HI())
21
    {
22
      temp|=0x0001;
23
    }
24
    
25
    LOW_SCK();
26
27
    if(aCmd&0x8000)
28
    {
29
      HI_SDI();
30
    }
31
    
32
    else
33
    {
34
      LOW_SDI();
35
    }
36
37
    HI_SCK();
38
    aCmd<<=1;
39
  };
40
41
  LOW_SCK();
42
  HI_SEL();
43
  return(temp);
44
}
45
46
//Daten senden
47
void RFM_SEND(unsigned char aByte)
48
{
49
  while(PIND&(1<<RFM_IRQ)); //wartet bis RFM_IRQ auf LOW ist
50
  RFM_CMD_SENDER(0xB800+aByte);
51
}
52
53
void DATEN_SENDEN(unsigned char data[6])
54
{
55
  unsigned char ChkSum;
56
  int i;
57
58
  RFM_CMD_SENDER(0x0000);//Statusregister auslesen
59
  RFM_SENDER_EIN();  //Sender einschalten
60
  ChkSum=0;
61
62
  //---------------------------------------------
63
  //Prefix, 0-3 Bytes senden
64
  RFM_SEND(0xAA);//Präambel 0
65
  RFM_SEND(0xAA);//Präambel 1
66
  RFM_SEND(SYNC0);  //Synchronisation 0
67
  RFM_SEND(SYNC1);  //Synchronisation 1
68
69
  //4-9 Bytes senden
70
  for (i=0;i<6;i++)
71
  {
72
    RFM_SEND(data[i]);
73
    ChkSum+=data[i];
74
  }
75
76
  //Suffix, 10-12 Bytes senden
77
  RFM_SEND(ChkSum);   //Checksumme
78
  RFM_SEND(0xAA);  //Suffix 0
79
  RFM_SEND(0xAA);  //Suffix 1
80
  //---------------------------------------------
81
82
  RFM_SENDER_AUS();  //Sender wieder ausschalten
83
84
}

von P. F. (pfuhsy)


Lesenswert?

HopeIHelped schrieb:
> Setzt du die Variablen im Hauptprogramm, rufst aber die Routine
> RFM_SEND() in einem Interrupt auf?
Nein. Siehe Code.

> Möglicherweise wurden die Variablen dann vom Compiler "wegoptimiert".
> Deklariere die Variablen mal als volatile uint8_t, oder kompiliere
> explizit im Debugmodus (= keine Optimierung).

Mit volatile kann ich während des debuggens unter "Os" in die Variable 
sehen, gut. Aber wegoptimiert ist das Ganze ohne volatile ja nicht 
wirlich. Wenn ich das  mit "Os" compiliere in meinen Controller lade und 
mit RFM12 an den anderen Controller sende, kommt der Inhalt der Variable 
an (sehe ich mit UART). Also ist Sie doch vorhanden.

von P. F. (pfuhsy)


Lesenswert?

Ich hab hier ein einfaches Beispiel:
1
int main(void) //Hauptprogramm
2
{
3
  initPorts();    //Ports deklarieren
4
  uint8_t commando[6] = {"######"};
5
  
6
  uint8_t *test;
7
  test = &commando[0];
8
  
9
  initUART();      //UART initialisieren
10
.....

Unter Parameter "O0" kann ich die Variable "test" einsehen. Er springt 
von Zeile zu Zeile.
Unter Parameter "Os" springt er von "uint8_t commando[6] = {"######"};" 
direkt auf "initUART();". In der Watchlist steht dann unter "test" 
Location not valid. Heisst das jetzt er hat Sie wegoptimiert und findet 
sie jetzt nicht merh ? Warum ? Vielleihct weil sie sonst kein nutzen hat 
???

von Karl H. (kbuchegg)


Lesenswert?

Peter F. schrieb:

> Location not valid. Heisst das jetzt er hat Sie wegoptimiert und findet
> sie jetzt nicht merh ?

Yep

> Warum ? Vielleihct weil sie sonst kein nutzen hat
> ???

genau. Der Compiler hat einen Weg gefunden, die Varible nicht zu 
benötigen. Sie existiert schlicht und ergreifend im endgültigen 
Programm, das zur Ausführung kommt nicht mehr.

Genauso wie er Anweisungen umsortieren wird und auch sonst noch so 
allerhand Dinge treiben wird, die dir beim Debuggen auffallen werden.

von Edi R. (edi_r)


Lesenswert?

Peter F. schrieb:
> Edi R. schrieb:
>> #define SYNC0  0x2D
>> #define SYNC1  0xD4
>
> Das funktioniert. Ich versteh aber nicht genau warum das andere nicht
> geht.

So ganz klar ist mir das auch nicht. Aber:

Peter F. schrieb:
> rfm12.h mit Funktion DATEN_SENDEN:

Vielleicht liegt's daran. In einer .h-Datei sollten nur die Definitionen 
stehen, der Code selber sollte in einer .c-Datei sein. (Ist jetzt aber 
nur ein Schuss ins Dunkel.) Also z. B. so:

Datei rfm12.h:
1
#ifndef _rfm12_h_
2
#define _rfm12_h_
3
4
uint8_t SYNC0 = 0x2D;
5
uint8_t SYNC1 = 0xD4;
6
7
extern unsigned int RFM_CMD_SENDER(unsigned int aCmd);
8
extern void RFM_SEND(unsigned char aByte);
9
extern void DATEN_SENDEN(unsigned char data[6]);
10
11
#endif


Datei rfm12.c:
1
#include "rfm12.h"
2
3
//Kommandos schreiben als Sender
4
unsigned int RFM_CMD_SENDER(unsigned int aCmd)
5
{
6
  int i = 0;
7
  unsigned int temp;
8
9
  ... usw. den Rest des Codes

von Spax (Gast)


Lesenswert?

Warum definierst du die Varibalen mit "uint8_t", wenn die Funktion 
"unsigned char" erwartet. Schion klar, dass möglicherweise beides 
dasselbe ist. Dennoch ist es schlechter Coding Stil und fehleranfällig.

von Edi R. (edi_r)


Lesenswert?

Damit hast Du zwar uneingeschränkt recht, aber das ist sicher nicht der 
Grund, warum es überhaupt nicht funktioniert.

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.