Equivalent for PORTB in Arduino Mega 2560

Hello,

like in the subject I would like to know the equivalent for the instruction:

PORTB |= 0x01;
PORTB &= ~0x01;

which is working in Arduino Uno to control whether the digital pin 8 to 13 are HIGH or LOW in the Arduino Mega 2560.

Thank you

Same, only with a different PORT register and value to and/or it with, depending on which pin.

See a pinout chart (google image search will find nice pinout diagrams - just search the board and the word pinout). They typically show the port pin as P, followed by the letter of the port, then the bit within the port (for example PB0 for the pin you referred to).

So for PB0, it would be
PORTB |= 0x01;
PORTB &= ~0x01;

while for PG5, it would be
PORTG |= 0x10;
PORTG &= ~0x10;

Note that you can also toggle the pin in a single operation by writing a 1 to the PINx register, ex:
PINB=0x01;

Since according to notifications people are still reading this, there are a few things also worth noting:

  1. PORTx (and DDRx (Data Direction Register) and PIN (PortINput) are "magic" registers because they are located in the "low I/O space", which makes it possible to set, clear, or test them with a single instruction work that executes in 2 clocks on a pre-2016 AVR.
PORTB |= 0x01; //1 word, 2 clocks on ATmega2560. Either way, this is atomic, and you don't have to worry about an interrupt firing in the middle
if(PORTB & 0x01) // 1 word 1 clock for the test, and 1 word for an rjmp (2 if it for some reason needs a jump, but the linker rarely does) -  the test instructions are sbic/sbis (Skip if Bit in Io register Clear/Set), that is, they test the bit (taking 1 clock to do so, and depending on the  value of the bit either skip (takes 1 clock) or don't skip (takes however long it normally takes) the next instruction, which is almost always a jump of some sort; rjmp takes 2 clocks, jmp 3 clocks)
if (PORTB & 0x03) // 2 word 2 clocks for the test then 1 word for a breq/brne - and potentially an extra 1 and 2 ontop of that for an rjmp since conditional branches can only go 64 words in either direction. 
PORTB  = 0x01; // 2 word 2 clocks, *and not atomic*
PORTB |= 0x03; // 3 word, 3 clocks, and not atomic. 
  1. On post 2016 AVRs, the register layout is different, PORTB/DDRB/PINB is replaced with PORTB.OUT, PORTB.DIR, PORTB.IN

These are in extended I/O space, so writes will generally take 2 clocks and reads three, plus the time to prepare the value you want to write (so PORTB.OUT |= 1 would be 5 words and 6 clocks, and is not atomic). Luckily, DIR and OUT have set/clear/toggle versions - these still take 3 words and 3 clocks to do say, PORTB.OUTCLR = 3 (which would clear the two low bits); but at least it's atomic.

  1. The modern AVRs also have "VPORTx.DIR/OUT/IN/INTFLAGS registers. Those are in the low I/O space, and can be accessed like the old PORTx/DDRx/INx registers:
VPORTB.OUT |= 1; // 1 word and 1 clock (sbi/cbi got faster!)
VPORTB.OUT = 1; // 2 word 2 clock *and not atomic*
VPORTB.OUT |= 3; //3 word, 3 clocks, and not atomic. 
if(VPORTB.OUT & 0x01) // 1 word 1 clock for the test, and 1 word for an rjmp (2 if it for some reason needs a jump, but the linker rarely does), just like before
4. The ATmega2560 however a problem - they ran out of registers in the low I/O space (the bit set clear test instructions only work on the first 32 addresses). For ports H and higher, the registers are stuffed in extended I/O! 
PORTH |= 1; // 5 words 5 clocks! *not atomic* 
PORTH = 1; // 3 words 3 clocks*not atomic* 
if(PORTH & 0x01) // or 
if(PORTH & 0x03) // 3 word 3-4 clocks for the test (lds sbrs rjmp - sbrs is another skipif OR lds, andi, breq/brne) *not atomic* 
2 Likes

Thank you very much for your reply.

Sorry, I am sure you are right but I am not able to understand you :confused:

I was thinking that my operation PORTB |= 0x01 just would have set the digital pins from 8 to 13 HIGH at the same time, now you are telling me that it sets only the PB0?

And, what 0x01 means? ( I thought it was 1 in decimal).

Can you kindly be more exhaustive and help a poor student going crazy for his graduating thesis?

Anyway thank you

PORTB |= 0x01 only changes 1 bit. 0x01 is the same as 0b00000001.

If you want all 6 bits of port B, use 0x3F, or 0b00111111.

Yes exactly I just need to change the digital pin 8.

I am slowly understanding the logic of port mapping... :slight_smile:

So from Uno to Mega 2560: PORTB |= 0x01 would become PORTH |= 0x04 ?

Thank you!

Mega D8 is PH5. 0b00100000, or 0x20.

Yes, you are right.

I finally understood :slight_smile:

Thank you very much..I'll try it later but I am almost sure it'll work.

I do that all the time to set & clear bits:
PORTB = PORTB | 0x01; // set LSB, leave rest alone
PORTB = PORTB & 0b11111110; // or 0xFE. clear LSB, leave rest alone

1 Like