6
\$\begingroup\$

I am using a STM32F407 discovery board for ADC and I found that the DR or the data register of the ADC can be configured in left or right alignment. What does this mean? Also, what are the advantage/disadvantages of each alignment?

\$\endgroup\$
1
  • \$\begingroup\$ I have not found that in the data sheet but to me it indicates there are more bit spaces in the register then you are getting from the A/D. Right alignment would make the LSB from the A/D bit 0. Left alignment indicates the same but the MSB of the A/D result would be the MSB of the register. The bits will not be seperated and the unused register values will filled with (read data sheet). Think 12 bit result from A/D 16 bit register. \$\endgroup\$ – Gil May 17 at 22:15
12
\$\begingroup\$

Alignment determines how the binary will end up in the hardware register. Suppose you have a 16 bit resolution register (or 2x8 bits) but only 12 bit ADC resolution. Your option is then either to get:

XXXX DDDD DDDD DDDD

or

DDDD DDDD DDDD XXXX

Where "D" is your data bits and "X" is "don't care" bits (usually filled with zeroes). The form requiring the least amount of bitwise arithmetic to get to your desired format is usual the preferred one. One will contain the need to shift, the other won't.

This in turn depends on endianess - the byte order. If the ADC is using the same endianess as your CPU then you'd pick the one matching best. In case of STM32 little endian that probably means the 2nd of the two forms. Built-in ADCs in microcontrollers typically have the same endianess as the CPU. In case of external ones, it could have either big or little endian.

\$\endgroup\$
3
  • 4
    \$\begingroup\$ Also, if you only need 8-bit resolution, and the output can be arranged like dddd dddd-dddd 0000, you can just read the high byte and ignore the low part. Makes more sense on an 8-bit system like AVR, than on a 32-bit system though. \$\endgroup\$ – ilkkachu May 17 at 16:50
  • \$\begingroup\$ What about the precision of the bits you get? I read this is one answer for the same topic. \$\endgroup\$ – Aditya Ubarhande May 18 at 13:02
  • \$\begingroup\$ @AdityaUbarhande What do you mean? You'll get the kind of precision you've specified/what the ADC guarantees. No more, no less. \$\endgroup\$ – Lundin May 18 at 13:08
1
\$\begingroup\$

The STM32 is a 32-bit CPU, but its ADC has a configurable 6, 8, 10 or 12-bit resolution.

If you take a look at the STM32F407's Reference Manual (RM0090) (this link is what I found now, for Rev 19 from Feb 2021), section 12.4, figures 48-50, you see this:

RM0090 Rev19 figs 48-50

With this, you can see that a 16-bit register is being accessed, with the place for each bit from least significant (D0) to most significant (D11 if you're using the 12-bit configuration). You can also see the implications of sign extension (SEXT), which is usually a copy of the most significant bit after applying the injected offset. You can also see the 6-bit special case alignment in figure 50, which hints at the utility of left alignment.

Right alignment is the most obvious: you get the raw bits in the way they come from the ADC, resulting in numbers from zero to formula. If you are capturing with an injected group you can subtract an offset which may make the number negative, hence the sign extension bits.

Left alignment is less obvious, but can be used as a shortcut when one is dealing with fixed-point numbers. If one is considering a "full register" as the number 1.0, then one can add it easily when using the full width of the STM32's 32-bit registers. You can add many of those and then divide/shift when the final result is ready. If you multiply two of them, you get a 32-bit value, which can be rescaled back to 16-bit by a 16-bit shift, which may be faster than, for example, a 12-bit shift, because it would be just a matter of moving a half-word. Then, most of this can be also done with a right-aligned 12-bit word, but you have to manage your bits much more carefully. Perhaps the most benefit comes from the fact that one can start the math operations directly, without shifting the data first. Depending on which operation you're doing, the added bits on the right result in a finer result, with less machine instructions and less risk of having to manage your results bit-by-bit*.

* In the algorithm side, you always have to manage all of it bit-by-bit. However, there's less chance for error if "all operations are 16-bit wide" than if your position is "this operation is 12-bit, this one is 16-bit, and this one is 2*12-16=8-bit" and others.

Example:

You're applying a IIR filter to your ADC sample (12-bit). You multiply your sample with a number, let's say your coefficient is 16-bit and then accumulate in memory for the next iteration. The multiplication results in a 12+16=28 bits. How will you accumulate? As 28-bits? As 12-bits to be the proper scaling? Or a compromise of 16-bits? In the first option, you have to keep track that the number is really 28-bits for when you want to use in the next operation. If the next operation is a multiplication, you have to scale it before multiplying. Did you need to scale it down by 12 or 16 bits? Do you remember, if the algorithm is spread throughout the code? What if you use the number in two other operations? Will you keep track of the number of bits in each of them? Then again, if you scale it back to 12-bit, you lose all the least significant bits. If you store as 16-bits, it seems like a compromise, but you have to shift it by 12 bits, which may (or may not, I don't know the ISA all that much) be slower.

If you set yourself to use only 16-bits, you multiply a "virtual 16-bit" number with another 16-bit number, then shift it by 16-bits and still keeps 4 of the bits.

\$\endgroup\$
2
  • \$\begingroup\$ What about the precision of the bits you get? I read about that in some another answer for the same topic, \$\endgroup\$ – Aditya Ubarhande May 18 at 13:03
  • \$\begingroup\$ @AdityaUbarhande, you get the same bits from the ADC for a given resolution, whether they're right-aligned or left-aligned. Then, when doing calculations, you can (sometimes) "gain or lose" precision, depending on how you handle scaling. If you discard the least significant bits, you lose precision in a sense analogous to quantization, but only up to the point that the bits are actually significant. Sometimes you can "gain" some bits through oversampling or other methods (search "Processing gain"), but not always, so adding more right-side bits also only helps up to a point. \$\endgroup\$ – Ronan Paixão May 20 at 1:11

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.