5

So Let say I want to access Digital Pin 13. Thats port B pin. Is there an memory address associated with this pin 13 of Arduino Uno r3?

How Port B pins are addressed with corresponding pin numbers like What is the address of digital pin 13?

Currently I am assuming its pin address is 0x05 so my pointer looks like this

    uint8_t *adr=0x00+0x05;

Now If I do

  *adr |= 0x20;

then should I expect that I am writing to some pin so I like to know which data sheet I should refer for pin addresses of port B?

Currently my code is not working because no matter which pin I connect my LED to it blinks. What if I dont want to use any library and just write to address and I need PORT B pin address how to refer to different pins?

Now assume I have a code that uses avr gcc

#include <avr/iom328p.h>//avr/io.h
#include    <util/delay.h>
#include <avr/sfr_defs.h>


#define     BLINK_DELAY_MS  18000

int main (void)
{
    DDRB |= _BV(DDB5);

    while(1)
    {
        PORTB |= _BV(PORTB5);
        _delay_ms(BLINK_DELAY_MS);

        PORTB &= ~_BV(PORTB5);
        _delay_ms(BLINK_DELAY_MS);
    }

    return 0;
}

What is the values correspond to DDRB and _BV(DDB5); and PORTB and _BV(PORTB5);? I like to do it with pointers so I need addresses of PORT B all pins I know the macros but I like the actual addresses . there should be a some datasheet for this what its called. Does arduino has it that gives memory mapped addresses?

The above code is simply for blinking LED light

5
  • 2
    What did you find when you looked into the included header files? What did you find when you read the documentation of avr-libc? What did you find when you looked into the Mega128 data sheet? Why did this not help you? Apr 18, 2022 at 9:36
  • @thebusybee what not making sense to me is this PORTB |= _BV(PORTB5) and DDRB |= _BV(DDB5); why PORTB generic address is used and what the hell is DDRB |= _BV(DDB5); where is the documentation on this memory mapped io. This is simple question. I checked gcc avr it's has addresses. But shouldn't there be some description for these macros and addresses. It's must be in data sheet but wait what I actually found was tuns of pages about pin layouts when search for arduino uno r3 datasheet.
    – user786
    Apr 18, 2022 at 10:05
  • That's why this question. It should have been pretty simple for what I am looking for but seems like there is lack of info. I need explanation
    – user786
    Apr 18, 2022 at 10:05
  • 1
    Exercise your web search skills and look for "atmega128p data sheet" and "avr-libc". You might need to read and think a bit, not everything in the real world is answered right away in the first link especially for you. We expect a bit of effort on your own. Apr 18, 2022 at 10:12
  • 1
    I think your problem is some misconception about how are io pins handled. Port is for multiple io pins. One io port is handled with one bit of the port register.
    – Juraj
    Apr 18, 2022 at 10:52

1 Answer 1

6

The address of PORTB can be found in the ATmega328P datasheet, section “I/O-Ports”, subsection “Register Description”. It is repeated near the end of the section “Register Summary”, where it is documented as:

0x05 (0x25)

Admittedly, this is confusing: there are two addresses! There is a footnote that gives some hint on the reason:

When using the I/O specific commands IN and OUT, the I/O addresses 0x00 - 0x3F must be used. When addressing I/O Registers as data space using LD and ST instructions, 0x20 must be added to these addresses.

To clarify, this register is mapped in two different address spaces:

  • It has I/O address 0x05. The I/O address space is a small (6 bits) address space dedicated to I/O registers. It is actually too small to host all the I/O registers. It can be accessed with the in and out instructions. Addresses lower than 32 can also be bit-addressed with the instructions sbi, cbi, sbis and sbic.

  • It has data address 0x25. This is a much larger address space that gives access to all the I/O registers and to the RAM. It is used with the ld/st family of instructions.

Since the C and C++ languages are not aware of the I/O address space, a regular data pointer is assumed to always point to the data address space. Thus, if you want to create a pointer to this register, you may write:

volatile uint8_t *adr = 0x25;  // PORTB

Note the volatile qualifier. This is required to prevent the compiler being too “smart” and optimizing out some of your writes under the assumption that this is just RAM.

Then you may turn the LED on with:

*adr |= 1 << 5;  // set PORTB5

Withe the proper optimization options, the compiler may be able to optimize this into sbi 0x05, 0x05, if it can prove that the address stored in the pointer doesn't change.

I need addresses of PORT B all pins I know the macros but I like the actual addresses.

I would recommend this:

volatile uint8_t *adr = &PORTB;

This avoids having magic numbers in your code, and makes the programmer's intent clear.

One last comment. When compiling your code I got:

include/avr/iom328p.h: [...]
error "Include <avr/io.h> instead of this file."

Just include <avr/io.h>: this header takes care of including both the correct <avr/iomXXX.h> and <avr/sfr_defs.h>.

2
  • I'd just dropped a comment about memory mapping the SBI part on the other answer. It's like having my mind read.
    – timemage
    Apr 18, 2022 at 13:02
  • 2
    re: "if it can prove that the address stored in the pointer doesn't change": you can give it a hand by making the pointer const, e.g. volatile uint8_t * const adr
    – mbrig
    Apr 18, 2022 at 19:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.