Reputation: 301
I am attempting to pass a reference to an I/O pin as an function argument on a PIC24F MCU using C. For PICs, the device header file provides access to the i/o buffer registers via:
LATAbits.LATA2 = 0; // sets the pin (RA2 in this case) low.
if (PORTAbits.RA3) { // reads the state of the pin. (RA3)
I want to do something like this:
int main() {
Configure(); // Sets up peripherals, etc.
WaitForHigh(PORTAbits.RA3); // waits for pin RA3 to go hi.
...
return 0;
}
void WaitForHigh( ?datatype? pin_reference ) {
while( !pin_reference ); // Stays here until the pin goes hi.
}
So what datatype am I trying to pass here? And what's actually going on when I poll that pin? Below, I copy a relevant portion from the PIC24F device header that I'm using in case it helps.
#define PORTA PORTA
extern volatile unsigned int PORTA __attribute__((__sfr__));
typedef struct tagPORTABITS {
unsigned RA0:1;
unsigned RA1:1;
unsigned RA2:1;
unsigned RA3:1;
unsigned RA4:1;
unsigned RA5:1;
} PORTABITS;
extern volatile PORTABITS PORTAbits __attribute__((__sfr__));
Thank you in advance!
Upvotes: 2
Views: 2017
Reputation: 2967
Please, note that the PORT bit values are obtained through a bit field, so, answering your question, you can't. Bit fields doesn't have address, so you cannot pass it as a pointer to a function.
Instead, you could use a Macro:
#define WaitForHigh(p) do{while(!(p));}while(0)
It is true that macros has it's draw backs on code readability, yet, given that proper care is taken, there are situations where they're the best solution. It is arguable if macro is the best solution in this Q&A, yet it is important to mention.
Thanks to the commenters for the suggestions to improve the macro safeness.
Upvotes: 1
Reputation: 301
As an alternative to using a macro, a function can accept both the PORT register address (or latch register address, eg. LATA in the case of a pin configured for output) and the mask of the bit in the register that is needed. For example:
#include<p24FV32KA301.h> // defines both PORTA and _PORTA_RA3_MASK
void WaitForHigh( volatile unsigned int * port, pin_mask ) {
while( !(*port & pin_mask) ); // Stays here until the pin goes hi.
}
int main()
{
...
WaitForHigh( &PORTA, _PORTA_RA3_MASK ); // waits for pin RA3 to go hi.
...
return 0;
}
Upvotes: 4
Reputation: 18359
You can combine preprocessor processing with a function to get what you wan along with compile time checking of the symbols. For example:
#define PORT_FUNC(f, p, b) f(p, b)
#define WaitForHigh(p, b) PORT_FUNC(WaitForHighImp, &p, _ ##p## _ ##b## _MASK)
void WaitForHighImp(volatile unsigned* p, unsigned char mask)
{
while (!(*p & m))
;
}
int main()
{
WaitForHigh(PORTA, RA3);
}
The advantage of this approach is that you online say "PORTA" once and "RA3" once at the time of the call, you make sure the bit name is present in the port and that the bit is present.
Upvotes: 0