[AIROC™ 蓝牙] 【英飞凌CYW20829测评】6.通过ADC+NTC电阻测量温度

[复制链接]
2913|2
 楼主| yuyy1989 发表于 2024-6-28 21:33 | 显示全部楼层 |阅读模式
tc, dc, NTC, ADC, AD
ADC是模拟到数字转换器(Analog-to-Digital Converter)缩写,主要用于将连续传输的模拟信号转换为数字信号,便于数字系统(如中央处理器CPU、微控制器MCU等)对传输信息进行快速处理和分析。模拟信号是指用连续变化的物理量所表达的信息,如温度、湿度、压力、电压、电流等。ADC模块所采集的模拟信号是连续变化的电压信号,其数值在一定范围内连续变化。
CYW20829内部集成12位的ADC,开发板上能用作模拟量输入的是这几个

先用个可调电阻器实现简单的分压

电阻两端连接VCC和GND,中间连接ADC输入引脚,用ADC测量一下分压后的电压值,初始化ADC,使用单次测量模式
  1. cyhal_adc_t adc_obj;
  2. cyhal_adc_channel_t adc_ch_obj;
  3. void APP_AdcInit(void)
  4. {
  5.     cyhal_adc_config_t adc_cfg = {
  6.             .continuous_scanning = false,
  7.             .resolution = 12,
  8.             .average_count = 1,
  9.             .ext_vref_mv = 0,
  10.             .vneg = CYHAL_ADC_VNEG_VSSA,
  11.             .vref = CYHAL_ADC_REF_VDDA,
  12.             .ext_vref = NC,
  13.             .bypass_pin = NC,
  14.     };
  15.     cyhal_adc_channel_config_t channel_cfg = {
  16.             .enable_averaging = false,
  17.             .enabled = true,
  18.             .min_acquisition_ns = 1000,
  19.     };
  20.     cyhal_adc_init(&adc_obj, CYBSP_A1, NULL);
  21.     cyhal_adc_channel_init_diff(&adc_ch_obj, &adc_obj, CYBSP_A1, CYHAL_ADC_VNEG, &channel_cfg);
  22.     cyhal_adc_configure(&adc_obj, &adc_cfg);
  23. }

在主循环中每隔1秒读取一次电压值,cyhal_adc_read_uv这个方法获取到的是转换好的电压值单位是微伏,除以1000后以mV打印
  1. int main(void)
  2. {
  3.     cy_rslt_t result;
  4.     int32_t adc_mv;
  5.     result = cybsp_init();
  6.     if (result != CY_RSLT_SUCCESS)
  7.     {
  8.         CY_ASSERT(0);
  9.     }
  10.     APP_LEDInit();
  11.     app_uart_init();
  12.     APP_AdcInit();
  13.     printf("APP Start\n");
  14.     /* Enable global interrupts */
  15.     __enable_irq();

  16.     for (;;)
  17.     {
  18.         Cy_SysLib_Delay(1000);
  19.         adc_mv = cyhal_adc_read_uv(&adc_ch_obj)/1000;
  20.         printf("printf adc volt %dmv\n",adc_mv);
  21.         cyhal_gpio_toggle(CYBSP_USER_LED1);
  22.     }
  23. }

输出结果

用万用表实测电压,ADC测量结果还是比较准的


NTC热敏电阻是负温度系数热敏电阻器,它是以锰、钴、镍和铜等金属氧化物为主要材料,采用陶瓷工艺制造而成的,随着温度升高它的阻值会降低,利用这一特性就可以通过ADC采集到的电压推算当前的温度,接下来就用NTC热敏电阻实现温度测量,电路设计如图

使用10K的上拉电阻,电压反推电阻的公式为R(ntc)=R(10k)*V(ADC)/(VCC-V(ADC))
NTC的阻值与温度对应关系可用过查表的方式获得,数据太多,这里只放一部分,需要注意的是不同的探头会有不同的对照表,使用时需要注意


每100ms读一次ADC值,使用平均值进行简单滤波,每秒输出一次温度值通过串口进行打印,代码如下
  1. uint16_t adc_values[ADC_VALUE_NUM];
  2. uint8_t adc_value_index = 0;
  3. #define NTC_TEMP_MIN 0
  4. #define NTC_TEMP_MAX 45
  5. const float ntc_res[] = {
  6.     32.040, 30.490, 29.022, 27.633, 26,317, 25.071, 23.889, 22.769, 27.707, 20.700,
  7.     19.788, 18.838, 17.977, 17.160, 16.383, 15.646, 14.945, 14.280, 13.647, 13.045,
  8.     12.472, 11.928, 11.409, 10.916, 10.447, 10.000,  9.574,  9.168,  8.781,  8.413,
  9.      8.062,  7.727,  7.407,  7.103,  6.812,  6.534,  6.270,  6.017,  5.775,  5.545,
  10.      5.324,  5.114,  4.913,  4.720,  4.536,  4.360};
  11. float NTC_GetTempFromRes(float res)
  12. {
  13.     uint8_t i = 1;
  14.     if(res < ntc_res[NTC_TEMP_MAX - NTC_TEMP_MIN])
  15.         return NTC_TEMP_MAX;
  16.     if(res > ntc_res[0])
  17.         return NTC_TEMP_MIN;
  18.     while(i < NTC_TEMP_MAX - NTC_TEMP_MIN + 1)
  19.     {
  20.         if(res > ntc_res[i])
  21.             break;
  22.         i += 1;
  23.     }
  24.     return NTC_TEMP_MIN+i-(res-ntc_res[i])/(ntc_res[i-1]-ntc_res[i]);
  25. }
  26. int main(void)
  27. {
  28.     cy_rslt_t result;
  29.     float ntc_res = 0;
  30.     uint32_t adc_sum = 0;
  31.     result = cybsp_init();
  32.     if (result != CY_RSLT_SUCCESS)
  33.     {
  34.         CY_ASSERT(0);
  35.     }
  36.     APP_LEDInit();
  37.     app_uart_init();
  38.     APP_AdcInit();
  39.     printf("APP Start\n");
  40.     __enable_irq();

  41.     for (;;)
  42.     {
  43.         Cy_SysLib_Delay(100);
  44.         adc_values[adc_value_index] = cyhal_adc_read_uv(&adc_ch_obj)/1000;
  45.         adc_value_index += 1;
  46.         if(adc_value_index == ADC_VALUE_NUM)
  47.         {
  48.             adc_value_index = 0;
  49.             adc_sum = 0;
  50.             while(adc_value_index < ADC_VALUE_NUM)
  51.             {
  52.                 adc_sum += adc_values[adc_value_index];
  53.                 adc_value_index += 1;
  54.             }
  55.             adc_sum/=ADC_VALUE_NUM;
  56.             if(adc_sum < 0xFFFF)
  57.                 ntc_res = 10.0*adc_sum/(3300-adc_sum);
  58.             else
  59.                 ntc_res = 999;
  60.             printf("NTC res:%.3f temp %.1f\n",ntc_res,NTC_GetTempFromRes(ntc_res));
  61.             adc_value_index = 0;
  62.             cyhal_gpio_toggle(CYBSP_USER_LED1);
  63.         }
  64.     }
  65. }

测量结果



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
caoyunhj2301 发表于 2024-6-30 13:59 | 显示全部楼层
连接电路:

将一个可调电阻器连接在VCC和GND之间。
电阻器的中间引脚连接到CYW20829的ADC输入引脚,以便将分压后的电压送入ADC测量。
gaonaiweng 发表于 2024-6-30 16:25 | 显示全部楼层
在主循环中每隔1秒读取一次电压值,cyhal_adc_read_uv这个方法获取到的是转换好的电压值单位是微伏
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

168

主题

828

帖子

10

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