[应用相关] 通过ADC测量 AVDD电压

[复制链接]
 楼主| 天灵灵地灵灵 发表于 2017-6-25 17:38 | 显示全部楼层 |阅读模式
  1. /****************************************************************************
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V2.0
  4. * $Revision: 1 $
  5. * $Date: 16/06/22 10:09a $
  6. * @brief
  7. *           Measure AVDD voltage by ADC.
  8. *
  9. * @note
  10. * Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
  11. *
  12. ******************************************************************************/
  13. #include <stdio.h>
  14. #include "NUC123.h"


  15. #define PLL_CLOCK       72000000

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

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


  27. /*---------------------------------------------------------------------------------------------------------*/
  28. /* Define global variables and constants                                                                   */
  29. /*---------------------------------------------------------------------------------------------------------*/
  30. volatile uint8_t g_u8ADF;


  31. void SYS_Init(void)
  32. {
  33.     /*---------------------------------------------------------------------------------------------------------*/
  34.     /* Init System Clock                                                                                       */
  35.     /*---------------------------------------------------------------------------------------------------------*/

  36.     /* Enable Internal RC 22.1184MHz clock */
  37.     CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

  38.     /* Waiting for Internal RC clock ready */
  39.     CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);

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

  42.     /* Enable XT1_OUT(PF.0) and XT1_IN(PF.1) */
  43.     SYS->GPF_MFP |= SYS_GPF_MFP_PF0_XT1_OUT | SYS_GPF_MFP_PF1_XT1_IN;

  44.     /* Enable external XTAL 12MHz clock */
  45.     CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);

  46.     /* Waiting for external XTAL clock ready */
  47.     CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);

  48.     /* Set core clock as PLL_CLOCK from PLL */
  49.     CLK_SetCoreClock(PLL_CLOCK);

  50.     /* Enable UART module clock */
  51.     CLK_EnableModuleClock(UART0_MODULE);

  52.     /* Enable ADC module clock */
  53.     CLK_EnableModuleClock(ADC_MODULE);

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

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

  58.     /*---------------------------------------------------------------------------------------------------------*/
  59.     /* Init I/O Multi-function                                                                                 */
  60.     /*---------------------------------------------------------------------------------------------------------*/

  61.     /* Set GPB multi-function pins for UART0 RXD and TXD */
  62.     SYS->GPB_MFP &= ~(SYS_GPB_MFP_PB0_Msk | SYS_GPB_MFP_PB1_Msk);
  63.     SYS->GPB_MFP |= SYS_GPB_MFP_PB0_UART0_RXD | SYS_GPB_MFP_PB1_UART0_TXD;
  64. }

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

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

  75. /*---------------------------------------------------------------------------------------------------------*/
  76. /* Function: GetAVDDVoltage                                                                                */
  77. /*                                                                                                         */
  78. /* Parameters:                                                                                             */
  79. /*   None.                                                                                                 */
  80. /*                                                                                                         */
  81. /* Returns:                                                                                                */
  82. /*   AVDD voltage(mV).                                                                                     */
  83. /*                                                                                                         */
  84. /* Description:                                                                                            */
  85. /*   Use Band-gap voltage to calculate AVDD voltage                                                        */
  86. /*---------------------------------------------------------------------------------------------------------*/
  87. uint32_t GetAVDDVoltage(void)
  88. {
  89.     uint32_t  u32ConversionResult;
  90.     uint64_t u64MvAVDD;

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

  93.     /* u32ConversionResult = VBG * 1024 / Vref, Vref = AVDD */
  94.     /* => AVDD = VBG * 1024 / u32ConversionResult */
  95.     u64MvAVDD = (VBG_VOLTAGE << 10) / (uint64_t)u32ConversionResult;

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

  97.     return (uint32_t)u64MvAVDD;
  98. }

  99. /*---------------------------------------------------------------------------------------------------------*/
  100. /* Function: GetAVDDCodeByADC                                                                              */
  101. /*                                                                                                         */
  102. /* Parameters:                                                                                             */
  103. /*   None.                                                                                                 */
  104. /*                                                                                                         */
  105. /* Returns:                                                                                                */
  106. /*   ADC code of AVDD voltage.                                                                             */
  107. /*                                                                                                         */
  108. /* Description:                                                                                            */
  109. /*   Get ADC conversion result of Band-gap voltage.                                                        */
  110. /*---------------------------------------------------------------------------------------------------------*/
  111. uint32_t GetAVDDCodeByADC(void)
  112. {
  113.     uint32_t u32Count, u32Sum, u32Data;

  114.     /* Configure ADC: single-end input, single scan mode, enable ADC analog circuit. */
  115.     ADC_Open(ADC, NULL, ADC_ADCR_ADMD_SINGLE, BIT7);
  116.     /* Configure the analog input source of channel 7 as internal band-gap voltage */
  117.     ADC_CONFIG_CH7(ADC, ADC_ADCHER_PRESEL_INT_BANDGAP);

  118.     /* Power on ADC */
  119.     ADC_POWER_ON(ADC);

  120.     /* Clear conversion finish flag */
  121.     ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT);

  122.     /* Enable ADC conversion finish interrupt */
  123.     ADC_EnableInt(ADC, ADC_ADF_INT);
  124.     NVIC_EnableIRQ(ADC_IRQn);

  125.     g_u8ADF = 0;
  126.     u32Sum = 0;

  127.     /* sample times are according to ADC_SAMPLE_COUNT definition */
  128.     for(u32Count = 0; u32Count < ADC_SAMPLE_COUNT; u32Count++)
  129.     {
  130.         /* Delay for band-gap voltage stability */
  131.         CLK_SysTickDelay(100);

  132.         /* Start A/D conversion */
  133.         ADC_START_CONV(ADC);

  134.         u32Data = 0;
  135.         /* Wait conversion done */
  136.         while(g_u8ADF == 0);
  137.         g_u8ADF = 0;
  138.         /* Get the conversion result */
  139.         u32Data = ADC_GET_CONVERSION_DATA(ADC, 7);
  140.         /* Sum each conversion data */
  141.         u32Sum += u32Data;
  142.     }
  143.     /* Disable ADC interrupt */
  144.     ADC_DisableInt(ADC, ADC_ADF_INT);
  145.     /* Disable ADC */
  146.     ADC_POWER_DOWN(ADC);

  147.     /* Return the average of ADC_SAMPLE_COUNT samples */
  148.     return (u32Sum >> 7);
  149. }



  150. /*---------------------------------------------------------------------------------------------------------*/
  151. /* ADC interrupt handler                                                                                   */
  152. /*---------------------------------------------------------------------------------------------------------*/
  153. void ADC_IRQHandler(void)
  154. {
  155.     uint32_t u32Flag;

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

  158.     /* Check ADC conversion finish */
  159.     if(u32Flag & ADC_ADF_INT)
  160.         g_u8ADF = 1;

  161.     /* Clear conversion finish flag */
  162.     ADC_CLR_INT_FLAG(ADC, u32Flag);
  163. }

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

  167. main(void)
  168. {
  169.     uint32_t u32AVDDVoltage;

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

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

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

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

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

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

  185.     printf("\nIn this sample code, software will get voltage value from AVDD.\n");

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

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

  190.            ConversionResult = VBG * 1024 / Vref, Vref = AVDD and VBG = 1.20V
  191.            => AVDD = 1.20V * 1024 / ConversionResult


  192.        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)
  193.                 The deviation of measured AVDD is list as follows:

  194.                 The Spec. of band-gap voltage in NUC123 series is as follows:
  195.                 -----------------------------------------------------------------------------------------
  196.                 |                  | Min.   | Typ.   | Max.   |                                         |
  197.                 |                  |--------------------------- VDD = 2.5 V ~ 5.5 V                     |
  198.                 | band-gap voltage | 1.18 V | 1.20 V | 1.22 V | temperature = -40 ~ 110 degrees Celsius |
  199.                 |                  |        |        |        |                                         |
  200.                 -----------------------------------------------------------------------------------------

  201.                 Deviation range of measured AVDD
  202.                 ----------------------------------------------------
  203.                 |                | Min. Deviation | Max. Deviation |
  204.                 |                |                |                |
  205.                 |                | VBG = 1.18 V   | VBG = 1.22 V   |
  206.                 |--------------------------------------------------|
  207.                 |  AVDD = 2.5 V  |   -4.57%       |    4.86%       |
  208.                 |--------------------------------------------------|
  209.                 |  AVDD = 5.5 V  |   -7.85%       |    8.98%       |
  210.                 ----------------------------------------------------


  211.        Note 2: The typical value of band-gap voltage can be modified by VBG_VOLTAGE definition.

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

  216.     /* Disable ADC module */
  217.     ADC_Close(ADC);

  218.     /* Disable ADC IP clock */
  219.     CLK_DisableModuleClock(ADC_MODULE);

  220.     /* Disable External Interrupt */
  221.     NVIC_DisableIRQ(ADC_IRQn);

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

  223.     while(1);

  224. }




 楼主| 天灵灵地灵灵 发表于 2017-6-25 17:39 | 显示全部楼层
通过一个通道测量自身电压,作为自检程序,很不错的
aspoke 发表于 2017-6-25 21:26 | 显示全部楼层
怎么样保持基准电压?
232321122 发表于 2017-6-25 21:27 | 显示全部楼层
天灵灵地灵灵 发表于 2017-6-25 17:39
通过一个通道测量自身电压,作为自检程序,很不错的

这个的效果怎么样?
ghuca 发表于 2017-6-25 21:27 | 显示全部楼层
ADC采样数据准确。
xiaoyaozt 发表于 2017-6-25 21:28 | 显示全部楼层
这个的参考电源来自哪里?
soodesyt 发表于 2017-6-25 21:28 | 显示全部楼层
来个硬件电路参考一下。
plsbackup 发表于 2017-6-25 21:29 | 显示全部楼层
这个应该是配合硬件电路使用吧。
eefas 发表于 2017-6-25 21:30 | 显示全部楼层
使用外部的参考电压可以实现。
qiufengsd 发表于 2017-6-25 21:31 | 显示全部楼层
soodesyt 发表于 2017-6-25 21:28
来个硬件电路参考一下。

硬件电路使用开发板就可以。
jstgotodo 发表于 2017-6-25 21:31 | 显示全部楼层
ghuca 发表于 2017-6-25 21:27
ADC采样数据准确。

采样准确是12位ADC分辨率。
aspoke 发表于 2017-6-25 21:32 | 显示全部楼层
电压变化之后参考电压没有问题吗?
232321122 发表于 2017-6-25 21:32 | 显示全部楼层
天灵灵地灵灵 发表于 2017-6-25 17:39
通过一个通道测量自身电压,作为自检程序,很不错的

想实现一个低电压的保护电路。
ghuca 发表于 2017-6-25 21:32 | 显示全部楼层
ST的ADC是12位的ADC采样。
xiaoyaozt 发表于 2017-6-25 21:32 | 显示全部楼层
有维持基准电压的芯片吗?
soodesyt 发表于 2017-6-25 21:32 | 显示全部楼层
Measure AVDD voltage的ref电压呢?
plsbackup 发表于 2017-6-25 21:32 | 显示全部楼层
这个代码就是基本的ADC采样代码。
eefas 发表于 2017-6-25 21:32 | 显示全部楼层
锂电池可以稳定为3.3V电压。
qiufengsd 发表于 2017-6-25 21:32 | 显示全部楼层
soodesyt 发表于 2017-6-25 21:28
来个硬件电路参考一下。

现在的STM32都有评估板。
jstgotodo 发表于 2017-6-25 21:32 | 显示全部楼层
ghuca 发表于 2017-6-25 21:27
ADC采样数据准确。

还是外部的ADC更精确一些。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

182

主题

3469

帖子

13

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

182

主题

3469

帖子

13

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