找回密码
立即注册
搜索
热搜: 活动 交友 discuz
发新帖

132

积分

0

好友

10

主题
发表于 2023-9-22 12:16:33 | 查看: 579| 回复: 3 IP:中国广东省 中国电信

最近学习HC32L110遇到太多坑了,内部温度采集调试了很久都没搞出来,求大佬分享一下内部温度采集的程序,谢谢谢谢

发表于 2023-9-22 12:17:42 IP:中国广东省 中国电信

image.png

文档说的很详细了,建议看文档

发表于 2023-9-22 12:18:24 IP:中国广东省 中国电信

HC32L110C6PA是华大基础的一款MCU,该MCU内置了一个ADC模块,可以实现内部温度的采集。下面是一个基本的温度采集代码:

#include "hc32l110.h"
#include "hc32l110_gpio.h"
#include "hc32l110_clk.h"
#include "hc32l110_adc.h"

void Delay(uint32_t u32Cnt);

void ADC_Init(void);
void ADC_Start(void);
uint16_t ADC_ReadData(uint8_t u8Channel);

int main(void)
{
    uint16_t u16AdcData;
    float fTemp;

    CLK_XtalConfig(CLK_XTALCMD_HIGH);
    ADC_Init();

    while (1)
    {
        ADC_Start();
        while (ADC_GetFlag(ADC_FLAG_EOCA) == Reset) {}
        ADC_ClearFlag(ADC_FLAG_EOCA);
        u16AdcData = ADC_ReadData(ADC_CH0);
        fTemp = (float)(u16AdcData - 544) * 0.977f + 25.0f; // 转换温度值
        Delay(50000);
    }
}

void ADC_Init(void)
{
    stc_adc_cfg_t stcAdcCfg;

    ///< 打开ADC外设时钟
    CLK_FcgPeriphClockCmd(CLK_FCG_ADC, Enable);

    stcAdcCfg.enAdcOpMode = AdcSCanMode;  //扫描模式采样
    stcAdcCfg.enAdcClkSel = AdcClkSysTDiv1;  //采样时钟为系统时钟/1
    stcAdcCfg.enAdcSampTimeSel = AdcSampTime4Clk;  //采样时间选择为4个采样时钟
    stcAdcCfg.enAdcRefVolSel = VoltageRefAvcc;  //电压参考源为AVCC
    stcAdcCfg.enAdcResultAlign = AdcDataAlignRight;  //采样数据右对齐
    stcAdcCfg.enAdcSampTimeCfgA = AdcSampTimeCfgDefault;
    stcAdcCfg.enAdcSampTimeCfgB = AdcSampTimeCfgDefault;
    stcAdcCfg.enAdcSampTimeCfgC = AdcSampTimeCfgDefault;
    stcAdcCfg.enAdcSampTimeCfgD = AdcSampTimeCfgDefault;
    ADC_Init(&stcAdcCfg);

    ///< 选择通道0进行采样
    ADC_ConfigChannel(ADC_CH0, AdcExInputCH0);
    ///< 使能DMA传输
    ADC_DmaCmd(Enable);
}

void ADC_Start(void)
{
    ///< 使能ADC转换
    ADC_Start();
}

uint16_t ADC_ReadData(uint8_t u8Channel)
{
    uint16_t u16AdcData;

    u16AdcData = ADC_GetChannelData(u8Channel);

    return u16AdcData;
}

void Delay(uint32_t u32Cnt)
{
    uint32_t i = 0;
    for (i = 0; i < u32Cnt; i++)
    {
        __NOP();
    }
}

其中,关于温度的转换公式为:

温度值 = (ADC采样值 - 544)* 0.977 + 25

这个公式是针对HC32L110C6PA的内部温度传感器的,如果使用其他型号的MCU,需要根据其内部温度传感器的特性来修改转换公式。

发表于 2023-9-22 12:22:13 IP:中国广东省 中国电信

您可以参考以下的步骤和代码:

  1. 在CUBEMX配置界面左侧的Analog界面中选中ADC3,即可看到右边存在一个Temperature Sensor Channel,点击选中,在此使用轮询方式对温度传感器进行读取。
  2. 在ADC配置中找到RANK,修改采样时间为810.5个时钟,更长的采样时间会保证更高的精度。
  3. 在ADC的时钟源选择HSI,即内部高速时钟,频率为16MHz。
  4. 在ADC的通道配置中,选择通道16,即温度传感器通道,设置采样时间为480个时钟周期。
  5. 在ADC的中断配置中,使能EOC中断,即转换结束中断。
  6. 在ADC的初始化函数中,调用ADC_Enable()函数,使能ADC模块。
  7. 在ADC的中断服务函数中,调用ADC_GetResult()函数,获取ADC转换结果。
  8. 根据HC32L110的数据手册,温度传感器的输出电压与温度的关系为:Vtemp = 1.43 - 4.3 10^-3 T,其中T为温度,单位为摄氏度。
  9. 根据ADC的分辨率和参考电压,将ADC转换结果转换为温度传感器的输出电压,然后根据上式反推出温度。

以下是一个简单的示例代码,仅供参考:

#include "adc.h"
#include "gpio.h"

#define ADC_RESOLUTION 4096 // ADC的分辨率为12位,即4096个等级
#define ADC_REF_VOLTAGE 3.3 // ADC的参考电压为3.3V
#define TEMP_SENSOR_SLOPE -4.3e-3 // 温度传感器的斜率,单位为V/℃
#define TEMP_SENSOR_OFFSET 1.43 // 温度传感器的截距,单位为V

uint16_t adc_value; // ADC转换结果
float temp_voltage; // 温度传感器输出电压
float temp_value; // 温度值,单位为摄氏度

void AdcEOCIrqCallback(void)
{
    adc_value = ADC_GetResult(); // 获取ADC转换结果
    temp_voltage = (float)adc_value / ADC_RESOLUTION * ADC_REF_VOLTAGE; // 计算温度传感器输出电压
    temp_value = (TEMP_SENSOR_OFFSET - temp_voltage) / TEMP_SENSOR_SLOPE; // 计算温度值
}

int main(void)
{
    stc_adc_cfg_t stcAdcCfg; // ADC配置结构体
    stc_adc_irq_t stcAdcIrq; // ADC中断结构体
    stc_adc_irq_calbakfn_pt_t stcAdcIrqCalbaks; // ADC中断回调函数结构体

    // 初始化ADC配置结构体
    stcAdcCfg.enAdcRefVolSel = RefVolSelAVDD;
    stcAdcCfg.enAdcResultAlign = AdcAlignRight;
    stcAdcCfg.enAdcSampTimeSel = AdcSampTime8Clk;
    stcAdcCfg.enAdcTrig0Sel = AdcTrigDisable;
    stcAdcCfg.enAdcTrig1Sel = AdcTrigDisable;

    // 初始化ADC中断结构体
    stcAdcIrq.bAdcIrq = FALSE;
    stcAdcIrq.bAdcRegCmp = FALSE;
    stcAdcIrq.bAdcHhtCmp = FALSE;
    stcAdcIrq.bAdcLltCmp = FALSE;

    // 初始化ADC中断回调函数结构体
    stcAdcIrqCalbaks.pfnAdcIrq = AdcEOCIrqCallback;
    stcAdcIrqCalbaks.pfnAdcRegCmp = NULL;
    stcAdcIrqCalbaks.pfnAdcHhtCmp = NULL;
    stcAdcIrqCalbaks.pfnAdcLltCmp = NULL;

    // 初始化ADC模块
    ADC_Init(&stcAdcCfg);

    // 使能ADC中断
    ADC_EnableIrq(&stcAdcIrq);

    // 注册ADC中断回调函数
    ADC_ConfigIrq(&stcAdcIrqCalbaks);

    // 使能ADC模块
    ADC_Enable();

    // 配置ADC通道
    ADC_ConfigChannel(AdcExInputCH16, AdcSampTime480Clk);

    // 启动ADC转换
    ADC_Start();

    while (1)
    {
        // 在此处添加您的代码
    }
}
*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|国产电子社区 ( 沪ICP备2023018578号-1|

苏公网安备 32011102010465号


)|网站地图

GMT+8, 2024-7-27 17:58 , Processed in 0.068126 second(s), 26 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表