ADC Sample Mode

RTL8721Dx:

ADC only supports sample mode: Continuous Mode. In this mode, ADC samples the channels in the channel list continuously and sequentially. Users can start it or stop it at any time. It is suitable for continuous voltage sampling over short periods.

ADC supports multi-channel sample. Users can configure channel switch list, including channel list length and channel switch order.

ADC works as: each time a trigger signal is generated, ADC will sample all the channels in channel switch list in order.

To use ADC continuous mode, the following steps are mandatory.

  1. Enable clock and function of ADC module.

    RCC_PeriphClockCmd(APBPeriph_ADC, APBPeriph_ADC_CLOCK, ENABLE);
    RCC_PeriphClockCmd(APBPeriph_CTC, APBPeriph_CTC_CLOCK, ENABLE);
    
  2. Configure ADC pinmux according to the pinmux specification.

    For example, call the following functions to use ADC0.

    Pinmux_Config(ADC_CH0_PIN, PINMUX_FUNCTION_xxx); // Refer to pinmux table to get function ID
    PAD_InputCtrl(ADC_CH0_PIN, DISABLE);
    PAD_PullCtrl(ADC_CH0_PIN, GPIO_PuPd_NOPULL);
    PAD_SleepPullCtrl(ADC_CH0_PIN, GPIO_PuPd_NOPULL);
    

    Note

    Step2 could be skipped when user wants to use BAT_MEAS pin.

  3. Initialize ADC parameters and modify ADC mode. ADC samples all the channels sequentially by default.

    ADC_StructInit(ADC_InitTypeDef *ADC_InitStruct);
    ADC_InitStruct->ADC_OpMode = ADC_AUTO_MODE; // Set auto mode
    
  4. Channel list and other parameters can be modified in ADC_InitStruct if needed.

    For example, user sets channel switch list length to 3 and makes ADC sample ADC0/ADC2/ADC4 in order.

    ADC_InitStruct->ADC_CvlistLen = 3 - 1; // Set channel switch list length
    ADC_InitStruct->ADC_Cvlist[0] = ADC_CH0; // Set the 1st channel ID
    ADC_InitStruct->ADC_Cvlist[1] = ADC_CH2; // Set the 2nd channel ID
    ADC_InitStruct->ADC_Cvlist[2] = ADC_CH4; // Set the 3rd channel ID
    
  5. Initialize ADC and enable ADC.

    ADC_Init(ADC_InitTypeDef *ADC_InitStruct);
    ADC_Cmd(ENABLE);
    
  6. Read ADC sample data. Users can acquire ADC sample data in polling mode or interrupt mode.

    • Polling mode:

      ADC_ReceiveBuf(u16 *pBuf, u32 len);
      
    • Interrupt mode:

      ADC_INTConfig(ADC_BIT_IT_FIFO_OVER_EN | ADC_BIT_IT_FIFO_FULL_EN, ENABLE);
      InterruptRegister((IRQ_FUN)ADCIrqHandle, ADC_IRQ, NULL, INT_PRI_MIDDLE);
      InterruptEn(ADC_IRQ, INT_PRI_MIDDLE);
      ADC_AutoCSwCmd(ENABLE);
      

    Where ADCIrqHandle is defined as

    u32 ADCIrqHandle(void *para)
    {
       (void)para;
       u32 status = ADC_GetISR();
    
       if (status & ADC_BIT_IT_FIFO_FULL_STS) {
          while (ADC_Readable()) {
             u32 sample_value = ADC_Read(); // Read out sample value
             if (sample_cnt ++ > MAX_SAMPLE_CNT) { // Get enough sample value
                ADC_AutoCSwCmd(DISABLE);
                ADC_INTConfig(ADC_BIT_IT_FIFO_OVER_EN | ADC_BIT_IT_FIFO_FULL_EN, DISABLE);
                InterruptDis(ADC_IRQ);
                break;
             }
          }
       }
    
       ADC_INTClearPendingBits(status);
       return 0;
    }
    

Note

ADC sample result consists of 4-bit Channel ID and 12-bit sample data. User could get them by the following macros:

  • ADC_GET_CH_NUM_GLOBAL(sample_data): Get 4-bit channel ID

  • ADC_GET_DATA_GLOBAL(sample_data): Get 12-bit sample value

ADC Digital Comparator

The ADC includes a digital comparator that generates an interrupt when the sampled value of a specified channel falls within a configured range. Users can perform specific operations (e.g., reading the current voltage) in the interrupt handler.

Digital comparator can work well under all the ADC sample modes.

Digital comparator supports the following comparison modes:

  • Below Low Threshold

  • Above High Threshold

  • Within Range: Greater than or equal to low threshold AND less than or equal to high threshold

  • Outside Range: Less than low threshold OR greater than high threshold

Note

Low threshold and high threshold values must be in the range 0 to 4095. Low threshold should not be greater than high threshold.

For example, if user wants to use ADC digital comparator under continuous sample mode, the following steps are mandatory.

  1. Enable clock and function of ADC module.

    RCC_PeriphClockCmd(APBPeriph_ADC, APBPeriph_ADC_CLOCK, ENABLE);
    RCC_PeriphClockCmd(APBPeriph_CTC, APBPeriph_CTC_CLOCK, ENABLE);
    
  2. Configure ADC pinmux according to the pinmux specification.

    For example, call the following functions to use ADC0.

    Pinmux_Config(ADC_CH0_PIN, PINMUX_FUNCTION_xxx); // Refer to pinmux table to get function ID
    PAD_InputCtrl(ADC_CH0_PIN, DISABLE);
    PAD_PullCtrl(ADC_CH0_PIN, GPIO_PuPd_NOPULL);
    PAD_SleepPullCtrl(ADC_CH0_PIN, GPIO_PuPd_NOPULL);
    
  3. Assign a channel and configure the low/high thresholds and comparison mode of digital comparator.

    For example, call the function below to set comparison mode of ADC0. An interrupt will arise when the sampled value is between 2000 and 3000.

    ADC_SetComp(ADC_CH0, 3000, 2000, ADC_COMP_WITHIN_THL_AND_THH);
    InterruptRegister((IRQ_FUN)ADCIrqHandle, ADC_IRQ, NULL, INT_PRI_MIDDLE);
    InterruptEn(ADC_IRQ, INT_PRI_MIDDLE);
    

    Where ADCIrqHandle is defined as

    u32 ADCIrqHandle(void *para)
    {
       (void)para;
       u32 status = ADC_GetISR();
       u32 value;
    
       if (status & ADC_BIT_IT_COMP_ALL_STS) {
          printf("ISR:0x%x, Comp status:0x%x\n", status, ADC->ADC_COMP_STS); // ADC sample data is in predefined range
          while (ADC_Readable() == 0);
          value = ADC_Read();
       }
       ADC_INTClearPendingBits(status);
       return 0;
    }
    
  4. Initialize ADC parameters and modify ADC mode. ADC samples all the channels sequentially by default.

    ADC_StructInit(ADC_InitTypeDef *ADC_InitStruct);
    ADC_InitStruct->ADC_OpMode = ADC_AUTO_MODE; // Set auto mode
    
  5. Channel list and other parameters can be modified in ADC_InitStruct if needed.

    For example, user sets channel switch list length to 3 and makes ADC sample ADC0/ADC2/ADC4 in order.

    ADC_InitStruct->ADC_CvlistLen = 3 - 1; // Set channel switch list length
    ADC_InitStruct->ADC_Cvlist[0] = ADC_CH0; // Set the 1st channel ID
    ADC_InitStruct->ADC_Cvlist[1] = ADC_CH2; // Set the 2nd channel ID
    ADC_InitStruct->ADC_Cvlist[2] = ADC_CH4; // Set the 3rd channel ID
    
  6. Initialize ADC and enable ADC.

    ADC_Init(ADC_InitTypeDef *ADC_InitStruct);
    ADC_Cmd(ENABLE);
    
  7. It is suggested to read ADC sample result by polling mode.