搜索

[DemoCode下载] 通过Bandgap测量VDDD的方法

[复制链接]
227|13
 楼主 | 2020-6-20 22:07 | 显示全部楼层 |阅读模式
  1. /*---------------------------------------------------------------------------------------------------------*/
  2. /*                                                                                                         */
  3. /* Copyright(c) 2016 Nuvoton Technology Corp. All rights reserved.                                         */
  4. /*                                                                                                         */
  5. /*---------------------------------------------------------------------------------------------------------*/

  6. //***********************************************************************************************************
  7. //  Nuvoton Technoledge Corp.
  8. //  Website: http://www.nuvoton.com
  9. //  E-Mail : MicroC-8bit@nuvoton.com
  10. //  Date   : Apr/21/2016
  11. //***********************************************************************************************************

  12. //***********************************************************************************************************
  13. //  File Function: N76E885 ADC demo code
  14. //***********************************************************************************************************

  15. #include "N76E003.h"
  16. #include "SFR_Macro.h"
  17. #include "Function_define.h"
  18. #include "Common.h"
  19. #include "Delay.h"

  20. //*****************  The Following is in define in Fucntion_define.h  ***************************
  21. //****** Always include Function_define.h call the define you want, detail see main(void) *******
  22. //***********************************************************************************************
  23. #if 0
  24. //#define Enable_ADC_BandGap        ADCCON0|=SET_BIT3;ADCCON0&=0xF8;                                                                                                                                                                                                                                                        //Band-gap 1.22V
  25. #endif

  26. double  Bandgap_Voltage,VDD_Voltage;                        //please always use "double" mode for this
  27. unsigned  char xdata ADCdataH[5], ADCdataL[5];
  28. int ADCsumH=0, ADCsumL=0;
  29. unsigned char ADCavgH,ADCavgL;

  30. void READ_BANDGAP()
  31. {
  32.                 UINT8 BandgapHigh,BandgapLow,BandgapMark;
  33.                 double Bandgap_Value,Bandgap_Voltage_Temp;
  34.        
  35.                 set_IAPEN;
  36.                 IAPCN = READ_UID;
  37.                 IAPAL = 0x0d;
  38.     IAPAH = 0x00;
  39.     set_IAPGO;
  40.                 BandgapLow = IAPFD;
  41.                 BandgapMark = BandgapLow&0xF0;
  42.                        
  43.                 if (BandgapMark==0x80)
  44.                 {
  45.                                 BandgapLow = BandgapLow&0x0F;
  46.                                 IAPAL = 0x0C;
  47.                                 IAPAH = 0x00;
  48.                                 set_IAPGO;
  49.                                 BandgapHigh = IAPFD;
  50.                                 Bandgap_Value = (BandgapHigh<<4)+BandgapLow;
  51.                                 Bandgap_Voltage_Temp = Bandgap_Value*3/4;
  52.                                 Bandgap_Voltage = Bandgap_Voltage_Temp - 33;                        //the actually banggap voltage value is similar this value.
  53.                 }
  54.                 if (BandgapMark==0x00)
  55.                 {
  56.                                 BandgapLow = BandgapLow&0x0F;
  57.                                 IAPAL = 0x0C;
  58.                                 IAPAH = 0x00;
  59.                                 set_IAPGO;
  60.                                 BandgapHigh = IAPFD;
  61.                                 Bandgap_Value = (BandgapHigh<<4)+BandgapLow;
  62.                                 Bandgap_Voltage= Bandgap_Value*3/4;
  63.                 }
  64.                 if (BandgapMark==0x90)
  65.                 {
  66.                                 IAPAL = 0x0E;
  67.                                 IAPAH = 0x00;
  68.                                 set_IAPGO;
  69.                                 BandgapHigh = IAPFD;
  70.                                 IAPAL = 0x0F;
  71.                                 IAPAH = 0x00;
  72.                                 set_IAPGO;
  73.                                 BandgapLow = IAPFD;
  74.                                 BandgapLow = BandgapLow&0x0F;
  75.                                 Bandgap_Value = (BandgapHigh<<4)+BandgapLow;
  76.                                 Bandgap_Voltage= Bandgap_Value*3/4;
  77.                 }
  78.                 clr_IAPEN;
  79. //                        printf ("\n BG High = %bX",BandgapHigh);
  80. //                        printf ("\n BG Low = %bX",BandgapLow);
  81. //                        printf ("\n BG ROMMAP = %e",Bandgap_Voltage);
  82. }
  83.                
  84.                
  85. /******************************************************************************
  86. The main C function.  Program execution starts
  87. here after stack initialization.
  88. ******************************************************************************/
  89. void main (void)
  90. {
  91.                 double bgvalue;
  92.                 unsigned int i;
  93.        
  94.                 InitialUART0_Timer1(115200);
  95.                 READ_BANDGAP();
  96.                 printf ("\n BG ROMMAP = %e",Bandgap_Voltage);
  97.        
  98.                 while (1)
  99.                 {
  100.                                 Enable_ADC_BandGap;                                                                                               
  101.                                 CKDIV = 0x02;                                                                                                                        // IMPORTANT!! Modify system clock to 4MHz ,then add the ADC sampling clock base to add the sampling timing.
  102.                                 for(i=0;i<5;i++)                                                                                                        // All following ADC detect timing is 200uS run under 4MHz.
  103.                                 {
  104.                                                 clr_ADCF;
  105.                                                 set_ADCS;                                                                                                                               
  106.                                                 while(ADCF == 0);
  107.                                                 ADCdataH[i] = ADCRH;
  108.                                                 ADCdataL[i] = ADCRL;
  109.                                 }               
  110.                                 CKDIV = 0x00;                                                                                                                        // After ADC sampling, modify system clock back to 16MHz to run next code.
  111.                                 Disable_ADC;
  112.                                 for(i=2;i<5;i++)                                                                                                        // use the last 3 times data to make average
  113.                                 {
  114.                                         ADCsumH = ADCsumH + ADCdataH[i];
  115.                                         ADCsumL = ADCsumL + ADCdataL[i];
  116.                                 }                               
  117.                                 ADCavgH = ADCsumH/3;
  118.                                 ADCavgL = ADCsumL/3;
  119.                                 bgvalue = (ADCavgH<<4) + ADCavgL;
  120.                                 VDD_Voltage = (0x1000/bgvalue)*Bandgap_Voltage;
  121.                                 printf ("\n VDD voltage = %e", VDD_Voltage);
  122.                                 Timer0_Delay1ms(500);
  123.                                 ADCsumH = 0;
  124.                                 ADCsumL = 0;
  125.                 }
  126. }


复制代码


使用特权

评论回复
 楼主 | 2020-6-20 22:08 | 显示全部楼层
新唐很多单片机都具备这个功能,太神奇,太好用了。

使用特权

评论回复
 楼主 | 2020-6-20 22:08 | 显示全部楼层
你觉得呢?

使用特权

评论回复
 楼主 | 2020-6-20 22:09 | 显示全部楼层
例如MS51

  1. /*---------------------------------------------------------------------------------------------------------*/
  2. /*                                                                                                         */
  3. /* Copyright(c) 2019 Nuvoton Technology Corp. All rights reserved.                                         */
  4. /*                                                                                                         */
  5. /*---------------------------------------------------------------------------------------------------------*/

  6. /***********************************************************************************************************/
  7. /*  Website: http://www.nuvoton.com                                                                        */
  8. /*  E-Mail : MicroC-8bit@nuvoton.com                                                                       */
  9. /*  Date   : Jan/21/2019                                                                                   */
  10. /***********************************************************************************************************/

  11. //**********************************************************************************************************/
  12. //  File Function: MS51 ADC read bandgap to VDD demo code                                                  */
  13. //**********************************************************************************************************/

  14. #include "MS51_16K.H"

  15. //*****************  The Following is in define in Fucntion_define.h  ***************************
  16. //****** Always include Function_define.h call the define you want, detail see main(void) *******
  17. //***********************************************************************************************
  18. double  Bandgap_Voltage,VDD_Voltage,Bandgap_Value;      //please always use "double" mode for this
  19. unsigned  char xdata ADCdataH[5], ADCdataL[5];
  20. int ADCsumH=0, ADCsumL=0;
  21. unsigned char ADCavgH,ADCavgL;

  22. void READ_BANDGAP()
  23. {
  24.     UINT8 BandgapHigh,BandgapLow,BandgapMark;
  25.   
  26.     set_CHPCON_IAPEN;
  27.     IAPCN = READ_UID;
  28.     IAPAL = 0x0d;
  29.     IAPAH = 0x00;
  30.     set_IAPTRG_IAPGO;
  31.     BandgapLow = IAPFD;
  32.     BandgapMark = BandgapLow&0xF0;
  33.     BandgapLow = BandgapLow&0x0F;
  34.     IAPAL = 0x0C;
  35.     IAPAH = 0x00;
  36.     set_IAPTRG_IAPGO;
  37.     BandgapHigh = IAPFD;
  38.     Bandgap_Value = (BandgapHigh<<4)+BandgapLow;
  39.     Bandgap_Voltage= Bandgap_Value*3/4;
  40.     clr_CHPCON_IAPEN;
  41. }

  42. /******************************************************************************
  43. The main C function.  Program execution starts
  44. here after stack initialization.
  45. ******************************************************************************/
  46. void main (void)
  47. {
  48.     double bgvalue;
  49.     unsigned int i;

  50. /*Read bandgap value */
  51.     READ_BANDGAP();
  52. /* ADC Low speed initial*/  
  53.     ENABLE_ADC_BANDGAP;
  54.     ADCCON1|=0x30;            /* clock divider */
  55.     ADCCON2|=0x0E;            /* AQT time */
  56.     AUXR1|=SET_BIT4;          /* ADC clock low speed */
  57. /*start bandgap ADC */
  58.     clr_ADCCON0_ADCF;
  59.     set_ADCCON0_ADCS;                                
  60.     while(ADCF == 0);
  61.     ADCdataH[i] = ADCRH;
  62.     ADCdataL[i] = ADCRL;
  63. /* to convert VDD value */
  64.     bgvalue = (ADCRH<<4) + ADCRL;
  65.     VDD_Voltage = (0x1000/bgvalue)*Bandgap_Voltage;

  66. /* UART0 settting for printf function */
  67.     MODIFY_HIRC(HIRC_24);
  68.     P06_QUASI_MODE;
  69.     UART_Open(24000000,UART0_Timer3,115200);
  70.     ENABLE_UART0_PRINTF;
  71. /*printf result value */
  72.     printf ("\n BG Voltage = %e", Bandgap_Voltage);
  73.     printf ("\n VDD voltage = %e", VDD_Voltage);
  74.     while(1);

  75. }


复制代码

使用特权

评论回复
 楼主 | 2020-6-20 22:10 | 显示全部楼层
例如M051
  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/21 1:35p $
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]    Measure AVDD voltage by ADC.
  7. *
  8. * @note
  9. * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
  10. *
  11. ******************************************************************************/
  12. #include <stdio.h>
  13. #include "M051Series.h"

  14. #define PLL_CLOCK       50000000

  15. #define VBG_VOLTAGE (1250) /* 1.25V = 1250 mV (Typical band-gap voltage of M051XxDE series) */
  16. //#define VBG_VOLTAGE (1200) /* 1.20V = 1200 mV (Typical band-gap voltage of M051XxDN series) */
  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 external XTAL 12MHz clock */
  43.     CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);

  44.     /* Waiting for external XTAL clock ready */
  45.     CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);

  46.     /* Set core clock as PLL_CLOCK from PLL */
  47.     CLK_SetCoreClock(PLL_CLOCK);

  48.     /* Enable UART module clock */
  49.     CLK_EnableModuleClock(UART0_MODULE);

  50.     /* Enable ADC module clock */
  51.     CLK_EnableModuleClock(ADC_MODULE);

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

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

  56.     /*---------------------------------------------------------------------------------------------------------*/
  57.     /* Init I/O Multi-function                                                                                 */
  58.     /*---------------------------------------------------------------------------------------------------------*/
  59.     /* Set P3 multi-function pins for UART0 RXD and TXD */
  60.     SYS->P3_MFP &= ~(SYS_MFP_P30_Msk | SYS_MFP_P31_Msk);
  61.     SYS->P3_MFP |= SYS_MFP_P30_RXD0 | SYS_MFP_P31_TXD0;
  62. }

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

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

  73. /*---------------------------------------------------------------------------------------------------------*/
  74. /* ADC interrupt handler                                                                                   */
  75. /*---------------------------------------------------------------------------------------------------------*/
  76. void ADC_IRQHandler(void)
  77. {
  78.     uint32_t u32Flag;

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

  81.     /* Check ADC conversion finish */
  82.     if(u32Flag & ADC_ADF_INT)
  83.         g_u8ADF = 1;

  84.     /* Clear conversion finish flag */
  85.     ADC_CLR_INT_FLAG(ADC, u32Flag);
  86. }

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

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

  105.     /* u32ConversionResult = VBG * 4096 / Vref, Vref = AVDD */
  106.     /* => AVDD = VBG * 4096 / u32ConversionResult */
  107.     u64MvAVDD = (VBG_VOLTAGE << 12) / (uint64_t)u32ConversionResult;

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

  109.     return (uint32_t)u64MvAVDD;
  110. }

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

  126.     /* Power on ADC */
  127.     ADC_POWER_ON(ADC);

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

  132.     /* Clear conversion finish flag */
  133.     ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT);

  134.     /* Enable ADC conversion finish interrupt */
  135.     ADC_EnableInt(ADC, ADC_ADF_INT);
  136.     NVIC_EnableIRQ(ADC_IRQn);

  137.     g_u8ADF = 0;
  138.     u32Sum = 0;

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

  144.         /* Start A/D conversion */
  145.         ADC_START_CONV(ADC);

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

  159.     /* Return the average of ADC_SAMPLE_COUNT samples */
  160.     return (u32Sum >> 7);
  161. }

  162. /*---------------------------------------------------------------------------------------------------------*/
  163. /* MAIN function                                                                                           */
  164. /*---------------------------------------------------------------------------------------------------------*/

  165. int main(void)
  166. {
  167.     uint32_t u32AVDDVoltage;

  168.     /* Unlock protected registers */
  169.     SYS_UnlockReg();

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

  172.     /* Lock protected registers */
  173.     SYS_LockReg();

  174.     /* Init UART0 for printf */
  175.     UART0_Init();

  176.     /*---------------------------------------------------------------------------------------------------------*/
  177.     /* SAMPLE CODE                                                                                             */
  178.     /*---------------------------------------------------------------------------------------------------------*/
  179.     printf("\nSystem clock rate: %d Hz\n", SystemCoreClock);
  180.     printf("+----------------------------------------------------------------------+\n");
  181.     printf("|                 ADC for AVDD Measurement sample code                 |\n");
  182.     printf("+----------------------------------------------------------------------+\n");

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

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

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

  188.            ConversionResult = VBG * 4096 / Vref, Vref = AVDD and VBG = 1.25V
  189.            => AVDD = 1.25V * 4096 / ConversionResult


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

  192.                 (1) M051XxDN series:
  193.                     The Spec. of band-gap voltage in M051XxDN is as follows:
  194.                     -----------------------------------------------------------------------------------------
  195.                     |                  | Min.   | Typ.   | Max.   |                                         |
  196.                     |                  |--------------------------- VDD = 2.5 V ~ 5.5 V                     |
  197.                     | band-gap voltage | 1.14 V | 1.20 V | 1.26 V | temperature = -40 ~ 105 degrees Celsius |
  198.                     |                  |        |        |        |                                         |
  199.                     -----------------------------------------------------------------------------------------

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

  210.                 (2) M051XxDE series:
  211.                     The Spec. of band-gap voltage in M051XxDE is as follows:
  212.                     -----------------------------------------------------------------------------------------
  213.                     |                  | Min.   | Typ.   | Max.   |                                         |
  214.                     |                  |--------------------------- VDD = 2.5 V ~ 5.5 V                     |
  215.                     | band-gap voltage | 1.18 V | 1.25 V | 1.32 V | temperature = -40 ~ 105 degrees Celsius |
  216.                     |                  |        |        |        |                                         |
  217.                     -----------------------------------------------------------------------------------------

  218.                     Deviation range of measured AVDD
  219.                     ----------------------------------------------------
  220.                     |                | Min. Deviation | Max. Deviation |
  221.                     |                |                |                |
  222.                     |                | VBG = 1.18 V   | VBG = 1.32 V   |
  223.                     |--------------------------------------------------|
  224.                     |  AVDD = 2.5 V  |   -6.28%       |    6.37%       |
  225.                     |--------------------------------------------------|
  226.                     |  AVDD = 5.5 V  |   -7.09%       |    7.32%       |
  227.                     ----------------------------------------------------

  228.        Note 2: The typical value of band-gap voltage in M051XxDN series is 1.20V, and it is 1.25V in M051XxDE series.
  229.                In this sample code is using the typical value of M051XxDE series: 1.25 V, and it can be modified by VBG_VOLTAGE definition.

  230.     ------------------------------------------------------------------------------------------------------------------*/
  231.     /* Measure AVDD */
  232.     u32AVDDVoltage = GetAVDDVoltage();
  233.     printf("AVDD Voltage: %dmV\n", u32AVDDVoltage);

  234.     /* Disable ADC module */
  235.     ADC_Close(ADC);

  236.     /* Disable ADC IP clock */
  237.     CLK_DisableModuleClock(ADC_MODULE);

  238.     /* Disable External Interrupt */
  239.     NVIC_DisableIRQ(ADC_IRQn);

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

  241.     while(1);

  242. }

复制代码

使用特权

评论回复
 楼主 | 2020-6-20 22:10 | 显示全部楼层
例如M031
  1. /**************************************************************************//**
  2. * @file     main.c
  3. * @version  V3.00
  4. * @brief    Demonstrate how to calculate battery voltage( AVdd ) by using band-gap.
  5. *
  6. * [url=home.php?mod=space&uid=17282]@CopyRight[/url] (C) 2018 Nuvoton Technology Corp. All rights reserved.
  7. *
  8. ******************************************************************************/
  9. #include <stdio.h>
  10. #include "NuMicro.h"


  11. /*---------------------------------------------------------------------------------------------------------*/
  12. /* Define global variables and constants                                                                   */
  13. /*---------------------------------------------------------------------------------------------------------*/
  14. volatile uint32_t g_u32AdcIntFlag;
  15. volatile uint32_t g_u32BandGapConvValue;

  16. /**
  17.   * @brief      Read Built-in Band-Gap conversion value
  18.   * @param[in]  None
  19.   * [url=home.php?mod=space&uid=266161]@return[/url]     Built-in Band-Gap conversion value
  20.   * [url=home.php?mod=space&uid=1543424]@Details[/url]    This function is used to read Band-Gap conversion value.
  21.   */
  22. __STATIC_INLINE uint32_t FMC_ReadBandGap(void)
  23. {
  24.     FMC->ISPCMD = FMC_ISPCMD_READ_UID;            /* Set ISP Command Code */
  25.     FMC->ISPADDR = 0x70u;                         /* Must keep 0x70 when read Band-Gap */
  26.     FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;           /* Trigger to start ISP procedure */
  27. #if ISBEN
  28.     __ISB();
  29. #endif                                            /* To make sure ISP/CPU be Synchronized */
  30.     while(FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) {}  /* Waiting for ISP Done */

  31.     return FMC->ISPDAT & 0xFFF;
  32. }

  33. void SYS_Init(void)
  34. {
  35.     /* Unlock protected registers */
  36.     SYS_UnlockReg();

  37.     /* Enable HIRC clock (Internal RC 48 MHz) */
  38.     CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);

  39.     /* Wait for HIRC clock ready */
  40.     CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);

  41.     /* Select HCLK clock source as HIRC and HCLK source divider as 1 */
  42.     CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1));

  43.     /* Enable module clock */
  44.     CLK_EnableModuleClock(UART0_MODULE);
  45.     CLK_EnableModuleClock(ADC_MODULE);

  46.     /* Switch UART0 clock source to HIRC */
  47.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));
  48.     /* Switch ADC clock source to HIRC, set divider to 2, ADC clock is 48/2 MHz */
  49.     CLK_SetModuleClock(ADC_MODULE, CLK_CLKSEL2_ADCSEL_PCLK1, CLK_CLKDIV0_ADC(2));

  50.     /* Update System Core Clock */
  51.     /* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CycylesPerUs automatically. */
  52.     SystemCoreClockUpdate();

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

  56.     /* Set GPB multi-function pins for UART0 RXD and TXD */
  57.     SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk)) |
  58.                     (SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);

  59.     /* Lock protected registers */
  60.     SYS_LockReg();
  61. }

  62. void ADC_FunctionTest()
  63. {
  64.     int32_t  i32ConversionData;
  65.     int32_t  i32BuiltInData;

  66.     printf("\n");
  67.     printf("+----------------------------------------------------------------------------+\n");
  68.     printf("|     ADC for calculate battery voltage( AVdd ) by using band-gap test       |\n");
  69.     printf("+----------------------------------------------------------------------------+\n\n");

  70.     printf("+----------------------------------------------------------------------+\n");
  71.     printf("|   ADC clock source -> PCLK1  = 48 MHz                                |\n");
  72.     printf("|   ADC clock divider          = 2                                     |\n");
  73.     printf("|   ADC clock                  = 48 MHz / 2 = 24 MHz                   |\n");
  74.     printf("|   ADC extended sampling time = 71                                    |\n");
  75.     printf("|   ADC conversion time = 17 + ADC extended sampling time = 88         |\n");
  76.     printf("|   ADC conversion rate = 24 MHz / 88 = 272.7 ksps                     |\n");
  77.     printf("+----------------------------------------------------------------------+\n");

  78.     /* Enable ADC converter */
  79.     ADC_POWER_ON(ADC);

  80.     /* Set input mode as single-end, Single mode, and select channel 29 (band-gap voltage) */
  81.     ADC_Open(ADC, ADC_ADCR_DIFFEN_SINGLE_END, ADC_ADCR_ADMD_SINGLE, BIT29);

  82.     /* To sample band-gap precisely, the ADC capacitor must be charged at least 3 us for charging the ADC capacitor ( Cin )*/
  83.     /* Sampling time = extended sampling time + 1 */
  84.     /* 1/24000000 * (Sampling time) = 3 us */
  85.     ADC_SetExtendSampleTime(ADC, 0, 71);

  86.     /* Clear the A/D interrupt flag for safe */
  87.     ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT);

  88.     /* Enable the sample module interrupt.  */
  89.     ADC_ENABLE_INT(ADC, ADC_ADF_INT);   // Enable sample module A/D interrupt.
  90.     NVIC_EnableIRQ(ADC_IRQn);

  91.     printf(" Press any key to start the test\n\n");
  92.     getchar();

  93.     /* Reset the ADC interrupt indicator and trigger sample module to start A/D conversion */
  94.     g_u32AdcIntFlag = 0;
  95.     ADC_START_CONV(ADC);

  96.     /* Wait ADC conversion done */
  97.     while(g_u32AdcIntFlag == 0);

  98.     /* Disable the A/D interrupt */
  99.     ADC_DISABLE_INT(ADC, ADC_ADF_INT);

  100.     /* Get the conversion result of the channel 29 */
  101.     i32ConversionData = ADC_GET_CONVERSION_DATA(ADC, 29);


  102.     /* Enable FMC ISP function to read built-in band-gap A/D conversion result*/
  103.     SYS_UnlockReg();
  104.     FMC_Open();
  105.     i32BuiltInData = FMC_ReadBandGap();

  106.     /* Use Conversion result of Band-gap to calculating AVdd */

  107.     printf("      AVdd           i32BuiltInData                   \n");
  108.     printf("   ---------- = -------------------------             \n");
  109.     printf("      3072          i32ConversionData                 \n");
  110.     printf("                                                      \n");
  111.     printf("AVdd =  3072 * i32BuiltInData / i32ConversionData     \n\n");

  112.     printf("Built-in band-gap A/D conversion result: 0x%X (%d) \n", i32BuiltInData, i32BuiltInData);
  113.     printf("Conversion result of Band-gap:           0x%X (%d) \n\n", i32ConversionData, i32ConversionData);

  114.     printf("AVdd = 3072 * %d / %d = %d mV \n\n", i32BuiltInData, i32ConversionData, 3072*i32BuiltInData/i32ConversionData);
  115. }

  116. void ADC_IRQHandler(void)
  117. {
  118.     g_u32AdcIntFlag = 1;
  119.     ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT); /* Clear the A/D interrupt flag */
  120. }

  121. /*----------------------------------------------------------------------*/
  122. /* Init UART0                                                           */
  123. /*----------------------------------------------------------------------*/
  124. void UART0_Init(void)
  125. {
  126.     /* Reset UART0 */
  127.     SYS_ResetModule(UART0_RST);

  128.     /* Configure UART0 and set UART0 baud rate */
  129.     UART_Open(UART0, 115200);
  130. }

  131. int32_t main(void)
  132. {
  133.     /* Init System, IP clock and multi-function I/O. */
  134.     SYS_Init();

  135.     /* Init UART0 for printf */
  136.     UART0_Init();

  137.     printf("\nSystem clock rate: %d Hz", SystemCoreClock);

  138.     /* ADC function test */
  139.     ADC_FunctionTest();

  140.     /* Disable ADC IP clock */
  141.     CLK_DisableModuleClock(ADC_MODULE);

  142.     /* Disable External Interrupt */
  143.     NVIC_DisableIRQ(ADC_IRQn);

  144.     printf("Exit ADC sample code\n");

  145.     while(1);
  146. }
复制代码

使用特权

评论回复
 楼主 | 2020-6-20 22:11 | 显示全部楼层
例如M058S
  1. /****************************************************************************
  2. * @file     main.c
  3. * @version  V3.0
  4. * $Revision: 1 $
  5. * $Date: 16/06/29 4:40p $
  6. * @brief    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. }

复制代码

使用特权

评论回复
| 2020-6-20 22:15 | 显示全部楼层
总结的很不错,几个系列例子都有了。

使用特权

评论回复
| 2020-6-20 22:43 | 显示全部楼层
齐全了,参考非常方便。

使用特权

评论回复
| 2020-7-9 11:45 | 显示全部楼层
就喜欢这样的楼主。

使用特权

评论回复
| 2020-7-10 17:07 | 显示全部楼层
不错的方案啊

使用特权

评论回复
| 2020-7-10 17:07 | 显示全部楼层
非常感谢楼主分享

使用特权

评论回复
| 2020-7-14 20:56 | 显示全部楼层
是不错,就是代码量太大了,需要压缩。

使用特权

评论回复
| 2020-7-18 09:49 | 显示全部楼层
认真推算了一下,懂了。

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 我要提问 投诉建议 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

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