My C skills are seriously lacking, and I haven't come up w/ a good way to do this on 8 bit architecture. I've tried shifting by 4, but then I lose digits, I know I can just multiply my 10bit result by 16, but then how do I get the unsigned int into 2- 8 bit registers??

  • 2
    \$\begingroup\$ I am not understanding why you can not just keep the 8 lower as the 8 lower and the 2 upper stored to the 6 upper, with 0s for the rest. It seems like you are expecting some mathematical functional that you are not explaining. \$\endgroup\$ – Kortuk Dec 17 '12 at 2:19
  • 1
    \$\begingroup\$ Perhaps you could draw a picture of what you have and what you want. A little bit of context would help, too. Where does the 10-bit data come from, and how do you expect to use the 14-bit value? \$\endgroup\$ – Dave Tweed Dec 17 '12 at 3:08

Assuming that you do not need to have the result sign extended AND that your goal is simply to normalize the 10-bit input to a 14-bit result then here is code that should do what you require.

// these two byte variables have the 2:8 input values
unsigned char val10_2;
unsigned char val10_8;

// this variable will be used as a working unsigned integer (guessing as 16-bit)
unsigned int temp16;

// these two byte variables will have the 6:8 result values
unsigned char reg14_6;
unsigned char reg14_8;

// combine inputs into an unsigned integer
temp16 = ((val10_2 & 0x03) << 8) | val10_8;

// normalize 10-bit value to 14-bit
temp16 = temp16 << 4;

// extract the final result out to the two 8-bit register values
reg14_6 = (temp16 >> 8) & 0xFF;
reg14_8 = temp16 & 0xFF;

I've included some extra masking of the values in the last two assignments that that may not be strictly necessary and any decent optimizing compiler will eliminate extra steps for you.

  • \$\begingroup\$ Actually, these variables are likely to be hardware registers, such as an input from an ADC. In that case they are declared as volatile, and then the compiler will not be able to optimize away the possibly superfluous extra masking. \$\endgroup\$ – Lundin Dec 17 '12 at 13:46
  • \$\begingroup\$ this seems unlikely to work to me... in particular, I think ((val10_2 & 0x03) << 8) will always result in 0 because val10_2 is a char - better cast it to an int (or better yet use uint16_t from <stdint.h>)... so do (((uint16_t) (val10_2 & 0x03)) << 8) | val10_8 \$\endgroup\$ – vicatcu Dec 17 '12 at 14:41

Let's say int is 16 bits and char is 8 bits.

You can split the 16-bit value into its two component bytes with code like this:

unsigned int val;
unsigned char lsb, msb;

lsb = val & 0x00FF;
msb = (val >> 8) & 0x00FF;

I've just dashed this off off the top of my head. You can probably reduce this code even further with careful study of what C guarantees about type conversions and the specific quirks of your compiler. To be honest, I haven't gone and rechecked the C specs, but the two masks (x & 0x00FF) might not even be required -- but even so, I might keep them in the code to make the intent clear.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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