Note

This article is a part of Arduino / ATmega328p Embedded C Firmware Programming Tutorial. Consider exploring the course home page for articles on similar topics.

Arduino Tutorial Embedded C Register Level Arduino Master Class

Arduino Tutorial Embedded C Register Level Arduino Master Class

Also visit the Release Page for Register Level Embedded C Hardware Abstraction Library and Code for AVR.

Introduction

Atmega328p is used as an example to explain the concepts but they are applicable to all the AVR 8-bit Microcontrollers.

All AVR ports have true Read-Modify-Write functionality when used as general digital I/O ports. This means that the direction of one port pin can be changed without unintentionally changing the direction of any other pin with the SBI and CBI instructions. The same applies when changing drive value (if configured as an output) or enabling/disabling pull-up resistors (if configured as input). Each output buffer has symmetrical drive characteristics with both high sink and source capability. The pin driver is strong enough to drive LED displays directly. All port pins have individually selectable pull-up resistors with a supply-voltage invariant resistance. All I/O pins have protection diodes to both VCC and Ground.

AVR GPIO I/O Pin Equivalent Schematic
AVR GPIO I/O Pin Equivalent Schematic

All registers and bit references in this section are written in a general form. A lower case “x” represents the numbering letter for the port, and a lower case “n” represents the bit number. However, when using the register or bit defines in a program, the precise form must be used. For example, PORTB3 for a bit no. 3 in Port B, here documented generally as PORTxn.

Three I/O memory address locations are allocated for each port, one each for

  • Data Register – PORTx – Read Write
  • Data Direction Register – DDRx – Read Write
  • Port Input Pins – PINx  Read Only

What You Will Learn

  • What are the IO Port Registers in Arduino?
  • What are the GPIO Registers in AVR ATmega328p?
  • Which AVR Registers control and configures Digital Input Output?
  • What is the function of the PORT, DDR and PIN Registers?

Ports as General Digital I/O

The ports are bi-directional I/O ports with optional internal pull-ups.

AVR I/O Detailed Block Diagram
AVR I/O Detailed Block Diagram
WRx, WPx, WDx, RRx, RPx, and RDx are common to all pins within the same port. clkI/O, SLEEP, and PUD are common to all ports

The DDxn bit in the DDRx Register selects the direction of this pin. If DDxn is written logic one, Pxn is configured as an output pin. If DDxn is written logic zero, Pxn is configured as an input pin.

DDRB76543210
0x04 (0x24)DDRB7DDRB6DDRB5DDRB4DDRB3DDRB2DDRB1DDRB0
Read/WriteR/WR/WR/WR/WR/WR/WR/WR/W
Initial Value00000000
DDRC76543210
0x07 (0x27)DDRC7DDRC6DDRC5DDRC4DDRC3DDRC2DDRC1DDRC0
Read/WriteR/WR/WR/WR/WR/WR/WR/WR/W
Initial Value00000000
DDRD76543210
0x0A (0x2A)DDRD7DDRD6DDRD5DDRD4DDRD3DDRD2DDRD1DDRD0
Read/WriteR/WR/WR/WR/WR/WR/WR/WR/W
Initial Value00000000

If PORTxn is written logic one when the pin is configured as an input pin, the pull-up resistor is activated. To switch the pull-up resistor off, PORTxn has to be written logic zero, or the pin has to be configured as an output pin. The port pins are tri-stated when the reset condition becomes active, even if no clocks are running.

If PORTxn is written logic one when the pin is configured as an output pin, the port pin is driven high (one). If PORTxn is written logic zero when the pin is configured as an output pin, the port pin is driven low (zero).

PORTB76543210
0x05 (0x25)PORTB7PORTB6PORTB5PORTB4PORTB3PORTB2PORTB1PORTB0
Read/WriteR/WR/WR/WR/WR/WR/WR/WR/W
Initial Value00000000
PORTC76543210
0x08 (0x28)PORTC7PORTC6PORTC5PORTC4PORTC3PORTC2PORTC1PORTC0
Read/WriteR/WR/WR/WR/WR/WR/WR/WR/W
Initial Value00000000
PORTD76543210
0x0B (0x2B)PORTD7PORTD6PORTD5PORTD4PORTD3PORTD2PORTD1PORTD0
Read/WriteR/WR/WR/WR/WR/WR/WR/WR/W
Initial Value00000000

Writing a logic one to PINxn toggles the value of PORTxn, independent of the value of DDRxn. Note that the SBI instruction can be used to toggle one single bit in a port.

Independent of the setting of Data Direction bit DDxn, the port pin can be read through the PINxn Register bit.

PINB76543210
0x03 (0x23)PINB7PINB6PINB5PINB4PINB3PINB2PINB1PINB0
Read/WriteR/WR/WR/WR/WR/WR/WR/WR/W
Initial ValueN/AN/AN/AN/AN/AN/AN/AN/A
PINC76543210
0x06 (0x26)PINC7PINC6PINC5PINC4PINC3PINC2PINC1PINC0
Read/WriteR/WR/WR/WR/WR/WR/WR/WR/W
Initial ValueN/AN/AN/AN/AN/AN/AN/AN/A
PIND76543210
0x09 (0x29)PIND7PIND6PIND5PIND4PIND3PIND2PIND1PIND0
Read/WriteR/WR/WR/WR/WR/WR/WR/WR/W
Initial ValueN/AN/AN/AN/AN/AN/AN/AN/A
//Refer the table above
unsigned char i;
...
/* Define pull-ups and set outputs high */
/* Define directions for port pins */
PORTB = (1<<PB7)|(1<<PB6)|(1<<PB1)|(1<<PB0);
DDRB = (1<<DDB3)|(1<<DDB2)|(1<<DDB1)|(1<<DDB0);
/* Insert nop for synchronization*/
__no_operation();
/* Read port pins */
i = PINB;
...

If some pins are unused, it is recommended to ensure that these pins have a defined level. Even though most of the digital inputs are disabled in the deep sleep modes as described above, floating inputs should be avoided to reduce current consumption in all other modes where the digital inputs are enabled (Reset, Active mode, and Idle mode).

The simplest method to ensure a defined level of an unused pin is to enable the internal pull-up. In this case, the pull-up will be disabled during the reset. If low power consumption during reset is important, it is recommended to use an external pull-up or pull-down. Connecting unused pins directly to VCC or GND is not recommended, since this may cause excessive currents if the pin is accidentally configured as an output.

DDxn PORTxn PUD
(in MCUCR)
I/O Pull-up 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)

MCUCR – MCU Control Register

MCUCR76543210
0x35 (0x24)BODSBODSEPUDIVSELIVCE
Read/WriteRR/WR/WR/WRRR/WR/W
Initial Value00000000

• Bit 4 – PUD: Pull-up Disable
When this bit is written to one, the pull-ups in the I/O ports are disabled even if the DDxn and PORTxn Registers are configured to enable the pull-ups ({DDxn, PORTxn} = 0b01).



Crazy Engineer

MAKER - ENGINEER - YOUTUBER

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.