Atmega328p pin manipulation

A normal Atmega328p microcontroller which is commonly used in robotics has 32 pin and 14 of them are digital pin. Digital pin is the most common pin for microcontroller to communicate and receive signal from the circuit. Atmega328p usually run on 16MHz clock speed or 62.5 ns to complete a clock signal. Theorically, Atmega328p should only need 62.5 ns to flip the power state of a digital pin. However, this simple operation will take 3.40 microsecond (3400 ns) to complete if using digitalWrite() from Arduino library. This is 54.4 times longer than the theorical speed and the root cause is digitalWrite() performs a lot of state checking before doing the real state switching. This can protect the Atmega328p from nasty electronic stuff and beginner programmer. As an “experienced” programmer, we need to develop our own fast pin manipulation code.

Mechanism behind the pins

Based on the diagram above provided by AVR, each digital pins is consist of three register, DDRX, PORTX, PINX. Fast pin manipulation can be achieve by reading and writing to the registers. Before we start, we need to know their purpose.

DDRX register

DDRX register aka data direction register is register that control the direction of data flow of a digital pin.

If DDRX state is 0, then digital pin will be input mode.

If DDRx state is 1, the digital pin will be output mode.

register description

DDRB – The Port B Data Direction Register

Bit 7 6 5 4 3 2 1 0
Name DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
IO R/W R/W R/W R/W R/W R/W R/W R/W
Init 0 0 0 0 0 0 0 0

DDRC – The Port C Data Direction Register

Bit 7 6 5 4 3 2 1 0
Name - DC6 DC5 DC4 DC3 DC2 DC1 DC0
IO R R/W R/W R/W R/W R/W R/W R/W
Init 0 0 0 0 0 0 0 0

DDRD – The Port D Data Direction Register

Bit 7 6 5 4 3 2 1 0
Name DD7 DD6 DD5 DD4 DD3 DD2 DD1 DD0
IO R/W R/W R/W R/W R/W R/W R/W R/W
Init 0 0 0 0 0 0 0 0

PORTX register

PORTX register is the register that store data for pin.

In output mode, digital pin will output signal according to PORTX register.

In input mode, digital pin will set pull-up resistor according to PORTX

register description

PORTB – The B Data Register

Bit 7 6 5 4 3 2 1 0
Name PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0
IO R/W R/W R/W R/W R/W R/W R/W R/W
Init 0 0 0 0 0 0 0 0

PORTC – The C Data Register

Bit 7 6 5 4 3 2 1 0
Name - PC6 PC5 PC4 PC3 PC2 PC1 PC0
IO R R/W R/W R/W R/W R/W R/W R/W
Init 0 0 0 0 0 0 0 0

PORTD – The D Data Register

Bit 7 6 5 4 3 2 1 0
Name PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0
IO R/W R/W R/W R/W R/W R/W R/W R/W
Init 0 0 0 0 0 0 0 0

PINX register

PINX register will receive and store the signal from pin in input mode.

register description

PINB – The B Pin Register

Bit 7 6 5 4 3 2 1 0
Name PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0
IO R/W R/W R/W R/W R/W R/W R/W R/W
Init 0 0 0 0 0 0 0 0

PINC – The C Pin Register

Bit 7 6 5 4 3 2 1 0
Name - PC6 PC5 PC4 PC3 PC2 PC1 PC0
IO R R/W R/W R/W R/W R/W R/W R/W
Init 0 0 0 0 0 0 0 0

PIND – The D Pin Register

Bit 7 6 5 4 3 2 1 0
Name PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0
IO R/W R/W R/W R/W R/W R/W R/W R/W
Init 0 0 0 0 0 0 0 0

MCUCR register

MCUCR register as known as MCU control register is a special register for pull-up register control.

register description

MCUCR - The MCU control register

Bit 7 6 5 4 3 2 1 0
Name - BODS BODSE PUD - - IVSEL IVCE
IO R R R R/W R R R/W R/W
Init 0 0 0 0 0 0 0 0

Pin configuration

Different state of register will also change the behavior of digital pin.

DDxn PORTxn PUD (in MCUCR) pull-up resister mode comment
0 0 X Input No Tri-state (Hi-Z)
0 1 0 Input Yes Pxn will source current if ext. pulled low.
0 1 1 Input No Tri-state (Hi-Z)
1 0 X Output No Output low (sink)
1 1 X Output No Output high (source)

Coding part

The theory part is done and lets write some code.

Here’s the code that will turn on pin 6 and turn off pin 9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <avr/io.h>

int main(void) {
// set pin 6 to output mode
DDRD |= 0b01000000;

// set pin 9 to output mode
DDRB |= 0b00000010;

// turn on pin 6
PORTD |= 0b01000000;

// turn off pin 9
PORTB &= 0b11111101;

while(1) {};
}