[DemoCode下载] nano100如何使用内部BandGap 2.5V电压来测量芯片的内部温度和供电电压

[复制链接]
799|3
 楼主| xinxianshi 发表于 2024-2-25 20:19 | 显示全部楼层 |阅读模式
EC_Nano100_Use_BandGap_Measure_VDD_And_Temperature_V1.00.zip (4.98 MB, 下载次数: 5)
  1. /**************************************************************************//**
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
  4. * $Revision: 6 $
  5. * $Date: 14/05/08 4:24p $
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]    Demonstrate measure internal temperature and supply voltage of IC using internal BandGap 2.5V voltage.
  7. *
  8. * @note
  9. * Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
  10. *****************************************************************************/
  11. #include <stdio.h>
  12. #include "Nano100Series.h"

  13. volatile float fTmp = 0;
  14. volatile float fAvdd = 0;
  15. void ADC_IRQHandler(void);

  16. void ADC_IRQHandler(void)
  17. {
  18.     uint32_t u32Flag;

  19.     // Get ADC conversion finish interrupt flag
  20.     u32Flag = ADC_GET_INT_FLAG(ADC, ADC_ADF_INT);

  21.     if (u32Flag & ADC_ADF_INT)
  22.     {
  23.         uint32_t u32Result;
  24.         u32Result = ADC_GET_CONVERSION_DATA(ADC, 15);
  25.         fAvdd = 2.5 * 0xfff / u32Result;
  26.         printf(" Channel 15 conversion result is %d, VDD is %f volt \n", u32Result, fAvdd);
  27.         u32Result = ADC_GET_CONVERSION_DATA(ADC, 14);
  28.         fTmp = (740 - (1000 * u32Result / 4096) * fAvdd) / 1.73 ;
  29.         printf(" Channel 14 conversion result is %d, Temperature is %f degree \n", u32Result, fTmp);
  30.     }

  31.     ADC_CLR_INT_FLAG(ADC, u32Flag);
  32. }

  33. void SYS_EnableTempCtl()
  34. {
  35.     SYS->TEMPCTL  |= (SYS_TEMPCTL_VTEMP_EN_Msk);
  36. }

  37. void SYS_DisableTempCtl()
  38. {
  39.     SYS->TEMPCTL  = ((SYS->TEMPCTL & ~0x1));
  40. }

  41. void SYS_EnableIntVRefBGP(uint8_t iValue)
  42. {
  43.     if (iValue)
  44.         SYS->Int_VREFCTL   = ((SYS->Int_VREFCTL & ~0x7) | (SYS_VREFCTL_BGP_EN_Msk | SYS_VREFCTL_REG_EN_Msk | 0x4)); // BGP 2.5V
  45.     else
  46.         SYS->Int_VREFCTL  = ((SYS->Int_VREFCTL & ~0x7) | (SYS_VREFCTL_BGP_EN_Msk | SYS_VREFCTL_REG_EN_Msk)); // BGP 1.8V
  47. }

  48. void SYS_DisableIntRefBGP()
  49. {
  50.     SYS->Int_VREFCTL &= ~0x7 ;
  51. }

  52. void ADC_SetVrefVoltage(uint8_t iValue)
  53. {
  54.     ADC->CR &= ~ADC_CR_REFSEL_Msk;

  55.     if (iValue == 1) // Select Int_Vref as Voltage
  56.     {
  57.         ADC->CR |= (0x1 << ADC_CR_REFSEL_Pos);
  58.     }
  59.     else if (iValue == 2) // Select Vref as Voltage
  60.     {
  61.         ADC->CR |= (0x2 << ADC_CR_REFSEL_Pos);
  62.     }
  63.     else // default Select Power as Voltage
  64.     {
  65.     }
  66. }

  67. /*---------------------------------------------------------------------------------------------------------*/
  68. /* Init System Clock                                                                                       */
  69. /*---------------------------------------------------------------------------------------------------------*/
  70. void SYS_Init(void)
  71. {
  72.     /* Unlock protected registers */
  73.     SYS_UnlockReg();

  74.     /* Set HCLK source form HXT and HCLK source divide 1  */
  75.     CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HXT, CLK_HCLK_CLK_DIVIDER(1));

  76.     /* Enable external 12MHz HXT, 32KHz LXT and HIRC */
  77.     CLK_EnableXtalRC(CLK_PWRCTL_HXT_EN_Msk | CLK_PWRCTL_LXT_EN_Msk | CLK_PWRCTL_HIRC_EN_Msk);

  78.     /* Waiting for clock ready */
  79.     CLK_WaitClockReady(CLK_CLKSTATUS_HXT_STB_Msk | CLK_CLKSTATUS_LXT_STB_Msk | CLK_CLKSTATUS_HIRC_STB_Msk);

  80.     /*  Set HCLK frequency 42MHz */
  81.     CLK_SetCoreClock(32000000);

  82.     /* Enable IP clock */
  83.     CLK_EnableModuleClock(UART0_MODULE);

  84.     /* Enable ADC clock */
  85.     CLK_EnableModuleClock(ADC_MODULE);

  86.     /* Select IP clock source */
  87.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_UART_CLK_DIVIDER(1));
  88.     CLK_SetModuleClock(ADC_MODULE, CLK_CLKSEL1_ADC_S_HXT, CLK_ADC_CLK_DIVIDER(200));

  89.     /*---------------------------------------------------------------------------------------------------------*/
  90.     /* Init I/O Multi-function                                                                                 */
  91.     /*---------------------------------------------------------------------------------------------------------*/
  92.     /* Set PB multi-function pins for UART0 RXD and TXD */
  93.     SYS->PB_L_MFP &= ~(SYS_PB_L_MFP_PB0_MFP_Msk | SYS_PB_L_MFP_PB1_MFP_Msk);
  94.     SYS->PB_L_MFP |= (SYS_PB_L_MFP_PB0_MFP_UART0_RX | SYS_PB_L_MFP_PB1_MFP_UART0_TX);

  95.     /* Set PB multi-function pins for Clock Output */
  96.     SYS->PB_H_MFP = (SYS->PB_H_MFP & ~SYS_PB_H_MFP_PB12_MFP_Msk) |  SYS_PB_H_MFP_PB12_MFP_CKO;

  97.     /* Set PA.0 multi-function pin for ADC channel 0 */
  98.     SYS->PA_L_MFP = (SYS->PA_L_MFP & ~SYS_PA_L_MFP_PA0_MFP_Msk) | SYS_PA_L_MFP_PA0_MFP_ADC_CH0;

  99.     /* Disable PA.0 digital input path */
  100.     PA->OFFD |= ((1 << 0) << GP_OFFD_OFFD_Pos);

  101.     SYS_EnableTempCtl(); // Enable Temperature Sensor
  102.     SYS_EnableIntVRefBGP(1); // Enable Vref is BGP

  103.     /* Lock protected registers */
  104.     SYS_LockReg();
  105. }

  106. void UART0_Init()
  107. {
  108.     /*---------------------------------------------------------------------------------------------------------*/
  109.     /* Init UART                                                                                               */
  110.     /*---------------------------------------------------------------------------------------------------------*/
  111.     UART_Open(UART0, 115200);
  112. }

  113. int32_t main(void)
  114. {
  115.     //uint32_t u32Result;

  116.     /* Init System, IP clock and multi-function I/O
  117.        In the end of SYS_Init() will issue SYS_LockReg()
  118.        to lock protected register. If user want to write
  119.        protected register, please issue SYS_UnlockReg()
  120.        to unlock protected register if necessary */
  121.     SYS_Init();

  122.     /* Init UART0 for printf */
  123.     UART0_Init();

  124.     printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %dHz\n", SystemCoreClock);

  125.     printf("\n This sample code demonstrate measure VDD and Temperature.\n");
  126.     printf(" It convert ADC channel 14, 15 and print conversion result \n");
  127.     printf(" ADC channel 15 is VDD \n");
  128.     printf(" ADC channel 14 is Temperature \n\n");

  129.     // Set ADC
  130.     ADC_Open(ADC, ADC_INPUT_MODE_SINGLE_END, ADC_OPERATION_MODE_SINGLE_CYCLE, ADC_CH_14_MASK | ADC_CH_15_MASK);
  131.     ADC_SetExtraSampleTime(ADC, ADC_CH_14_MASK, 1024);

  132.     ADC_SetVrefVoltage(0); // Set Vref voltage

  133.     // Power on ADC
  134.     ADC_POWER_ON(ADC);

  135.     // Enable ADC ADC_IF interrupt
  136.     ADC_EnableInt(ADC, ADC_ADF_INT);
  137.     NVIC_EnableIRQ(ADC_IRQn);

  138.     ADC_START_CONV(ADC);

  139.     while (1);
  140. }

  141. /*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/




 楼主| xinxianshi 发表于 2024-2-25 20:21 | 显示全部楼层
这段代码是一个示例程序,用于演示如何使用内部BandGap 2.5V电压来测量芯片的内部温度和供电电压。下面是对代码的分析总结:

在代码开头的注释中,提供了文件名、版本信息、修订版本和日期等基本信息,以及简要的代码功能说明。

程序中使用了Nuvoton Nano100系列的头文件和相关函数。

定义了两个全局的浮点型变量 fTmp 和 fAvdd,用于存储温度和供电电压的测量结果。

实现了 ADC_IRQHandler 函数,用于处理 ADC 的中断事件。当 ADC 转换完成时,该函数会获取转换结果,并通过printf函数输出温度和供电电压的值。

定义了一些系统初始化函数,包括使能温度传感器、使能内部参考电压 BGP、设置 ADC 参考电压等。

实现了 SYS_Init 函数,用于初始化系统时钟、外设时钟和多功能IO。

实现了 UART0_Init 函数,用于初始化 UART0 模块,以便通过串口打印信息。

在主函数 main 中,首先调用 SYS_Init 进行系统初始化,然后调用 UART0_Init 初始化 UART0,接着通过printf函数打印CPU时钟频率信息和示例代码说明,然后配置 ADC,并使能 ADC 中断,并启动 ADC 转换。

最后是一个空的死循环,程序将在此处无限循环执行。

总的来说,这段代码通过内部ADC模块实现了对芯片内部温度和供电电压的测量,并通过串口输出结果。
 楼主| xinxianshi 发表于 2024-2-25 20:21 | 显示全部楼层
使用内部2.5V BandGap电压作为IC的内部参考电压。
启用内部ADC通道14,并启用温度检测寄存器来测量IC的内部温度。
计算函数如下所示:
Vtemp(mV) = 2.51000 (ADC_14/4096)
Vtemp (mV) = -1.73 (mV/℃) x Temperature (℃) + 740 (mV)。
使用ADC通道15测量供电电压。
计算函数如下所示:
VDD = (4096/ADC_15)*2.5V
jiekou001 发表于 2024-2-26 17:12 | 显示全部楼层
新唐的很多单片机系列貌似都提供了这个功能,可以省略一个外部的参靠电压源。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

102

主题

1163

帖子

1

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