Categories

Arduino port manipulation examples

Port registers allow for lower-level and faster manipulation of the i/o pins of the microcontroller on an Arduino board. The chips used on the Arduino UNO board have three ports:

B (digital pin 8 to 13)
C (analog input pins)
D (digital pins 0 to 7)

Each port is controlled by three registers, which are also defined variables in the arduino language. The DDR register, determines whether the pin is an INPUT or OUTPUT. The PORT register controls whether the pin is HIGH or LOW, and the PIN register reads the state of INPUT pins set to input with pinMode(). The maps of the ATmega8 and ATmega168 chips show the ports. The newer Atmega328p chip follows the pinout of the Atmega168 exactly.

DDR and PORT registers may be both written to, and read. PIN registers correspond to the state of inputs and may only be read.

PORTD maps to Arduino digital pins 0 to 7

DDRD – The Port D Data Direction Register – read/write
PORTD – The Port D Data Register – read/write
PIND – The Port D Input Pins Register – read only
PORTB maps to Arduino digital pins 8 to 13 The two high bits (6 & 7) map to the crystal pins and are not usable

DDRB – The Port B Data Direction Register – read/write
PORTB – The Port B Data Register – read/write
PINB – The Port B Input Pins Register – read only
PORTC maps to Arduino analog pins 0 to 5. Pins 6 & 7 are only accessible on the Arduino Mini

DDRC – The Port C Data Direction Register – read/write
PORTC – The Port C Data Register – read/write
PINC – The Port C Input Pins Register – read only
Each bit of these registers corresponds to a single pin; e.g. the low bit of DDRB, PORTB, and PINB refers to pin PB0 (digital pin 8). For a complete mapping of Arduino pin numbers to ports and bits, see the diagram for your chip: ATmega8, ATmega168. (Note that some bits of a port may be used for things other than i/o; be careful not to change the values of the register bits corresponding to them.)

 

Code

This example will set all of PORTB to outputs, a bit of overkill as it will then set all port pins high and then low rather than the individiual built in LED

#include <avr/io.h>
#include <avr/delay.h>
void setup()
{
DDRB = 0xFF;
}
void loop()
{
PORTB = 0xFF;
_delay_ms(1000);
PORTB = 0x00;
_delay_ms(1000);
}

This would set PB5 (Pin 13 – on board LED) only by setting the value of the PORT to 0x32 this is the following in binary – 00100000. Bit 5 is high.

#include <avr/io.h>
#include <avr/delay.h>
void setup()
{
DDRB = 0xFF;
}
void loop()
{
PORTB = 0x32;
_delay_ms(1000);
PORTB = 0x00;
_delay_ms(1000);
}

You can also do this like this, which does show you the bits you are setting and using and can be slightly easier to understand

#include <avr/io.h>
#include <avr/delay.h>
void setup()
{
DDRB = B11111111;
}
void loop()
{
PORTB = B00100000;
_delay_ms(1000);
PORTB = B00000000;
_delay_ms(1000);
}

This method will also switch the built in LED off and on

 

#include <avr/io.h>
#include <avr/delay.h>
 
void setup()
{
DDRB = B11111111;
}
void loop()
{
PORTB = PORTB | 0x20; // Writes PORTB5 low
_delay_ms(500);
PORTB = PORTB & 0xDF; // Writes PORTB5 high
_delay_ms(500);
}

 

Hex size:

Lets look at the blink example, this information is from the Arduino IDE

Sketch uses 1,030 bytes (3%) of program storage space. Maximum is 32,256 bytes.

Now using the bottom example above

Sketch uses 494 bytes (1%) of program storage space. Maximum is 32,256 bytes.

So its clear to see that this basic example will cut down the size of the hex file, not that vital in this example but in more complex examples may be relevant.
Speed.

Port manipulation is quicker than using the Arduino digitalWrite() command, probably not critical if you are just flashing an LED but there are occasions where speed can be an issue

Share

Comments are closed.