Skip to main content
+ note on how avr-libc defines ADC.
Source Link
Edgar Bonet
  • 45.2k
  • 4
  • 42
  • 81

There is no change in representation. analogRead() reads two I/O registers, ADCL and ADCH, which on the Uno are memory-mapped to addresses 0x0078 and 0x0079 respectively. It returns the result in a register pair, r24 and r25, which per the AVR C calling conventions is the standard way of returning a 16-bit number. Thus, r24 holds the value read from ADCL, and r25 the value read from ADCH. That's it. No conversion whatsoever.

There is a change in interpretation... of sorts. The function is declared as returning an int, which on the AVR is a 16-bit signed integer, whereas it could be argued that the I/O registers contain an unsigned number. However, since the sign bit will always be zero, the signed/unsigned distinction is moot: either way the result will be interpreted as a number between 0 and 1023.


Edit: As a clarification: the ADC register (which is another name for the ADCL/ADCH register pair) is a 16-bit I/O register. At the end of a conversion, it holds the 10-bit result right-adjusted into this 16-bit space, zero-padded on the left, as follows:

-------- ADCH --------- --------- ADCL --------
0  0  0  0  0  0  r9 r8 r7 r6 r5 r4 r3 r2 r1 r0
----------------- ADC (16 bits) ---------------

where the bits r9..r0 represent the 10-bit conversion result. Since the MSB is zero, it is irrelevant whether you interpret it as a sign bit or as a regular unsigned bit.

Just for completeness, it could be noted that it is possible (though not through the Arduino core library) to configure the ADC to left-adjust the result, as follows:

-------- ADCH --------- --------- ADCL --------
r9 r8 r7 r6 r5 r4 r3 r2 r1 r0 0  0  0  0  0  0
----------------- ADC (16 bits) ---------------

In this case, the MSB could be one, at it would obviously be incorrect to interpret it as a sign bit.

As a side note, the avr-libc defines ADC as (*(volatile uint16_t *)(0x78)), which is unsigned. And it makes sense considering that, unlike the users of Arduino core, the users of avr-libc are supposed to know they have the choice to get a left-adjusted result.

There is no change in representation. analogRead() reads two I/O registers, ADCL and ADCH, which on the Uno are memory-mapped to addresses 0x0078 and 0x0079 respectively. It returns the result in a register pair, r24 and r25, which per the AVR C calling conventions is the standard way of returning a 16-bit number. Thus, r24 holds the value read from ADCL, and r25 the value read from ADCH. That's it. No conversion whatsoever.

There is a change in interpretation... of sorts. The function is declared as returning an int, which on the AVR is a 16-bit signed integer, whereas it could be argued that the I/O registers contain an unsigned number. However, since the sign bit will always be zero, the signed/unsigned distinction is moot: either way the result will be interpreted as a number between 0 and 1023.


Edit: As a clarification: the ADC register (which is another name for the ADCL/ADCH register pair) is a 16-bit I/O register. At the end of a conversion, it holds the 10-bit result right-adjusted into this 16-bit space, zero-padded on the left, as follows:

-------- ADCH --------- --------- ADCL --------
0  0  0  0  0  0  r9 r8 r7 r6 r5 r4 r3 r2 r1 r0
----------------- ADC (16 bits) ---------------

where the bits r9..r0 represent the 10-bit conversion result. Since the MSB is zero, it is irrelevant whether you interpret it as a sign bit or as a regular unsigned bit.

Just for completeness, it could be noted that it is possible (though not through the Arduino core library) to configure the ADC to left-adjust the result, as follows:

-------- ADCH --------- --------- ADCL --------
r9 r8 r7 r6 r5 r4 r3 r2 r1 r0 0  0  0  0  0  0
----------------- ADC (16 bits) ---------------

In this case, the MSB could be one, at it would obviously be incorrect to interpret it as a sign bit.

There is no change in representation. analogRead() reads two I/O registers, ADCL and ADCH, which on the Uno are memory-mapped to addresses 0x0078 and 0x0079 respectively. It returns the result in a register pair, r24 and r25, which per the AVR C calling conventions is the standard way of returning a 16-bit number. Thus, r24 holds the value read from ADCL, and r25 the value read from ADCH. That's it. No conversion whatsoever.

There is a change in interpretation... of sorts. The function is declared as returning an int, which on the AVR is a 16-bit signed integer, whereas it could be argued that the I/O registers contain an unsigned number. However, since the sign bit will always be zero, the signed/unsigned distinction is moot: either way the result will be interpreted as a number between 0 and 1023.


Edit: As a clarification: the ADC register (which is another name for the ADCL/ADCH register pair) is a 16-bit I/O register. At the end of a conversion, it holds the 10-bit result right-adjusted into this 16-bit space, zero-padded on the left, as follows:

-------- ADCH --------- --------- ADCL --------
0  0  0  0  0  0  r9 r8 r7 r6 r5 r4 r3 r2 r1 r0
----------------- ADC (16 bits) ---------------

where the bits r9..r0 represent the 10-bit conversion result. Since the MSB is zero, it is irrelevant whether you interpret it as a sign bit or as a regular unsigned bit.

Just for completeness, it could be noted that it is possible (though not through the Arduino core library) to configure the ADC to left-adjust the result, as follows:

-------- ADCH --------- --------- ADCL --------
r9 r8 r7 r6 r5 r4 r3 r2 r1 r0 0  0  0  0  0  0
----------------- ADC (16 bits) ---------------

In this case, the MSB could be one, at it would obviously be incorrect to interpret it as a sign bit.

As a side note, the avr-libc defines ADC as (*(volatile uint16_t *)(0x78)), which is unsigned. And it makes sense considering that, unlike the users of Arduino core, the users of avr-libc are supposed to know they have the choice to get a left-adjusted result.

+ clarification about a 10-bit value in a 16-bit register.
Source Link
Edgar Bonet
  • 45.2k
  • 4
  • 42
  • 81

There is no change in representation. analogRead() reads two I/O registers, ADCL and ADCH, which on the Uno are memory-mapped to addresses 0x0078 and 0x0079 respectively. It returns the result in a register pair, r24 and r25, which per the AVR C calling conventions is the standard way of returning a 16-bit number. Thus, r24 holds the value read from ADCL, and r25 the value read from ADCH. That's it. No conversion whatsoever.

There is a change in interpretation... of sorts. The function is declared as returning an int, which on the AVR is a 16-bit signed integer, whereas it could be argued that the I/O registers contain an unsigned number. However, since the sign bit will always be zero, the signed/unsigned distinction is moot: either way the result will be interpreted as a number between 0 and 1023.


Edit: As a clarification: the ADC register (which is another name for the ADCL/ADCH register pair) is a 16-bit I/O register. At the end of a conversion, it holds the 10-bit result right-adjusted into this 16-bit space, zero-padded on the left, as follows:

-------- ADCH --------- --------- ADCL --------
0  0  0  0  0  0  r9 r8 r7 r6 r5 r4 r3 r2 r1 r0
----------------- ADC (16 bits) ---------------

where the bits r9..r0 represent the 10-bit conversion result. Since the MSB is zero, it is irrelevant whether you interpret it as a sign bit or as a regular unsigned bit.

Just for completeness, it could be noted that it is possible (though not through the Arduino core library) to configure the ADC to left-adjust the result, as follows:

-------- ADCH --------- --------- ADCL --------
r9 r8 r7 r6 r5 r4 r3 r2 r1 r0 0  0  0  0  0  0
----------------- ADC (16 bits) ---------------

In this case, the MSB could be one, at it would obviously be incorrect to interpret it as a sign bit.

There is no change in representation. analogRead() reads two I/O registers, ADCL and ADCH, which on the Uno are memory-mapped to addresses 0x0078 and 0x0079 respectively. It returns the result in a register pair, r24 and r25, which per the AVR C calling conventions is the standard way of returning a 16-bit number. Thus, r24 holds the value read from ADCL, and r25 the value read from ADCH. That's it. No conversion whatsoever.

There is a change in interpretation... of sorts. The function is declared as returning an int, which on the AVR is a 16-bit signed integer, whereas it could be argued that the I/O registers contain an unsigned number. However, since the sign bit will always be zero, the signed/unsigned distinction is moot: either way the result will be interpreted as a number between 0 and 1023.

There is no change in representation. analogRead() reads two I/O registers, ADCL and ADCH, which on the Uno are memory-mapped to addresses 0x0078 and 0x0079 respectively. It returns the result in a register pair, r24 and r25, which per the AVR C calling conventions is the standard way of returning a 16-bit number. Thus, r24 holds the value read from ADCL, and r25 the value read from ADCH. That's it. No conversion whatsoever.

There is a change in interpretation... of sorts. The function is declared as returning an int, which on the AVR is a 16-bit signed integer, whereas it could be argued that the I/O registers contain an unsigned number. However, since the sign bit will always be zero, the signed/unsigned distinction is moot: either way the result will be interpreted as a number between 0 and 1023.


Edit: As a clarification: the ADC register (which is another name for the ADCL/ADCH register pair) is a 16-bit I/O register. At the end of a conversion, it holds the 10-bit result right-adjusted into this 16-bit space, zero-padded on the left, as follows:

-------- ADCH --------- --------- ADCL --------
0  0  0  0  0  0  r9 r8 r7 r6 r5 r4 r3 r2 r1 r0
----------------- ADC (16 bits) ---------------

where the bits r9..r0 represent the 10-bit conversion result. Since the MSB is zero, it is irrelevant whether you interpret it as a sign bit or as a regular unsigned bit.

Just for completeness, it could be noted that it is possible (though not through the Arduino core library) to configure the ADC to left-adjust the result, as follows:

-------- ADCH --------- --------- ADCL --------
r9 r8 r7 r6 r5 r4 r3 r2 r1 r0 0  0  0  0  0  0
----------------- ADC (16 bits) ---------------

In this case, the MSB could be one, at it would obviously be incorrect to interpret it as a sign bit.

Source Link
Edgar Bonet
  • 45.2k
  • 4
  • 42
  • 81

There is no change in representation. analogRead() reads two I/O registers, ADCL and ADCH, which on the Uno are memory-mapped to addresses 0x0078 and 0x0079 respectively. It returns the result in a register pair, r24 and r25, which per the AVR C calling conventions is the standard way of returning a 16-bit number. Thus, r24 holds the value read from ADCL, and r25 the value read from ADCH. That's it. No conversion whatsoever.

There is a change in interpretation... of sorts. The function is declared as returning an int, which on the AVR is a 16-bit signed integer, whereas it could be argued that the I/O registers contain an unsigned number. However, since the sign bit will always be zero, the signed/unsigned distinction is moot: either way the result will be interpreted as a number between 0 and 1023.