[DemoCode下载] 使用ADC测量AVDD供电电压方法

[复制链接]
 楼主| zhuotuzi 发表于 2025-1-24 16:35 | 显示全部楼层 |阅读模式
  1. /****************************************************************************
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V3.0
  4. * $Revision: 1 $
  5. * $Date: 16/06/29 4:40p $
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]    Measure AVDD voltage by ADC.
  7. * @note
  8. * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
  9. *
  10. ******************************************************************************/
  11. #include <stdio.h>
  12. #include "M058S.h"

  13. #define PLL_CLOCK       50000000

  14. #define VBG_VOLTAGE (1200) /* 1.20V = 1200 mV (Typical band-gap voltage of M058S series) */
  15. #define ADC_SAMPLE_COUNT 128 /* The last line of GetAVDDCodeByADC() need revise when ADC_SAMPLE_COUNT is changed. */
  16. /* For example, if ADC_SAMPLE_COUNT is changed to 64, then the code need revised to "return (u32Sum >> 6);" */

  17. /*---------------------------------------------------------------------------------------------------------*/
  18. /* Define Function Prototypes                                                                              */
  19. /*---------------------------------------------------------------------------------------------------------*/
  20. void SYS_Init(void);
  21. void UART0_Init(void);
  22. void AdcMeasureAVDD(void);
  23. uint32_t GetAVDDCodeByADC(void);
  24. uint32_t GetAVDDVoltage(void);

  25. /*---------------------------------------------------------------------------------------------------------*/
  26. /* Define global variables and constants                                                                   */
  27. /*---------------------------------------------------------------------------------------------------------*/
  28. volatile uint8_t g_u8ADF;


  29. void SYS_Init(void)
  30. {
  31.     /*---------------------------------------------------------------------------------------------------------*/
  32.     /* Init System Clock                                                                                       */
  33.     /*---------------------------------------------------------------------------------------------------------*/

  34.     /* Enable Internal RC 22.1184 MHz clock */
  35.     CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

  36.     /* Waiting for Internal RC clock ready */
  37.     CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);

  38.     /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
  39.     CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));

  40.     /* Enable external XTAL 12 MHz clock */
  41.     CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);

  42.     /* Waiting for external XTAL clock ready */
  43.     CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);

  44.     /* Set core clock as PLL_CLOCK from PLL */
  45.     CLK_SetCoreClock(PLL_CLOCK);

  46.     /* Enable UART module clock */
  47.     CLK_EnableModuleClock(UART0_MODULE);

  48.     /* Enable ADC module clock */
  49.     CLK_EnableModuleClock(ADC_MODULE);

  50.     /* Select UART module clock source */
  51.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_PLL, CLK_CLKDIV_UART(1));

  52.     /* ADC clock source is 22.1184 MHz, set divider to 7, ADC clock is 22.1184/7 MHz */
  53.     CLK_SetModuleClock(ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_CLKDIV_ADC(7));

  54.     /*---------------------------------------------------------------------------------------------------------*/
  55.     /* Init I/O Multi-function                                                                                 */
  56.     /*---------------------------------------------------------------------------------------------------------*/

  57.     /* Set P3 multi-function pins for UART0 RXD and TXD */
  58.     SYS->P3_MFP &= ~(SYS_MFP_P30_Msk | SYS_MFP_P31_Msk);
  59.     SYS->P3_MFP |= SYS_MFP_P30_RXD | SYS_MFP_P31_TXD;

  60.     /* Disable the P1.0 - P1.3 digital input path to avoid the leakage current */
  61.     GPIO_DISABLE_DIGITAL_PATH(P1, 0xF);

  62.     /* Configure the P1.0 - P1.3 ADC analog input pins */
  63.     SYS->P1_MFP &= ~(SYS_MFP_P10_Msk | SYS_MFP_P11_Msk | SYS_MFP_P12_Msk | SYS_MFP_P13_Msk);
  64.     SYS->P1_MFP |= SYS_MFP_P10_AIN0 | SYS_MFP_P11_AIN1 | SYS_MFP_P12_AIN2 | SYS_MFP_P13_AIN3 ;

  65. }

  66. /*---------------------------------------------------------------------------------------------------------*/
  67. /* Init UART                                                                                               */
  68. /*---------------------------------------------------------------------------------------------------------*/
  69. void UART0_Init()
  70. {
  71.     /* Reset IP */
  72.     SYS_ResetModule(UART0_RST);

  73.     /* Configure UART0 and set UART0 Baudrate */
  74.     UART_Open(UART0, 115200);
  75. }

  76. /*---------------------------------------------------------------------------------------------------------*/
  77. /* ADC interrupt handler                                                                                   */
  78. /*---------------------------------------------------------------------------------------------------------*/
  79. void ADC_IRQHandler(void)
  80. {
  81.     uint32_t u32Flag;

  82.     /* Get ADC conversion finish interrupt flag */
  83.     u32Flag = ADC_GET_INT_FLAG(ADC, ADC_ADF_INT);

  84.     /* Check ADC conversion finish */
  85.     if(u32Flag & ADC_ADF_INT)
  86.         g_u8ADF = 1;

  87.     /* Clear conversion finish flag */
  88.     ADC_CLR_INT_FLAG(ADC, u32Flag);
  89. }

  90. /*---------------------------------------------------------------------------------------------------------*/
  91. /* Function: GetAVDDVoltage                                                                                */
  92. /*                                                                                                         */
  93. /* Parameters:                                                                                             */
  94. /*   None.                                                                                                 */
  95. /*                                                                                                         */
  96. /* Returns:                                                                                                */
  97. /*   AVDD voltage(mV).                                                                                     */
  98. /*                                                                                                         */
  99. /* Description:                                                                                            */
  100. /*   Use Band-gap voltage to calculate AVDD voltage                                                        */
  101. /*---------------------------------------------------------------------------------------------------------*/
  102. uint32_t GetAVDDVoltage(void)
  103. {
  104.     uint32_t  u32ConversionResult;
  105.     uint64_t u64MvAVDD;

  106.     /* Calculate Vref by using conversion result of VBG */
  107.     u32ConversionResult = GetAVDDCodeByADC();

  108.     /* u32ConversionResult = VBG * 4096 / Vref, Vref = AVDD */
  109.     /* => AVDD = VBG * 4096 / u32ConversionResult */
  110.     u64MvAVDD = (VBG_VOLTAGE << 12) / (uint64_t)u32ConversionResult;

  111.     printf("Conversion result: 0x%X\n", u32ConversionResult);

  112.     return (uint32_t)u64MvAVDD;
  113. }

  114. /*---------------------------------------------------------------------------------------------------------*/
  115. /* Function: GetAVDDCodeByADC                                                                              */
  116. /*                                                                                                         */
  117. /* Parameters:                                                                                             */
  118. /*   None.                                                                                                 */
  119. /*                                                                                                         */
  120. /* Returns:                                                                                                */
  121. /*   ADC code of AVDD voltage.                                                                             */
  122. /*                                                                                                         */
  123. /* Description:                                                                                            */
  124. /*   Get ADC conversion result of Band-gap voltage.                                                        */
  125. /*---------------------------------------------------------------------------------------------------------*/
  126. uint32_t GetAVDDCodeByADC(void)
  127. {
  128.     uint32_t u32Count, u32Sum, u32Data;

  129.     /* Power on ADC */
  130.     ADC_POWER_ON(ADC);

  131.     /* Configure ADC: single-end input, single scan mode, enable ADC analog circuit. */
  132.     ADC_Open(ADC, ADC_ADCR_DIFFEN_SINGLE_END, ADC_ADCR_ADMD_SINGLE, BIT7);
  133.     /* Configure the analog input source of channel 7 as internal band-gap voltage */
  134.     ADC_CONFIG_CH7(ADC, ADC_ADCHER_PRESEL_INT_BANDGAP);

  135.     /* Clear conversion finish flag */
  136.     ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT);

  137.     /* Enable ADC conversion finish interrupt */
  138.     ADC_EnableInt(ADC, ADC_ADF_INT);
  139.     NVIC_EnableIRQ(ADC_IRQn);

  140.     g_u8ADF = 0;
  141.     u32Sum = 0;

  142.     /* sample times are according to ADC_SAMPLE_COUNT definition */
  143.     for(u32Count = 0; u32Count < ADC_SAMPLE_COUNT; u32Count++)
  144.     {
  145.         /* Delay for band-gap voltage stability */
  146.         CLK_SysTickDelay(100);

  147.         /* Start A/D conversion */
  148.         ADC_START_CONV(ADC);

  149.         u32Data = 0;
  150.         /* Wait conversion done */
  151.         while(g_u8ADF == 0);
  152.         g_u8ADF = 0;
  153.         /* Get the conversion result */
  154.         u32Data = ADC_GET_CONVERSION_DATA(ADC, 7);
  155.         /* Sum each conversion data */
  156.         u32Sum += u32Data;
  157.     }
  158.     /* Disable ADC interrupt */
  159.     ADC_DisableInt(ADC, ADC_ADF_INT);
  160.     /* Disable ADC */
  161.     ADC_POWER_DOWN(ADC);

  162.     /* Return the average of ADC_SAMPLE_COUNT samples */
  163.     return (u32Sum >> 7);
  164. }

  165. /*---------------------------------------------------------------------------------------------------------*/
  166. /* MAIN function                                                                                           */
  167. /*---------------------------------------------------------------------------------------------------------*/

  168. int main(void)
  169. {
  170.     uint32_t u32AVDDVoltage;

  171.     /* Unlock protected registers */
  172.     SYS_UnlockReg();

  173.     /* Init System, IP clock and multi-function I/O */
  174.     SYS_Init();

  175.     /* Lock protected registers */
  176.     SYS_LockReg();

  177.     /* Init UART0 for printf */
  178.     UART0_Init();

  179.     /*---------------------------------------------------------------------------------------------------------*/
  180.     /* SAMPLE CODE                                                                                             */
  181.     /*---------------------------------------------------------------------------------------------------------*/

  182.     printf("\nSystem clock rate: %d Hz\n", SystemCoreClock);
  183.     printf("+----------------------------------------------------------------------+\n");
  184.     printf("|                 ADC for AVDD Measurement sample code                 |\n");
  185.     printf("+----------------------------------------------------------------------+\n");

  186.     printf("\nIn this sample code, software will get voltage value from AVDD.\n");
  187.     printf("Notice that the Vref of ADC is from AVDD.\n\n");

  188.     /*------------------------------------------------------------------------------------------------------------------
  189.        The method of measured AVDD voltage is using ADC to get conversion result of band-gap voltage.

  190.        For example, the typical value of band-gap voltage is 1.20 V, and Vref of ADC is from AVDD.
  191.        Through getting ADC conversion result of band-gap voltage, then AVDD voltage can be calculated by below formula:

  192.            ConversionResult = VBG * 4096 / Vref, Vref = AVDD and VBG = 1.20V
  193.            => AVDD = 1.20V * 4096 / ConversionResult


  194.        Note 1 : The measured AVDD has deviation that causes by the band-gap voltage has deviation in different temperature, power voltage and ADC conversion deviation.(4 LSB)
  195.                 The deviation of measured AVDD is list as follows:

  196.                 The Spec. of band-gap voltage in M058S is as follows:
  197.                 -----------------------------------------------------------------------------------------
  198.                 |                  | Min.   | Typ.   | Max.   |                                         |
  199.                 |                  |--------------------------- VDD = 2.5 V ~ 5.5 V                     |
  200.                 | band-gap voltage | 1.14 V | 1.20 V | 1.26 V | temperature = -40 ~ 85 degrees Celsius  |
  201.                 |                  |        |        |        |                                         |
  202.                 -----------------------------------------------------------------------------------------

  203.                 Deviation range of measured AVDD
  204.                 ----------------------------------------------------
  205.                 |                | Min. Deviation | Max. Deviation |
  206.                 |                |                |                |
  207.                 |                | VBG = 1.14 V   | VBG = 1.26 V   |
  208.                 |--------------------------------------------------|
  209.                 |  AVDD = 2.5 V  |   -5.71%       |    5.80%       |
  210.                 |--------------------------------------------------|
  211.                 |  AVDD = 5.5 V  |   -6.56%       |    6.79%       |
  212.                 ----------------------------------------------------


  213.        Note 2: In this sample code is using the typical value of M058S series: 1.20 V, and it can be modified by VBG_VOLTAGE definition.

  214.     ------------------------------------------------------------------------------------------------------------------*/
  215.     /* Measure AVDD */
  216.     u32AVDDVoltage = GetAVDDVoltage();
  217.     printf("AVDD Voltage: %dmV\n", u32AVDDVoltage);

  218.     /* Disable ADC module */
  219.     ADC_Close(ADC);

  220.     /* Disable ADC IP clock */
  221.     CLK_DisableModuleClock(ADC_MODULE);

  222.     /* Disable External Interrupt */
  223.     NVIC_DisableIRQ(ADC_IRQn);

  224.     printf("\nExit ADC sample code\n");

  225.     while(1);

  226. }



 楼主| zhuotuzi 发表于 2025-1-24 16:36 | 显示全部楼层
首先知道内部参考电压,然后根据内部参考电压评估外部供电电压。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

214

主题

3368

帖子

7

粉丝
快速回复 在线客服 返回列表 返回顶部