BackgroundRecently, I designed an optical sensor using Nuvoton M091, which contains 4 low temperature drift chopper stabilization OPAs (0.05 µV/℃). In order to increase the voltage resolution, I set the VREF of the M091 ADC to the built-in 2.048 V.
According to the design, the maximum output voltage of the amplifier is 3.3 V from the supply voltage of the M091 OPA. Later, when I read the datasheet of M091 thoroughly, I found that although the ADC chapter says that the input voltage can be AVDD, the later chapter 8 of the ADC electrical characteristics said it’s 0 V to VREF.
And also it is noted in the datasheet that the injection current will affect other channels, so far I’m thinking, 0 V to VREF is only the range that ADC can convert, or it’s already the upper limit causing the injection current?
Note: Injection current is a important topic of ADC accuracy. Injecting current on any analog input pins should be avoided to protect the conversion being performed on another analog input.
In order to verify this, I bought a development board NuMaker-M091YD for M091 at TECHDesign.
https://www.techdesign.com/market/nuvoton/product-detail/ntc000753/numaker-m091ydAfter getting the development board, there are two switches to adjust:1. Switch the TXD and RXD of ICESW2 to the ON position to get the printf() message from the UART.
2. Switch the NU1_3VCC of the SW2 to the ON position, allow the board to get 3.3 V power.
Modify the boardIn order to make the M091 switch to the built-in VREF, remove the L5 on the development board so that remove the AVDD from VREF pin. Nuvoton design is very intimate, both ends of L5 are connected to a 2-pin header, I soldered the header at the same time, so that if you want to use AVDD as a VREF, the only things to do is plug a jumper on it, and no need to re-solder the L5 which has been remove.
Test Method:The test method is very simple, that is: set an IO as the input of the ADC, and then connect an ammeter to 3.3 V, and read this analog pin with fixed sampling rate in the firmware (this allow input signal can enter the ADC), and compare to see if the input current is greatly increased when the VIN is 3.3 V, the VREF is 3.3 V or the built-in 2.048 V.
The test code
A simple program that makes the ADC sample every 1 ms in a loop. Here is the input to the ADC with PB.7/ADC0_CH7.
#include <stdio.h>
#include "NuMicro.h"
void SYS_Init(void)
{
/* Unlock protected registers */
SYS_UnlockReg();
/* Enable HIRC clock (Internal RC 48MHz) */
CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);
/* Wait for HIRC clock ready */
CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
/* Select HCLK clock source as HIRC and HCLK source divider as 1 */
CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1));
/* Enable UART0 clock */
CLK_EnableModuleClock(UART0_MODULE);
/* Switch UART0 clock source to HIRC */
CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));
/* Enable ADC module clock */
CLK_EnableModuleClock(ADC_MODULE);
/* ADC clock source is PCLK1, set divider to 1 */
CLK_SetModuleClock(ADC_MODULE, CLK_CLKSEL2_ADCSEL_PCLK1, CLK_CLKDIV0_ADC(1));
/* Update System Core Clock */
SystemCoreClockUpdate();
/* Set PB multi-function pins for UART0 RXD=PB.12 and TXD=PB.13 */
SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk)) | \
(SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);
/* Configure the PB.7 ADC analog input pins. */
SYS->GPB_MFPL = (SYS->GPB_MFPL & ~SYS_GPB_MFPL_PB7MFP_Msk) | SYS_GPB_MFPL_PB7MFP_ADC0_CH7;
/* Disable the PB.7 digital input path to avoid the leakage current. */
GPIO_DISABLE_DIGITAL_PATH(PB, BIT7);
/* Lock protected registers */
SYS_LockReg();
}
void main()
{
uint32_t u32Result;
SYS_Init();
/* Init UART0 to 115200-8n1 for print message */
UART_Open(UART0, 115200);
/* Connect UART to PC, and open a terminal tool to receive following message */
printf("Hello World\n");
ADC_POWER_ON(ADC);
ADC_Open(ADC, ADC_ADCR_DIFFEN_SINGLE_END, ADC_ADCR_ADMD_SINGLE_CYCLE, BIT7);
ADC_SetExtendSampleTime(ADC, 0, 255);
/* Got no where to go, just loop forever */
while(1)
{
/* Trigger sample module 0 to start A/D conversion */
ADC_START_CONV(ADC);
while(!ADC_IS_DATA_VALID(ADC, 7));
/* Get the conversion result of the sample module 0 */
u32Result = ADC_GET_CONVERSION_DATA(ADC, 7);
CLK_SysTickDelay(1000);
}
}Measuring the input current when VREF=3.3 V and VIN=3.3 VNow using AVDD as VREF, the 2-pin header should be shorted with jumper.
The input current is 4.6 nA.
Switch the VREF to the built-in 2.048 VRemember to remove the jumper on the 2-pin header before switching, because the VREF pin is basically directly connected to the VREF in the chip.
I sort out the process of switching to the built-in VREF from TRM:
- Enable the band-gap reference which alone with the built-in temperature sensor (this also for the internal VREF and DAC to operate)
- After activating the band-gap reference, you must wait for a 200 microsecond settling time
- Switch the reference voltage source to the built-in 2.048 V and the preload function is automatically enabled by the hardware, reducing the settling time
- Wait for the settling time after switching the reference voltage source, and the settling time TS depends on the external bypass capacitor, see 8.5.4 in datasheet
- Manually turned off the preload function to prevent the load effect from affecting the accuracy of the reference voltage source
The following lines should be added to the SYS_Init() in the firmware to switch to the built-in 2.048 V:
/* Temperature sensor band-gap will be enabled and Temperature sensor will supply current source to DAC and Internal Voltage Reference. */
SYS->TSCTL |= SYS_TSCTL_TSBGEN_Msk;
/* After TSBGEN is set, users should wait 200us stable time to enable DACEN(DACx_CTL[0]) or VREFEN (SYS_VREFCTL[0]). */
CLK_SysTickDelay(200);
/* Set VREF to 2.048 V */
SYS_SetVRef(SYS_VREFCTL_VREF_2_0V);
/* PRELOADEN should be cleared after 480us of VREFEN enabled, if VREF capacitor is 1uF and VREF initial is 0V. */
CLK_SysTickDelay(480);
/* When VREFEN is set to 1, PRELOADEN(SYS_VREFCTL[6]) will be set automatically to shorten VREF discharge and stable time. */
/* User needs to disable PRELOADEN function after stable time, otherwise it will affect the maximum load current that INT_VREF can provide. */
SYS->VREFCTL &= ~(SYS_VREFCTL_PRELOADEN_Msk);If switch successfully, should be able to actually measure 2.048 V on the VREF.
Now, let’s measuring the input current when VREF=2.048 V and VIN=3.3 VThe input current is 9.7 nA.
ConclusionThe general conditions for use of ADCs are AVDD≧VREF≧VIN.
The main question discussed in this experiment is: when VREF<AVDD and AVDD>VIN > VREF, will VIN have unreasonable injection current that causes the chip to operate abnormally or even damage the chip? - While AVDD=VREF=VIN=3.3 V, the input current is 4.6 nA
- While AVDD=VIN=3.3 V, VREF=2.048 V, the input current is 9.7 nA
From the experimental results, when the VIN is higher than the VREF (but the VIN is not higher than the AVDD) the current increase is reasonable, that’s not like the injection current, which will not damage the chip, the 8.5.2 12-bit SAR ADC in the datasheet shows that the VIN range is 0~VREF, which should refer to the range that can be converted (the effective range), but the ADC cannot parse the actual input signal while out of this range.
It should be noted that the VIN should not be higher than the AVDD, which is an unreasonable condition of use and will cause the risk of injected current (refer to table 8.1-2 in DS):

The SAR ADC input is a comparator that compares the conversion results with the DAC, while the VREF is usually only connected to the DAC as the reference voltage for the DAC. That's right! The ADC contains the DAC. Take a look if you are interested in the principle of ADC.
https://en.wikipedia.org/wiki/Successive-approximation_ADCSo, it's just like when we are using a comparator alone, VIN+ can be higher than VIN-, but neither VIN can be higher than the supply voltage, right?