Air001 ADC内部输入通道温度传感器读取

Air001 ADC内部输入通道温度传感器读取


Air001 内部集成的温度传感器说明

温度传感器产生一个随温度线性变化的电压。温度传感器在内部被连接到ADC内部的输入通道上,用于将传感器的输出转换成数字数值。

Air001模拟/ 数字转换( ADC)

✨Air001芯片具有 1 个 12 位的 SARADC(successive approximation analog-to-digital converter)。该模块共有 12个要被测量的通道,包括 10 个外部通道和 2 个内部通道。

  • 各通道的转换模式可以设定为单次、连续、扫描、不连续模式。转换结果存储在左对齐或者右对齐的 16 位数据寄存器中。
  • ADC 主要特性
    ◼ 高性能
    ➢ 12bit、10bit、8bit 和 6bit 分辨率可配置
    ➢ ADC 转换时间:1us@12bit(1MHz)
    ➢ 自校准
    ➢ 可编程的采样时间
    ➢ 可编程的数据对齐模式
    ➢ 支持 DMA
    ◼ 低功耗
    ➢ 为低功耗操作,降低 PCLK 频率,而仍然维持合适的 ADC 性能
    ➢ 等待模式:防止以低频 PCLK 运行产生溢出
    ◼ 模拟输入通道
    ➢ 10 个外部模拟输入通道:PA[7:0]和 PB[1:0]
    ➢ 1 个内部 temperature sensor 通道
    ➢ 1 个内部参考电压通道(VREFINT)
    ◼ 转换操作启动可以通过
    ➢ 软件启动
    ➢ 可配置极性的硬件启动(TIM1、TIM3 或者 GPIO)
    ◼ 转换模式
    ➢ 单次模式(single mode):可以转换 1 个单通道或者可以扫描一系列通道
    ➢ 连续模式(continuous mode):连续转换被选择的通道
    ➢ 不连续模式(discontinuous mode):每次触发,转换被选择的通道 1 次。

可编程采样时间 (SMP)

在启动 ADC 转换之前,ADC 需要在被测电压源和内嵌采样电容间建立一个直接连接。采样时间必须足够长以便输入电压源对内嵌电容充电到输入电压的水平。

  • 总转换时间计算如下:

tCONV = 采样时间 + (转换分辨率+0.5) x ADC 时钟周期例如:

  • 当 ADC_CLK = 16MHz,分辨率为 12 位,且采样时间为 3.5 个 ADC 时钟周期:
    tCONV = (3.5 + 12.5) x ADC 时钟周期= 16 x ADC 时钟周期 = 1 μs
    EOSMP 标志位用来表明采样阶段的结束。

⛳影响测量精度要素

  • MCU参考电压和实际MCU的供电电压。

  • 采样时间。

  • ✨通过Air001 SDK公开资料包,可找到相对应的测试例程,采用的是ADC中断模式读取内部温度传感器数据。
    Air001 ADC内部输入通道温度传感器读取_第1张图片

  • ⚡如果调整MCU时钟频率,需要调整对应的采样时间或者调整AHB时钟分频系数,以确保ADC转换总转换时间足够。

  • ADC配置函数:

/**
  * @brief  ADC配置函数
  * @param  无
  * @retval 无
  */
static void APP_AdcConfig(void)
{
    __HAL_RCC_ADC_FORCE_RESET();
    __HAL_RCC_ADC_RELEASE_RESET();                                                  /* 复位ADC */
    __HAL_RCC_ADC_CLK_ENABLE();                                                     /* ADC时钟使能 */

    AdcHandle.Instance = ADC1;

    /* ADC校准 */
    if(HAL_ADCEx_Calibration_Start(&AdcHandle) != HAL_OK)
    {
        Error_Handler();
    }

    AdcHandle.Instance                   = ADC1;                                    /* ADC1 */
    AdcHandle.Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV4;               /* 设置ADC时钟 */
    AdcHandle.Init.Resolution            = ADC_RESOLUTION_12B;                      /* 转换分辨率12bit */
    AdcHandle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;                     /* 数据右对齐 */
    AdcHandle.Init.ScanConvMode          = ADC_SCAN_DIRECTION_FORWARD;              /* 扫描序列方向:向上 */
    AdcHandle.Init.EOCSelection          = ADC_EOC_SEQ_CONV;                        /* 转换结束标志 */
    AdcHandle.Init.LowPowerAutoWait      = ENABLE;                                  /* 等待转换模式开启 */
    AdcHandle.Init.ContinuousConvMode    = DISABLE;                                 /* 单次转换模式 */
    AdcHandle.Init.DiscontinuousConvMode = DISABLE;                                 /* 不使能非连续模式 */
    AdcHandle.Init.ExternalTrigConv      = ADC_SOFTWARE_START;                      /* 软件触发 */
    AdcHandle.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE;           /* 触发边沿无 */
    AdcHandle.Init.DMAContinuousRequests = ENABLE;                                  /* DMA循环模式 */
    AdcHandle.Init.Overrun               = ADC_OVR_DATA_OVERWRITTEN;                /* 当过载发生时,覆盖上一个值 */

    AdcHandle.Init.SamplingTimeCommon    = ADC_SAMPLETIME_239CYCLES_5;               /* 通道采样时间为8MHz->41.5ADC时钟周期 */
    /* ADC初始化 */
    if(HAL_ADC_Init(&AdcHandle) != HAL_OK)
    {
        Error_Handler();
    }

    sConfig.Rank         = ADC_RANK_CHANNEL_NUMBER;                                 /* 设置加入规则组通道 */
    sConfig.Channel      = ADC_CHANNEL_TEMPSENSOR;                                  /* 设置采样通道 */
    /* 配置ADC通道 */
    if(HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)
    {
        Error_Handler();
    }
}
  • main函数代码:
/**
  * @brief  应用程序入口函数.
  * @retval int
  */
int main(void)
{
    uint32_t TimerUART = 0;
    /* 初始化所有外设,Flash接口,SysTick */
    HAL_Init();
    /* 系统时钟 初始化 */
    SystemClock_Config(RCC_HSICALIBRATION_24MHz);
	SystemCoreClockUpdate();
    /* 串口初始化*/
    MX_USART_UART_Init();
    /*GPIO 初始化LED */
    MX_GPIO_Init();
    /* 配置ADC */
    APP_AdcConfig();
    printf("Air001 SysClockFreq:%d \r\n", HAL_RCC_GetSysClockFreq());
    TimerUART = HAL_GetTick();
    while(1)
    {
        if((HAL_GetTick() - TimerUART) > 1000)
        {
            /* 校准并启动ADC并使能ADC中断 */
			HAL_ADCEx_Calibration_Start(&AdcHandle);
            if(HAL_ADC_Start_IT(&AdcHandle) != HAL_OK)
            {
                Error_Handler();
            }
            /* LED翻转 */
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
			printf("Air001 RCC_GetPCLK1Freq:%d \r\n", HAL_RCC_GetPCLK1Freq());
             printf(" TEMPERAUTE = %d \r\n", aTEMPERATURE);
			TimerUART = HAL_GetTick();
        }
    }
}
  • 串口打印结果:
    Air001 ADC内部输入通道温度传感器读取_第2张图片

测试工程源码:

链接:https://pan.baidu.com/s/1ZH7Grq26t78Lz4zkwjxoDg 
提取码:v301

  • 此文章仅作为个人学习探索知识的总结,不作为他人引用者的理论依据,由于学识所限,难免会出现错误或纰漏,欢迎大家指正。

你可能感兴趣的:(合宙MCU系列,Air001,ADC)