Quantcast
Channel: MSP430 Technical Forums
Viewing all articles
Browse latest Browse all 2077

Basic MSP430 GPIO Macros

$
0
0

In my project, I use a few basic macros for GPIO. The goal is, that I can easily redefine pin assignment in a central location without compromising performance or code size.

 

The macros (gpiomacros.h):

// MSP430 gpio macros
#define GPIO_SEL(port) P ## port ## SEL
#define GPIO_DIR(port) P ## port ## DIR
#define GPIO_OUT(port) P ## port ## OUT
#define GPIO_IN(port) P ## port ## IN

#define GPIO_IS_INPUT(port,pin) { GPIO_SEL(port) &= ~(pin); GPIO_DIR(port) &= ~(pin); }
#define GPIO_IS_OUTPUT(port,pin) { GPIO_SEL(port) &= ~(pin); GPIO_DIR(port) |= (pin); }
#define GPIO_IS_PERIPHERAL_IN(port,pin) { GPIO_SEL(port) |= (pin); GPIO_DIR(port) &= ~(pin); }
#define GPIO_IS_PERIPHERAL_OUT(port,pin) { GPIO_SEL(port) |= pin; GPIO_DIR(port) |= (pin); }

#define GPIO_SET(port,pin) { GPIO_OUT(port) |= (pin); }
#define GPIO_CLEAR(port,pin) { GPIO_OUT(port) &= ~pin; }
#define GPIO_READ(port,pin)  ( GPIO_IN(port) & (pin) )

In a central configuration file (e.g. hardware.h) I assign pins like this:

// Pin assignment
#define LED1_PIN  BIT1
#define LED1_PORT 6
#define LED2_PIN  BIT0
#define LED2_PORT 1

And then in the code I interact with GPIO like this:

// Setup LEDs
GPIO_IS_OUTPUT(LED1_PORT, LED1_PIN);
GPIO_IS_OUTPUT(LED2_PORT, LED2_PIN);

// Turn off LEDs
GPIO_CLEAR(LED1_PORT, LED1_PIN);
GPIO_CLEAR(LED2_PORT, LED2_PIN);

The macros are resolved in two steps:

1. Higher level "functions" define the commands. E.g. GPIO_SET(), GPIO_IS_OUTPUT(), ..

2. Lower level macros used within those functions translate port, pin to a register. E.g. GPIO_IN(), GPIO_SEL(), ..

 

The end result is code like you would write when directly working with the GPIO registers. E.g. P2OUT &= ~BIT0; Note that this translation is done by the C pre-processor before the code is compiled.

 

This all works fine and dandy, with the exception of port J. Port J doesn't have a SEL register, which breaks the 1st half of the GPIO_IS_OUTPUT and GPIO_IS_INPUT macros. I currently work around this by adding special GPIO_IS_OUTPUT/INPUT_J macros, but then the main code needs to include some logic to invoke the proper macro.

#if (LED2_PORT == J)
GPIO_IS_OUTPUT_J(LED2_PORT, LED2_PIN);
#else
GPIO_IS_OUTPUT(LED2_PORT, LED2_PIN);
#endif

Any ideas, how I could include a condition inside macros, that checks whether the port is J, and if so excludes the GPIO_SEL command?

 

And yes, I could probably use C++ templates with identical results and an easy workaround for port J, but I'd like to avoid migrating my plain old C project.


Viewing all articles
Browse latest Browse all 2077

Trending Articles