port I/O abstraction macros
- From: "Tom Torfs" <tomtorfs@xxxxxxxxx>
- Date: 2 Jun 2006 12:00:47 -0700
Everyone,
Earlier I posted some macros that allow you to easily define binary
constants in C (see http://cprog.tomsweb.net/binconst.txt). Playing
similar tricks with the preprocessor, I now created some macros that
allow you to make easy abstraction of port I/O's. It's written for the
MSP430 but the concept can be applied to other embedded architectures.
You simply define your signal location like:
#define LED P1,0
and then use them like:
SETDIR(LED);
CLR(LED);
TOGGLE(LED);
The obvious advantage, besides readability, is that in the next
hardware design or layout iteration - when most of the signals have
shifted to different pins on different ports - all you need to change
is one simple and readable #define in a central location.
Header file (or http://cprog.tomsweb.net/portio.txt):
/* Port I/O abstraction macros - by Tom Torfs, 2006
* MSP430 implementation
* Donated to the public domain. No warranties whatsoever.
*
* These macros allow you to make easy abstraction of I/O port & pin
numbers.
* You simply define your signal location like:
* #define LED P1,0
* and then use them like:
* SETDIR(LED);
* CLR(LED);
* TOGGLE(LED);
* ...
*
* The obvious advantage, besides readability, is that in the next
* hardware design or layout iteration - when most of the signals have
* shifted to different pins on different ports - all you need to
change
* is one simple and readable #define in a central location
*
* In addition, nothing stops you from porting this header to other
* microcontroller families. The specifics such as direction and
interrupt
* registers may be different but the basic concepts hold.
*
* Overview of user macros:
* - Reading from port registers: (these are meant to be used in
expressions)
* x = IN(signal), OUTBUF(signal), DIR(signal), SEL(signal),
IE(signal), IES(signal), IFG(signal)
* - Writing to port registers: (these are meant to be used as
statements)
* output bit manipulation: SET(signal); CLR(signal); TOGGLE(signal);
* direction bit manipulation: SETDIR(signal); CLRDIR(signal);
* special function bit manipulation: SETSEL(signal); CLRSEL(signal);
* interrupt bits manipulation: SETIE(signal); CLRIE(signal);
SETIES(signal); CLRIES(signal);
* interrupt flag manipulation: SETIFG(signal); CLRIFG(signal);
* copy 1 or 0 into output bit: CPYBIT(signal,bitvalue)
* - Getting the port name (string) or bit number (integer literal)
corresponding to a signal:
* const char s[] = PORTNAME(name);
* x = BITNUM(name);
* - Interrupt vector for port corresponding to a signal: (requires
compiler-specific mapping)
* INTVECTOR(name)
*/
/********** HELPER MACROS **********/
#define POUT_(Pn) Pn##OUT
#define PIN_(Pn) Pn##IN
#define PDIR_(Pn) Pn##DIR
#define PSEL_(Pn) Pn##SEL
#define PIE_(Pn) Pn##IE
#define PIES_(Pn) Pn##IES
#define PIFG_(Pn) Pn##IFG
#define IN_(p,b) (PIN_(p)&(1<<b))
#define OUTBUF_(p,b) (POUT_(p)&(1<<b))
#define DIR_(p,b) (PDIR_(p)&(1<<b))
#define SEL_(p,b) (PSEL_(p)&(1<<b))
#define IE_(p,b) (PIE_(p)&(1<<b))
#define IES_(p,b) (PIES_(p)&(1<<b))
#define IFG_(p,b) (PIFG_(p)&(1<<b))
#define SET_(p,b) POUT_(p)|=(1<<(b))
#define CLR_(p,b) POUT_(p)&=~(1<<(b))
#define TOGGLE_(p,b) POUT_(p)^=(1<<(b))
#define SETDIR_(p,b) PDIR_(p)|=(1<<(b))
#define SETSEL_(p,b) PSEL_(p)|=(1<<(b))
#define SETIE_(p,b) PIE_(p)|=(1<<(b))
#define SETIES_(p,b) PIES_(p)|=(1<<(b))
#define SETIFG_(p,b) PIFG_(p)|=(1<<(b))
#define CLRDIR_(p,b) PDIR_(p)&=~(1<<(b))
#define CLRSEL_(p,b) PSEL_(p)&=~(1<<(b))
#define CLRIE_(p,b) PIE_(p)&=~(1<<(b))
#define CLRIES_(p,b) PIES_(p)&=~(1<<(b))
#define CLRIFG_(p,b) PIFG_(p)&=~(1<<(b))
#define PORTNAME_(p,b) #p
#define BITNUM_(p,b) b
#define INTVECTOR_(p,b) INTVECTOR_##p
/********** USER MACROS **********/
/* for reading from port registers
note: these return 0 or nonzero, not 0 or 1
if necessary, use as: x = IN(signal) ? 1 : 0;
not necessary for normal use in if() etc. */
#define IN(name) IN_(name)
#define OUTBUF(name) OUTBUF_(name)
#define DIR(name) DIR_(name)
#define SEL(name) SEL_(name)
#define IE(name) IE_(name)
#define IES(name) IES_(name)
#define IFG(name) IFG_(name)
/* for writing to port registers */
#define SET(name) SET_(name)
#define CLR(name) CLR_(name)
#define TOGGLE(name) TOGGLE_(name)
#define SETDIR(name) SETDIR_(name)
#define SETSEL(name) SETSEL_(name)
#define SETIE(name) SETIE_(name)
#define SETIES(name) SETIES_(name)
#define SETIFG(name) SETIFG_(name)
#define CLRDIR(name) CLRDIR_(name)
#define CLRSEL(name) CLRSEL_(name)
#define CLRIE(name) CLRIE_(name)
#define CLRIES(name) CLRIES_(name)
#define CLRIFG(name) CLRIFG_(name)
#define CPYBIT(name,bit) ((bit) ? (SET_(name)) : (CLR_(name)))
/* if you want to know the port (string) or the bit number (integer
literal) */
#define PORTNAME(name) PORTNAME_(name)
#define BITNUM(name) BITNUM_(name)
/* interrupt vector for port */
#define INTVECTOR(name) INTVECTOR_(name)
/* mapping to compiler-specific interrupt vector names/numbers
(this is for mspgcc, adapt for your compiler) */
#define INTVECTOR_P1 PORT1_VECTOR
#define INTVECTOR_P2 PORT2_VECTOR
/* USAGE EXAMPLE:
- define your port I/O's as follows: (note you MUST use a #define,
not an enum)
#define LED P1,0
#define INPUTSIGNAL P2,1
#define ANALOGSIGNAL P6,3
#define INTSIGNAL P2,2
#define SIGBIT0 P3,7
#define SIGBIT1 P3,6
#define SIGBIT2 P3,5
#define UNUSED1 P1,5
#define UNUSED2 P1,6
#define UNUSED3 P1,7
- examples of usage:
SETDIR(LED); CLR(LED); TOGGLE(LED);
CLRDIR(INPUTSIGNAL); x = IN(INPUTSIGNAL);
SETSEL(ANALOGSIGNAL);
SETIE(INTSIGNAL); CLRIE(INTSIGNAL);
CPYBIT(SIGBIT0,x&1); CPYBIT(SIGBIT1,x&2); CPYBIT(SIGBIT2,x&4);
SETDIR(UNUSED1); SETDIR(UNUSED2); SETDIR(UNUSED3); // set to output to
save power
printf("The LED is on port %s, bit %d.\n", PORTNAME(LED),
BITNUM(LED));
ADC12MCTL0 = SREF_0 | BITNUM(ANALOGSIGNAL);
- example interrupt routine (compiler-specific syntax)
interrupt(INTVECTOR(INTSIGNAL)) int_func(void)
{
if (IFG(INTSIGNAL))
{
// do something...
CLRIFG(INTSIGNAL); // clear interrupt flag
}
}
*/
.
- Follow-Ups:
- Re: port I/O abstraction macros
- From: DAC
- Re: port I/O abstraction macros
- From: John Temples
- Re: port I/O abstraction macros
- Prev by Date: Re: Need an executable version of asm80
- Next by Date: Re: port I/O abstraction macros
- Previous by thread: Scope recommendations
- Next by thread: Re: port I/O abstraction macros
- Index(es):
Relevant Pages
|