Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
10 years, 1 month ago.
read_u16 on the Nucleo F401- least significant nibble equals the most significant nibble?
The code below is a simple demo of reading the ADC from pin A0 on the Nucleo F401.
As I increase the voltage on pin A0, so I surprised to see non-zero values in bits 0..3 I was expecting zeros. I understood this device to have a 12 bit ADC, and that the bits should be shifted left 4 bits for cross-platform compatibility.
However, they are either zero or equal to bits 12..15
It's easy to mask out, but I don't like not understanding the cause.
Can anyone explain why this is happening.
Nick
simple ADC example
#include "mbed.h"
//Function prototype
void doSample1Hz();
//Global objects
Serial pc(USBTX, USBRX);
AnalogIn POT_ADC_In(A0);
DigitalOut led(LED1);
//Shared variables
volatile static unsigned short sample16 = 0;
//The ticker, used to sample data at a fixed rate
Ticker t;
//Main function
int main()
{
//Set baud rate to 115200
pc.baud(115200);
//Set up the ticker - 1Hz
t.attach(doSample1Hz, 1.0);
while(1) {
//Sleep
sleep();
//Display the sample in HEX
pc.printf("ADC Value: %X\n", sample16);
} //end while(1)
} //end main
//ISR for the ticker - simply there to perform sampling
void doSample1Hz()
{
//Toggle on board led
led = !led;
//READ ADC as an unsigned integer - store in static global variable
sample16 = POT_ADC_In.read_u16();
}
1 Answer
10 years, 1 month ago.
If you inspect your target's mbed-src, specifically analogin_api.c, you'll see the 12 to 16 bit conversion:
uint16_t analogin_read_u16(analogin_t *obj) {
uint32_t value = adc_read_u32(obj);
return (value << 4) | ((value >> 8) & 0x000F); // 12 bit
}
Thus the 12 bit value is normalised to the full 16 bit scale.
If the 4 least significant bits were always 0 then the range would be from 0x0000 to 0xfff0, that's not the full range for a 16 bit output. In order to use the full range the value should go from 0x0000 to 0xffff. Copying the 4 most significant bits into the 4 least significant bits is a simple way to achieve this in a nice linear way that avoids any big jumps in the output.
posted by Andy A 17 Sep 2015Some years ago I worked as a DSP engineer and I never encountered this technique. Thanks for highlighting it.
posted by Nicholas Outram 17 Sep 2015