NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » DDRC =| (1<<PC4) meaning

April 10, 2010
by mark_dixon
mark_dixon's Avatar

I know that this line of code, DDRC |= (1<<PC)

is equivalent to, DDRC = DDRC | (1<<PC4)

which means take the value in the DDRC register and OR it with the 0b10000, since PC4 is defined as 4.

However, what confuses me is when I look for the definition of the DDRC macro, I find things like,

define DDRC _SFR_IO8(0x14)

define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)

ifndef __SFR_OFFSET

if AVR_ARCH >= 100

define __SFR_OFFSET 0x00

else

define __SFR_OFFSET 0x20

endif

endif

which to me means that DDRC is just 0x14 (assuming _SFR_OFFSET is 0x00)

Does this mean that the line of code, DDRC |= (1<<PC4) is equivalent to, 0x14 |= (1<<PC)

?

thanks, Mark

April 10, 2010
by mark_dixon
mark_dixon's Avatar

Sorry my post is looks funny. I wasn't careful with the markup... Mark

April 10, 2010
by Rick_S
Rick_S's Avatar

I'm not exactly sure where you got the code snippet from, but this is from winavr's include file (iom168p.h)

#define DDRC _SFR_IO8(0x07)
#define DDC0 0
#define DDC1 1
#define DDC2 2
#define DDC3 3
#define DDC4 4
#define DDC5 5
#define DDC6 6

And per the Datasheet, that is correct in that DDRC is at address 0x07

(See the register summary near the end of the datasheet)

And to answer the question "Does this mean that the line of code, DDRC |= (1<<PC4) is equivalent to, 0x14 |= (1<<PC) "

No, DDRC is the Data Direction Register for Port C and you are Or'ing your byte with it to set the direction of the pins on the micro.

Hope that helps,

Rick

April 11, 2010
by mark_dixon
mark_dixon's Avatar

Hi Rick,

Thanks.

I was more trying to ask how the compiler knows to treat "DDRC" as a register rather than just a fixed number (sorry, should have been more specific).

For example, in the file sfr_defs.h there is,

#define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)

so the define you show for DDRC,

#define DDRC _SFR_IO8(0x07)

would expand to just 0x07.

Does the compiler treat the string "DDRC" differently from "0x07", or something?

Given the above defines why is,

DDRC |= (1<<DDC4)

any different from

0x7 |= (1<<DDC4)

Thanks again,

Mark

April 11, 2010
by Rick_S
Rick_S's Avatar

I'll be honest with you, I'm not the most proficient person in C. Here is a LINK to the avr_libc documentation that may help. Otherwise, maybe someone with a bit more knowledge than I can help out...

Rick

April 11, 2010
by wayward
wayward's Avatar

I don't know exactly how it works, but I suspect that the macro will eventually expand to a memory-mapped I/O address.

April 12, 2010
by bretm
bretm's Avatar

When compiled with the avr-gcc compiler, _SRF_IO8(io_addr) is

#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)

and not

#define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)

The other definition resolves to 0x07, but this is for assembly programming only. For C programming it gets wrapped in _MMIO_BYTE which is defined as

#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))

Which means it's a pointer to volatile memory.

There are further optimizations in the compiler so that when it sees something like DDRC |= 1<<PC4, it doesn't do the whole "read PORTC, or it with 0b00010000, write it back" sequence. Instead it just uses a "set bit 4" instruction.

Post a Reply

Please log in to post a reply.

Did you know that our USB NerdKit works on Windows, Linux, and Mac OS X? Learn more...