ADC是模拟到数字转换器(Analog-to-Digital Converter)缩写,主要用于将连续传输的模拟信号转换为数字信号,便于数字系统(如中央处理器CPU、微控制器MCU等)对传输信息进行快速处理和分析。模拟信号是指用连续变化的物理量所表达的信息,如温度、湿度、压力、电压、电流等。ADC模块所采集的模拟信号是连续变化的电压信号,其数值在一定范围内连续变化。
CYW20829内部集成12位的ADC,开发板上能用作模拟量输入的是这几个
先用个可调电阻器实现简单的分压
电阻两端连接VCC和GND,中间连接ADC输入引脚,用ADC测量一下分压后的电压值,初始化ADC,使用单次测量模式
cyhal_adc_t adc_obj;
cyhal_adc_channel_t adc_ch_obj;
void APP_AdcInit(void)
{
cyhal_adc_config_t adc_cfg = {
.continuous_scanning = false,
.resolution = 12,
.average_count = 1,
.ext_vref_mv = 0,
.vneg = CYHAL_ADC_VNEG_VSSA,
.vref = CYHAL_ADC_REF_VDDA,
.ext_vref = NC,
.bypass_pin = NC,
};
cyhal_adc_channel_config_t channel_cfg = {
.enable_averaging = false,
.enabled = true,
.min_acquisition_ns = 1000,
};
cyhal_adc_init(&adc_obj, CYBSP_A1, NULL);
cyhal_adc_channel_init_diff(&adc_ch_obj, &adc_obj, CYBSP_A1, CYHAL_ADC_VNEG, &channel_cfg);
cyhal_adc_configure(&adc_obj, &adc_cfg);
}
在主循环中每隔1秒读取一次电压值,cyhal_adc_read_uv这个方法获取到的是转换好的电压值单位是微伏,除以1000后以mV打印
int main(void)
{
cy_rslt_t result;
int32_t adc_mv;
result = cybsp_init();
if (result != CY_RSLT_SUCCESS)
{
CY_ASSERT(0);
}
APP_LEDInit();
app_uart_init();
APP_AdcInit();
printf("APP Start\n");
/* Enable global interrupts */
__enable_irq();
for (;;)
{
Cy_SysLib_Delay(1000);
adc_mv = cyhal_adc_read_uv(&adc_ch_obj)/1000;
printf("printf adc volt %dmv\n",adc_mv);
cyhal_gpio_toggle(CYBSP_USER_LED1);
}
}
输出结果
用万用表实测电压,ADC测量结果还是比较准的
NTC热敏电阻是负温度系数热敏电阻器,它是以锰、钴、镍和铜等金属氧化物为主要材料,采用陶瓷工艺制造而成的,随着温度升高它的阻值会降低,利用这一特性就可以通过ADC采集到的电压推算当前的温度,接下来就用NTC热敏电阻实现温度测量,电路设计如图
使用10K的上拉电阻,电压反推电阻的公式为R(ntc)=R(10k)*V(ADC)/(VCC-V(ADC))
NTC的阻值与温度对应关系可用过查表的方式获得,数据太多,这里只放一部分,需要注意的是不同的探头会有不同的对照表,使用时需要注意
每100ms读一次ADC值,使用平均值进行简单滤波,每秒输出一次温度值通过串口进行打印,代码如下
uint16_t adc_values[ADC_VALUE_NUM];
uint8_t adc_value_index = 0;
#define NTC_TEMP_MIN 0
#define NTC_TEMP_MAX 45
const float ntc_res[] = {
32.040, 30.490, 29.022, 27.633, 26,317, 25.071, 23.889, 22.769, 27.707, 20.700,
19.788, 18.838, 17.977, 17.160, 16.383, 15.646, 14.945, 14.280, 13.647, 13.045,
12.472, 11.928, 11.409, 10.916, 10.447, 10.000, 9.574, 9.168, 8.781, 8.413,
8.062, 7.727, 7.407, 7.103, 6.812, 6.534, 6.270, 6.017, 5.775, 5.545,
5.324, 5.114, 4.913, 4.720, 4.536, 4.360};
float NTC_GetTempFromRes(float res)
{
uint8_t i = 1;
if(res < ntc_res[NTC_TEMP_MAX - NTC_TEMP_MIN])
return NTC_TEMP_MAX;
if(res > ntc_res[0])
return NTC_TEMP_MIN;
while(i < NTC_TEMP_MAX - NTC_TEMP_MIN + 1)
{
if(res > ntc_res[i])
break;
i += 1;
}
return NTC_TEMP_MIN+i-(res-ntc_res[i])/(ntc_res[i-1]-ntc_res[i]);
}
int main(void)
{
cy_rslt_t result;
float ntc_res = 0;
uint32_t adc_sum = 0;
result = cybsp_init();
if (result != CY_RSLT_SUCCESS)
{
CY_ASSERT(0);
}
APP_LEDInit();
app_uart_init();
APP_AdcInit();
printf("APP Start\n");
__enable_irq();
for (;;)
{
Cy_SysLib_Delay(100);
adc_values[adc_value_index] = cyhal_adc_read_uv(&adc_ch_obj)/1000;
adc_value_index += 1;
if(adc_value_index == ADC_VALUE_NUM)
{
adc_value_index = 0;
adc_sum = 0;
while(adc_value_index < ADC_VALUE_NUM)
{
adc_sum += adc_values[adc_value_index];
adc_value_index += 1;
}
adc_sum/=ADC_VALUE_NUM;
if(adc_sum < 0xFFFF)
ntc_res = 10.0*adc_sum/(3300-adc_sum);
else
ntc_res = 999;
printf("NTC res:%.3f temp %.1f\n",ntc_res,NTC_GetTempFromRes(ntc_res));
adc_value_index = 0;
cyhal_gpio_toggle(CYBSP_USER_LED1);
}
}
}
测量结果
|
此文章已获得独家原创/原创奖标签,著作权归21ic所有,未经允许禁止转载。
|