Electronic – Naming and grouping individual pins with the ATXMEGA

atxmegapinsprogrammingxmega

I am new to using atxmega chips (atxmega128a1 specifically) so sorry if my question is not worded in a "professional" way!

So far in order to set or clear a pin I use the following programming in C:

PORTA.OUTSET = PIN1_bm;

PORTA.OUTCLR = PIN1_bm;

The problem with this for me, is that the individual pin definition is on the right hand side of the "=" sign. I would like to be able to set a pin individually in this fashion:

PA0 = 1;

This would be useful to me as I have many individual pins on different ports that need to be "virtually grouped" in the code as they are doing related functions.

For example I have four motor "enable" pins set on different pins of 4 separate ports. Currently if i want to turn them on simultaneously I have to do this:

PORTE.OUTSET = PIN5_bm;

PORTH.OUTSET = PIN0_bm;

PORTJ.OUTSET = PIN3_bm;

PORTK.OUTSET = PIN6_bm;

I want to keep my naming conventions and port names clear and easy to read such that I can group these outputs into some sort of structure and simply write:

Motor1_Enable = 1;

How can I manipulate C to do this for me???

Hope this is clear! Thankyou!

Best Answer

To achieve something close to what you wish, you could define some macros. Here are separate macros for setting and clearing PA0 (assuming PA0 := port A, pin 0), and a macro that takes an argument to decide wether to clear or set the pin.

#define SET_PA0 PORTA.OUTSET = PIN0_bm
#define CLR_PA0 PORTA.OUTCLR = PIN0_bm
#define OUT_PA0(x) (x ? SET_PA0 : CLR_PA0)

int main()
{
  SET_PA0; // PA0 is set
  CLR_PA0; // PA0 is cleared

  OUT_PA0(1); // PA0 is set
  OUT_PA0(0); // PA0 is cleared

  return 0;
}

To use these, you would have to define such macros for all pins you are using. If you want to go an extra mile, you could use more generic macros like:

#define SET_PIN(port, pin) port.OUTSET = pin
#define CLR_PIN(port, pin) port.OUTCLR = pin

int main()
{
  SET_PIN(PORTA, PIN0_bm); // PA0 is set
  CLR_PIN(PORTA, PIN0_bm); // PA0 is cleared

  return 0;
}

But at this point, it would be far better practice to use a function. But you would have to search your headers for the port and pin types. I am not used to atxmega chips as well, but my guess is that they are enums. It would be something looking close to this:

void outPin(port_t port, pin_t pin, int outValue)
{
  if (outValue)
    port.OUTSET = pin;
  else
    port.OUTCLR = pin;
}

int main()
{
  outPin(PORTA, PIN0_bm, 1); // PA0 is set
  outPin(PORTA, PIN0_bm, 0); // PA0 is cleared

  return 0;
}

With these three options, your motor enabling would look like this (choose which best fits your style):

void motorEnable1()
{
  SET_PE5;
  SET_PH0;
  SET_PJ3;
  SET_PK6;
}

void motorEnable2()
{
  SET_PIN(PORTE, PIN5_bm);
  SET_PIN(PORTH, PIN0_bm);
  SET_PIN(PORTJ, PIN3_bm);
  SET_PIN(PORTK, PIN6_bm);
}

void motorEnable3()
{
  outPin(PORTE, PIN5_bm, 1);
  outPin(PORTH, PIN0_bm, 1);
  outPin(PORTJ, PIN3_bm, 1);
  outPin(PORTK, PIN6_bm, 1);
}

You can also write a struct to hold your motor pins information, and use that as argument to a motorEnable function for cleaner code when using more than one motor.