[DemoCode下载] M051系列通过内部ADC通道测量内部温度

[复制链接]
2078|3
 楼主| 幸福小强 发表于 2021-7-10 17:34 | 显示全部楼层 |阅读模式
1.1 简介
微控制器广泛的应用在不同的环境温度下,Nuvoton NuMicro® Cortex®–M0 M051 系列内建温度传感器,此范例将说明如何使用ADC取得温度传感器的摄氏温度。
1.2 原理
ADC 将参考电压作为基准,将参考电压平均对应至数阶,阶数与ADC的解析度相关。在测量温度传感器电压前,必须先得知参考电压,才能将量测温度传感器的数值换算成电压。
515960e96978a3fe1.png

M051 ADC可量测Band-gap电压,Band-gap电压是固定电压,M051的Band-gap电压为1.2V,透过公式1-1 可算出ADC 参考电压。
1356860e9698e4fadb.png
M051内建的温度传感器为负温度系数传感器,参考图1-1,当温度越低,电压越高。其中Gain 为负温度系数,Offset则为误差调整。由公式1-3可将温度传感器的电压转换为摄氏温度。实际温度传感器参数与Band-gap电压规格请参考M051的相关文件。
2955660e969ad49bde.png

 楼主| 幸福小强 发表于 2021-7-10 17:36 | 显示全部楼层
EC_M051_Measure_Internal_Temperature_Sensor_V1.00 (1).zip (1.49 MB, 下载次数: 6)
  1. /**************************************************************************//**
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * @brief
  4. *           Use ADC measure internal temperature sensor.
  5. * @note
  6. * Copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
  7. *****************************************************************************/
  8. #include <stdio.h>
  9. #include "M051Series.h"

  10. #define PLL_CLOCK       ((uint32_t)50000000)  //PLL clock setting     ,Unit : Hz
  11. #define VBG             ((double)1.20)        //M051 Band-gap voltage ,Unit : Volt
  12. #define Offset          ((uint32_t)724)       //Temperature sensor curve formula offset
  13. #define Gain            ((double)-1.75)       //Temperature sensor curve formula gain

  14. /*---------------------------------------------------------------------------*/
  15. /* Global variables                                                          */
  16. /*---------------------------------------------------------------------------*/
  17. char ai8TemperatureUnit[] = "\u2103";         //Degree Celsies encode

  18. /*---------------------------------------------------------------------------*/
  19. /* Functions                                                                 */
  20. /*---------------------------------------------------------------------------*/
  21. void SYS_Init(void);
  22. void UART0_Init(void);
  23. void ADC_Example_InternalTemperature(void);

  24. /*---------------------------------------------------------------------------
  25.    Function:    SYS_Init
  26.    Parameters:  None.
  27.    Returns:     None.
  28.    Description: System and periphial module clock setting.
  29. ---------------------------------------------------------------------------*/
  30. void SYS_Init(void)
  31. {

  32.     /* Enable Internal RC 22.1184MHz clock */
  33.     CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

  34.     /* Waiting for Internal RC clock ready */
  35.     CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);

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

  38.     /* Enable external XTAL 12MHz clock */
  39.     CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);

  40.     /* Waiting for external XTAL clock ready */
  41.     CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);

  42.     /* Set core clock as PLL_CLOCK from PLL */
  43.     CLK_SetCoreClock(PLL_CLOCK);

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

  46.     /* Enable ADC module clock */
  47.     CLK_EnableModuleClock(ADC_MODULE);

  48.     /* Select UART module clock source */
  49.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));

  50.     /* ADC clock source is 22.1184MHz, set divider to 100, ADC clock is 22.1184/100 MHz */
  51.     CLK_SetModuleClock(ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_CLKDIV_ADC(100));

  52. }

  53. /*---------------------------------------------------------------------------
  54.    Function:    UART0_Init
  55.    Parameters:  None.
  56.    Returns:     None.
  57.    Description: Initialize UART0 module, setting buadrate is 115200 bps
  58. ---------------------------------------------------------------------------*/
  59. void UART0_Init(void)
  60. {
  61.     /* Reset IP */
  62.     SYS_ResetModule(UART0_RST);

  63.     /* Configure UART0 and set UART0 Baudrate */
  64.     UART_Open(UART0, 115200);
  65. }

  66. /*---------------------------------------------------------------------------
  67.    Function:    ADC_Example_InternalTemperature
  68.    Parameters:  None.
  69.    Returns:     None.
  70.    Description: Measure chip band-gap voltage through ADC, and estimate
  71.                 external reference voltage. Measure chip internal temperature,
  72.                 according to temperature sensor curve formula and comparison
  73.                 voltage of reference. Finally printf out the Celsius.
  74. ---------------------------------------------------------------------------*/
  75. void ADC_Example_InternalTemperature(void)
  76. {
  77.     int32_t  i32ConversionData;
  78.     double   dVref;
  79.     double   dTempData;

  80.     printf("+----------------------------------------------------------------------+\n");
  81.     printf("|               ADC for temperature sensor example code                |\n");
  82.     printf("+----------------------------------------------------------------------+\n");

  83.     printf("\nIn this example, software will get value from temperature sensor.\n");

  84.     /* Enable Temperature Sensor function */
  85.     SYS->TEMPCR |= SYS_TEMPCR_VTEMP_EN_Msk;

  86.     /* Set the ADC operation mode as continuous scan, input mode as single-end and
  87.     enable the analog input channel 7 */
  88.     ADC_Open(ADC, ADC_ADCR_DIFFEN_SINGLE_END, ADC_ADCR_ADMD_CONTINUOUS, BIT7);

  89.     /* Configure the analog input source of channel 7 */
  90.     ADC_CONFIG_CH7(ADC, ADC_ADCHER_PRESEL_INT_BANDGAP);

  91.     /* Power on ADC module */
  92.     ADC_POWER_ON(ADC);

  93.     /* clear the A/D interrupt flag for safe */
  94.     ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT);

  95.     /* start A/D conversion */
  96.     ADC_START_CONV(ADC);

  97.     while (1)
  98.     {
  99.         /* Wait conversion done */
  100.         while (!ADC_GET_INT_FLAG(ADC, ADC_ADF_INT));

  101.         /* Stop A/D conversion */
  102.         ADC_STOP_CONV(ADC);

  103.         /* clear the A/D interrupt flag for safe */
  104.         ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT);

  105.         /* Calculate dVref by using conversion result of VBG */
  106.         /* ConversionData = VBG * 4096 / Vref */
  107.         i32ConversionData = ADC_GET_CONVERSION_DATA(ADC, 7);
  108.         dVref = VBG * 4096 / (double)i32ConversionData;

  109.         /* Delay */
  110.         CLK_SysTickDelay(500000);

  111.         /* Configure the analog input source of channel 7 */
  112.         ADC_CONFIG_CH7(ADC, ADC_ADCHER_PRESEL_INT_TEMPERATURE_SENSOR);

  113.         /* start A/D conversion */
  114.         ADC_START_CONV(ADC);

  115.         /* Wait conversion done */
  116.         while (!ADC_GET_INT_FLAG(ADC, ADC_ADF_INT));

  117.         /* Stop A/D conversion */
  118.         ADC_STOP_CONV(ADC);

  119.         /* clear the A/D interrupt flag for safe */
  120.         ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT);

  121.         /* Calculate value from temperature sensor  */
  122.         /* ConversionData = Vtemp(V) * 4096 / dVref */
  123.         /* Vtemp(mV) = Gain * Temperature + Offset  */
  124.         i32ConversionData = ADC_GET_CONVERSION_DATA(ADC, 7);
  125.         dTempData = (((double)i32ConversionData * dVref / 4096) * 1000 - Offset) / Gain;
  126.         printf("Conversion result of channel %d: 0x%X (%.2f %s)\n", 7, i32ConversionData, dTempData, ai8TemperatureUnit);

  127.         /* Delay */
  128.         CLK_SysTickDelay(500000);

  129.         /* Configure the analog input source of channel 7 */
  130.         ADC_CONFIG_CH7(ADC, ADC_ADCHER_PRESEL_INT_BANDGAP);

  131.         /* start A/D conversion */
  132.         ADC_START_CONV(ADC);
  133.     }
  134. }

  135. /*---------------------------------------------------------------------------
  136.    Function:    main
  137.    Parameters:  None.
  138.    Returns:     None.
  139.    Description: main routine of the example.
  140. ---------------------------------------------------------------------------*/
  141. int main(void)
  142. {

  143.     /* Unlock protected registers */
  144.     SYS_UnlockReg();

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

  147.     /* Lock protected registers */
  148.     SYS_LockReg();

  149.     /* Init UART0 for printf */
  150.     UART0_Init();

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

  152.     /* Internal Temperature */
  153.     ADC_Example_InternalTemperature();

  154.     /* Disable ADC module */
  155.     ADC_Close(ADC);

  156.     /* Disable ADC IP clock */
  157.     CLK_DisableModuleClock(ADC_MODULE);

  158.     /* Disable External Interrupt */
  159.     NVIC_DisableIRQ(ADC_IRQn);

  160.     printf("\nExit ADC example code\n");

  161.     while (1);

  162. }
执行结果
5395060e96a06e07f6.png
huahuagg 发表于 2021-7-10 18:06 | 显示全部楼层
内部测温一般用于什么方面
cyclefly 发表于 2021-7-12 15:19 | 显示全部楼层
前几天也是看到Band-gap电压,
ADC的参考电压不固定么?

感觉很多之前的定义和理解,都被刷新了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

143

主题

1720

帖子

3

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