0

I use the following macro functions for my MSP430 to check the status of GPIO pins:

#define PIN(port)             port##IN                    // register name

#define IN_(port,pin,act)     PIN(port) & (1<<(pin))      // request pin status

#define IN(name)              IN_(name)                   // final macro function call

Then I am able to get the status of a GPIO pin like:

enum {ACT_LOW = 0 , ACT_HIGH};
#define STATUS_LED      P3,0,ACT_LOW         // P3       ... port name, 
                                             // 0        ... associated port pin,
                                             // ACT_LOW  ... pin intended for active low action

void main()
{
  if(!IN(STATUS_LED))
     printf("Status LED connected to P3.0 is switched on");
  else
     printf("Status LED connected to P3.0 is switched off");
}

Now I want to take the active state for my pin into account in order not to bother while programming that my LED is switched low side ('0' = LED is switched on). My approach was then the following instead of the aforementioned 2nd line:

#define IN_(port,pin,act)           \
 do{                                \
    if((act) == ACT_HIGH)           \
     PIN(port) & (1<<(pin));        \
    else                            \
     ~(PIN(port) & (1<<(pin)));     \
   }while(0) 

However, the compiler 'expects an expression'. What's my mistake? What do I get wrong?

  • It should be a syntax error, in which line is giving the error? – Diego R. Alcantara Feb 09 '14 at 13:48
  • `do ... while` is a statement, not an expression. It doesn't evaluate to anything. Consequently, you can't use it in the condition of an `if` statement. –  Feb 09 '14 at 14:00

1 Answers1

0

The following code

#define PIN(port)             port##IN                    // register name
#define IN_(port,pin,act)           \
 do{                                \
    if((act) == ACT_HIGH)           \
     PIN(port) & (1<<(pin));        \
    else                            \
     ~(PIN(port) & (1<<(pin)));     \
   }while(0)
#define IN(name)              IN_(name)                   // final macro function call

enum {ACT_LOW = 0 , ACT_HIGH};
#define STATUS_LED      P3,0,ACT_LOW         // P3       ... port name, 
                                             // 0        ... associated port pin,
                                             // ACT_LOW  ... pin intended for active low action

void main()
{
  if(!IN(STATUS_LED))
     printf("Status LED connected to P3.0 is switched on");
  else
     printf("Status LED connected to P3.0 is switched off");
}

Will expand a do...while statement as the controlling expression of an if statement. You can't do that. An alternative is to use the ternary operator:

#define IN_(port,pin,act) ((act) == ACT_HIGH ? PIN(port) & (1<<(pin)) : ~(PIN(port) & (1<<(pin))) )

Also note the following issues:

  1. You did not #include <stdio.h>
  2. ~(PIN(port) & (1<<(pin))) should be !(PIN(port) & (1<<(pin))) or (~PIN(port))&(1<<(pin))
  3. For portability, main should return an int (see What should main() return in C and C++?)
Community
  • 1
  • 1
jerry
  • 2,581
  • 1
  • 21
  • 32
  • In fact, I don't use printf() in my actual code. Therefore, I forgot to #include But the above hints are working fine, thanks! – user3289374 Feb 09 '14 at 18:13
  • @user3289374 Glad its working. I mirrored your `if...else` construct in the answer, but you can likely shorten it and remove the ternary operator. To be pedantic, it may depend on the exact type, but you might want to try something like `#define IN_(port,pin,act) (act == (PIN(port) >> pin & 1) )`. – jerry Feb 09 '14 at 20:32