Forum: Mikrocontroller und Digitale Elektronik "expression must have a constant value" umgehen


von Ben H. (powerun)


Lesenswert?

Hallo!

Momentan arbeite ich als Praktikum in einem Betrieb, der elektronische 
Vorschaltgeräte im hochleistungsbetrieb baut und ich bin für die 
erweiterung der Firmware zuständig.

Ich programmiere einen PIC18F458 mit C. Intern läuft alles über CAN.

Meine Aufgabe war es erst, die 7 transmit (TX) und die 7 reicive (RX) 
messages so zu erweitern, dass zukünftig 16 Geräte gleichzeitig über 
einen Bus betrieben werden können, wobei über einen dreh-codierschalter 
eine eindeutige ID zugewiesen werden kann.

Mit den TX habe ich es scho geschafft.
Auszüge:
im header:
1
#define TX1_DLC            8
2
#define TX1_ID_0              0x030
dazu beim initialisieren:
1
   if(DIP_POS == 0x0) //device 1
2
    {
3
      TX1_ID = TX1_ID_0;
4
      TX2_ID = TX2_ID_0;
5
      TX3_ID = TX3_ID_0;
6
      TX4_ID = TX4_ID_0;
7
      TX5_ID = TX5_ID_0;
8
      TX6_ID = TX6_ID_0;
9
      TX7_ID = TX7_ID_0;
10
      TX8_ID = TX8_ID_0;
11
    }
12
   else if(DIP_POS == 0x1) //device 2
13
    {
14
      TX1_ID = TX1_ID_0 + 0x040;
15
      TX2_ID = TX2_ID_0 + 0x040;
16
      TX3_ID = TX3_ID_0 + 0x040;
17
      TX4_ID = TX4_ID_0 + 0x040;
18
      TX5_ID = TX5_ID_0 + 0x040;
19
      TX6_ID = TX6_ID_0 + 0x040;           
20
      TX7_ID = TX7_ID_0 + 0x040;
21
      TX8_ID = TX8_ID_0 + 0x040;     
22
    }
und so weiter...
dies funktioniert einwandfrei. Deshalb wollte ich das selbe mit den RX 
machen.
header:
1
  #define RX1_DLC          3
2
  #define RX1_ID_0          0x010  
3
4
  #define CAN_RX_MSG1        RX1_DLC + (RX1_ID&0x007)*(unsigned short)0x2000 + (RX1_ID>>3)*(unsigned long)0x10000
Nun wird aber je nachdem welche Message in empfang genommen wird, beim 
switch ein anderer case ausgelöst:
1
      switch(SJA_FRAME_INFO_AND_ID_SFF)
2
      {
3
         case CAN_RX_MSG1:  
4
               ...
5
         break;

Nun kommt aber bei jedem case die fehlermeldung:
1
Error[Pe028]: expression must have a constant value

Jetzt wüsste ich gerne:
was kann ich tun, damit es funktioniert, ohne dass ich den switch 
weglassen muss.

Hoffe jemand kann mir helfen und ich hoffe meine Angaben reichen für das 
Verständnis meiner Frage.

MFG
-Ben
von (prx) A. K. (prx)


Lesenswert?

Ben Hub schrieb:
>   #define CAN_RX_MSG1        RX1_DLC + (RX1_ID&0x007)*(unsigned
> short)0x2000 + (RX1_ID>>3)*(unsigned long)0x10000   [/c]

Bisschen Ästhetik: (unsigned long)0x2000 == 0x2000uL

> was kann ich tun, damit es funktioniert, ohne dass ich den switch
> weglassen muss.

Wie der Compiler schon sagt ist als "case" Ausdruck nur eine Konstante 
erlaubt. Da die RX1_xxx Dinger keine Konstanten sondern I/O-Register 
sind geht das so nicht.
von Ben H. (powerun)


Lesenswert?

A. K. schrieb:
> Wie der Compiler schon sagt ist als "case" Ausdruck nur eine Konstante
>
> erlaubt. Da die RX1_xxx Dinger keine Konstanten sondern I/O-Register
>
> sind geht das so nicht.

ja das is mir klar.

Davor war ja RXx_ID konstant belegt. Jetzt ändert sich der Wert je nach 
Schalterstellung.
Meine Frage bleibt daher weiterhin offen: Kann ich da noch irgendwas 
machen, ohne den switch zu löschen? Oder was für möglichkeiten habe ich 
überhaupt? (Ich bin noch recht amateurhaft im Bezug auf microcontroller 
und programmierung :x )
von (prx) A. K. (prx)


Lesenswert?

Versuch mal zu beschreiben, was du eigentlich mit dem Statement 
erreichen willst.
von cskulkw (Gast)


Lesenswert?

Du hast Dir eine Makroberechnung programmiert.

Meine Kollege sind von so etwas ebenfalls schwer begeistert. Ich finde 
sie Verwirrung stiftend. Deshalb halte ich mich mit so etwas zurück.

Der Preprozessor ersetzt Deine Berechnung stumpf und setzt es in die 
case-Anweisung.

Versuche Dein Define einem anderen vorher zuzuweisen, wie

Ben Hub schrieb:
> #define RX1_ID_0          0x010
>
>
>
>   #define CAN_RX_MSG1        RX1_DLC + (RX1_ID&0x007)*(unsigned short)0x2000 + 
(RX1_ID>>3)*(unsigned long)0x10000

#define CAN_RX_MSG_COPY CAN_RX_MSG1


switch( ...

case CAN_RX_MSG_COPY:

wenn das auch nicht geht, dann mußt Du es halt ausrechnen und Dich 
festlegen. D. h. Nein es gibt dann keine andere Möglichkeit.

...
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.