ADC(Analog to Digital Converter),模拟数字转换器,是电子工程师必须掌握的一个内容。由于单片机、计算机等是由0和1组成的,因此其无法直接测量或使用连续的模拟信号,需要用ADC将模拟信号转换为离散的数字信号。ADC的具体原理在此处不做展开,我们需要知道的是,ADC内核一般要使用两个参考电压(在单片机中,一般为3.3V)和(在单片机中,一般为0)。ADC的分辨率是指转换为数字信号的精度,如12位ADC能够得到数字信号的最大值为。以12位分辨率为例,当输入电压时,ADC输出满量程值0xFFF;当时,ADC输出0;当时,ADC的输出电压。
因此,若想要使用ADC测量外界某一量程范围内的电压值,只需要将其输入至ADC的通道,读取ADC的输出值,再用输出值公式反向计算输入电压即可。即。
下面我们用PB15的ADC通道测量模拟电压。首先配置Cube:
这里我们不使用ADC外部中断(EXTI(EXTernal Interrupt)),而是使用输入通道15(IN15)。
在圆圈处可以看到,此ADC的分辨率为12位,即它的最大输出为4095。
这样就设置完成了。而使用ADC的代码也非常简单,只需要用到两个HAL库函数:开启ADC和读取ADC输出:
double getADC(ADC_HandleTypeDef *hadc)
{
uint16_t adc = 0;
HAL_ADC_Start(hadc); //开启ADC
adc = HAL_ADC_GetValue(hadc); //读取ADC输出
return 3.3*adc/4095;
}
在主循环中调用此函数,即可通过PB15引脚持续测量外部模拟电压值:
double Vin = getADC(&hadc2);
下面我们以第十四届省赛题为例,总结ADC的用法:
查看电路原理图(资源数据包中的CT117E-M4产品手册),可以看到R37对应的引脚为PB15:
通过调节电位器R37,PB15的模拟电压值能从0~3.3V变化。我们将PB15设置为ADC输入通道,测量其电压值(用以上代码即可),并将测量得到的模拟电压值与PA1输出的占空比建立映射关系:
double pa1_duty = 0.5;
int pa1_autoreload = 20000;
while (1)
{
uint16_t V_R37 = getADC(&hadc2);
pa1_duty = ((0.85-0.1)/(3-1))*(V_R37-1)+0.1;
if (pa1_duty < 0.1) pa1_duty = 0.1;
else if (pa1_duty > 0.85) pa1_duty = 0.85;
__HAL_TIM_SetCompare(&htim2, int(pa1_autoreload*pa1_duty));
}