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
1 Answer 1
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 thein
andout
instructions. Addresses lower than 32 can also be bit-addressed with the instructionssbi
,cbi
,sbis
andsbic
.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 theld
/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>
.
-
I'd just dropped a comment about memory mapping the SBI part on the other answer. It's like having my mind read.timemage– timemage2022年04月18日 13:02:46 +00:00Commented Apr 18, 2022 at 13:02
-
2re: "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– mbrig2022年04月18日 19:46:37 +00:00Commented Apr 18, 2022 at 19:46
PORTB |= _BV(PORTB5)
andDDRB |= _BV(DDB5);
why PORTB generic address is used and what the hell isDDRB |= _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.