Chart or tutorial on hexidecimal output/input codes?

Go To Last Post
20 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry if this has been asked/answered before, but I'm such a noob I don't really know what to search for.

While going over some example code, I ran across this:

DDRB = 0x1F; // PB0-PB4 output

Where can I find a chart or explanation on how to tell what the hexidecimal values would be for different pin configurations?

Thank you all.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
DDRB = 0x1F;       // PB0-PB4 output
DDRB = 31;         // PB0-PB4 output
DDRB = 0b00011111; // PB0-PB4 output

http://en.wikipedia.org/wiki/Hex...

http://en.wikipedia.org/wiki/Dat...

http://en.wikipedia.org/wiki/RTFM

Warning: Grumpy Old Chuff. Reading this post may severely damage your mental health.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

More generally

0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
A 1010
B 1011
C 1100
D 1101
E 1110
F 1111

So 0x1F (the 0x means "hex") becomes:

0001 1111

(as MBedder showed).
The columns are 128 64 32 16 8 4 2 1. So 00011111 means 16+8+4+2+1 = 31 in decimal (as MBedder also showed).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

beyond understanding how to translate between numeric bases, you also need to understand the hardware, and for that you need to start by reading the datasheet for the device you are working with.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Get a calculator or calculator app that does dec/hex/bin conversions. Even the Windows calculator will do this when you change it to scientific mode.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Get a calculator or calculator app that does dec/hex/bin conversions. Even the Windows calculator will do this when you change it to scientific mode.

Downside of that is that you don't learn how to the things really relate. The calculator doesn't tell you that the reason 0x50=80 is because 5*16=80

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

http://www.pcguide.com/res/tablesASCII-c.html

One of these is very handy too.

--greg
Still learning, don't shout at me, educate me.
Starting the fire is easy; the hardest part is learning how to keep the flame!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Where can I find a chart or explanation on how to tell what the hexidecimal values would be for different pin configurations?
I think he is asking a more basic question about this:
    DDRB = 0x1F; // PB0-PB4 output
This is a case where using the appropriate radix would make things easier to understand. Since the Data Direction Register is bitmapped the hex value 1F (or 31 decimal) does not have any specific meaning but the binary version of 00011111 does.

Each bit in the register controls the data direction for the corresponding port pin. Eaxh '0' bit sets that port pin for input and each '1' bit sets the port pin for output. So in this case port pins 7, 6, and 5 are input and 4, 3, 2, 1, and 0 are output.

I prefer to write this as:

    DDRB = 0b00011111; // PB0-PB4 output

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

At a glance...asciitable.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

floresta1212 wrote:
[T]he hex value 1F (or 31 decimal) does not have any specific meaning but the binary version of 00011111 does.
Nonsense. The three notations are simply different ways of expressing the same value. I agree that the base-2 form is perhaps easier for beginners to relate to what happens in the registers but it also more cumbersome to read and type. Once you've become accustomed to using base-16, however, it is just as easy to relate to the register effect and it much faster to read and type. Base-10 values make the least sense in this context yet I've seen plenty of cases where people have done just that.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also note that binary notation is not supported by all C compilers. Binary notation is a relatively new addition to the C standard. It's support will vary depending on which version of the standard the tools you are using conform to.

It is often better to explicately call out each bit being set/cleard by name, instead of using "magic numbers". While more cumbersome to type they are less error prone and much easier to read. [I will admit that for the PORTx/DDRx/PINx registers it's probably a wash in terms of benefit, but for other I/O's it has a clear advantage of being concise]

Thus

DDRB = 0x1F; // PB0-PB4 output 

would be written as:

DDRB = (0<<PB7) | (0<<PB6) | (0<<PB5) | (1<<PB4) | \
       (1<<PB3) | (1<<PB2) | (1<<PB1) | (1<<PB0);

Admittadly the above can be a bit confusing at first, but once you get used to the notation, it is very easy to read.

It can be enhanced a bit by defining a couple of constants [for in and out].

#define DD_IN  0
#define DD_OUT 1

DDRB = (DD_IN  << PB7) | (DD_IN  << PB6) | \
       (DD_IN  << PB5) | (DD_OUT << PB4) | \
       (DD_OUT << PB3) | (DD_OUT << PB2) | \
       (DD_OUT << PB1) | (DD_OUT << PB0);

If you find yourself doing this a lot, you can wrap the whole thing in a macro as well.

#define DD_IN  0
#define DD_OUT 1

#define BITMAP(B7, B6, B5, B4, B3, B2, B1, B0) \
                ((B7 << 7) | (B6 << 6) | \
                 (B5 << 5) | (B4 << 4) | \
                 (B3 << 3) | (B2 << 2) | \ 
                 (B1 << 1) | (B0 << 0))

DDRB = BITMAP( DD_IN,  DD_IN,  DD_IN, DD_OUT, \
              DD_OUT, DD_OUT, DD_OUT, DD_OUT);

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

glitch wrote:
Also note that binary notation is not supported by all C compilers. Binary notation is a relatively new addition to the C standard. It's support will vary depending on which version of the standard the tools you are using conform to.

Actually it's not in any standard, not even the near-final C1x draft (1.6M PDF).

It is, however, supported by many compilers, including gcc, clang/llvm, and icc at least.

If you need greater portability, you can use BOOST_BINARY; while Boost is primarily a C++ library, this is a preprocessor macro that works equally in C. It also lets you embed blanks in the constant, which can aid readability.

uint8_t k = BOOST_BINARY( 1001 0011 );
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You appear to be correct... for some reason I thought it was added to the c99 spec. [obviously a brain-fart]

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey guys, take a closer look at the original post and specifically at the thread 'subject'. He was interested in how the hex value of 1F was derived in terms of input and output directions on Port D. He didn't need references to the definition of 'datasheet', how to convert decimal to binary, or a pointer to an ASCII table. Everyone has to start somewhere. His was a valid question if you look at the actual question, and he shouldn't have been told to RTFM.

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kpschoedel wrote:
BOOST_BINARY
Just out of curiosity I looked at the macro. Wow! I wonder if they submitted it to an obfuscated code contest. I think it would fare well.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
take a closer look at the original post and specifically at the thread 'subject'.
But his question was:
Quote:
Where can I find a chart or explanation on how to tell what the hexidecimal values would be for different pin configurations?
This has been answered above.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
This has been answered above.
I agree. We will just have to wait to hear from BackWoodsBrewer to find out which of the answers helped him the most.

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ezharkov wrote:
kpschoedel wrote:
BOOST_BINARY
Just out of curiosity I looked at the macro. Wow! I wonder if they submitted it to an obfuscated code contest. I think it would fare well.

Not obfuscated [at least not purposfully] they are doing what is required to make the C pre-processor appear to perform recursion, and intelligent parsing. This is done by generating every possibly value for a result, and storing it in a unique macro. This is ecause a macro [or any sub-macros] is not allowed to refer to itself [or referring macro]. Macros are simple text-replacement, no additional processing is available, thus a tree of possible branches must be created.

Here's a simplified example of what's going on:

// note that the correct number of bits must be passed,
// passing too few, or too many, will result in error descriptions 
// that are none too helpful, unless you understand how the macros work
// the input is a sequence of 0's and 1's [and possibly spaces] defining a 4 bit binary pattern

#define BITMAPPER(A) MKBITS4(_, A)

// MKBITSxxx Macros:
//  Parameter1 is the cumulative result so far
//  Parameter 2 is whatever remains of the input
#define MKBITS4(A, B) BM##A##B##)
#define MKBITS3(A, B) BM##A##B##)
#define MKBITS2(A, B) BM##A##B##)
#define MKBITS1(A, B) BM##A##B##)
#define MKBITS0(A, B) BITS##A##B

// the BMxxx Macros:
// These macros peel off the first part of the string up to any space
// and recurse back by passing whatever remains to a MKBITSxxx macro, whild also passing forward the pattern so far
#define BM_0 MKBITS3(_0,
#define BM_1 MKBITS3(_1, 

#define BM_00 MKBITS2(_00,
#define BM_01 MKBITS2(_01, 
#define BM_10 MKBITS2(_10,
#define BM_11 MKBITS2(_11, 

#define BM_000 MKBITS1(_000,
#define BM_001 MKBITS1(_001, 
#define BM_010 MKBITS1(_010,
#define BM_011 MKBITS1(_011,
#define BM_100 MKBITS1(_100,
#define BM_101 MKBITS1(_101, 
#define BM_110 MKBITS1(_110,
#define BM_111 MKBITS1(_111, 

#define BM_0000 MKBITS0(_0000,
#define BM_0001 MKBITS0(_0001,
#define BM_0010 MKBITS0(_0010,
#define BM_0011 MKBITS0(_0011,
#define BM_0100 MKBITS0(_0100,
#define BM_0101 MKBITS0(_0101,
#define BM_0110 MKBITS0(_0110,
#define BM_0111 MKBITS0(_0111,
#define BM_1000 MKBITS0(_1000,
#define BM_1001 MKBITS0(_1001,
#define BM_1010 MKBITS0(_1010,
#define BM_1011 MKBITS0(_1011,
#define BM_1100 MKBITS0(_1100,
#define BM_1101 MKBITS0(_1101,
#define BM_1110 MKBITS0(_1110,
#define BM_1111 MKBITS0(_1111,

// our parsing results
#define BITS_0000 0x00
#define BITS_0001 0x01
#define BITS_0010 0x02
#define BITS_0011 0x03
#define BITS_0100 0x04
#define BITS_0101 0x05
#define BITS_0110 0x06
#define BITS_0111 0x07
#define BITS_1000 0x08
#define BITS_1001 0x09
#define BITS_1010 0x0a
#define BITS_1011 0x0b
#define BITS_1100 0x0c
#define BITS_1101 0x0d
#define BITS_1110 0x0e
#define BITS_1111 0x0f

using a code generator this can easily be extended to as many bits as desired.

Example evaluation breakdown:

var = BITMAPPER(0 1 0 1)
var = MKBITS4(_, 0 1 0 1)
var = BM_0 1 0 1)
var = MKBITS3(_0, 1 0 1)
var = BM_01 0 1)
var = MKBITS2(_01, 0 1)
var = BM_010 1)
var = MKBITS1(_010, 1)
var = BM_0101)
var = MKBITS0(_0101, )
var = BITS_0101
var = 0x05


// same pattern, but bits grouped in pairs
var = BITMAPPER(01 01)
var = MKBITS4(_, 01 01)
var = BM_01 01)
var = MKBITS2(_01, 01)
var = BM_0101)
var = MKBITS0(_0101, )
var = BITS_0101
var = 0x05

Note how the two macros [MKBITSxxx & BMxxx] come together to form the next macro call.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

He's not your typical student with a project due yesterday but you did a good job of scaring him away anyway.

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks guys, yes Don correctly interpreted my "noobness", I was interested in how the hex value related to the input/output assignment. This definitely turned into an interesting topic to go through :)