洋桃电子STM32F407单片机入门教程笔记七:ADC模数转换功能

发布时间:2023年12月28日

?此文档作为对洋桃电子STM32F407单片机视频的整理,B站链接:第23集)ADC模数转换功能_哔哩哔哩_bilibili

????????ADC是将模拟信号转换成数字信号的功能,可以读出端口上的电压值,是常用的单片机内部功能。

????????GPIO端口功能只有高电平和低电平两种输入状态,适用于按键之类的输入电平,只有开和关两种状态的数字信号。输入到单片机时以1和0表示,但还有一些电路输入的是线性电压值,电压是0V~3.3V之间的任意值,这时就需要ADC功能来读取这种模拟电压值,输入到单片机时,在12位分辨率下以0~4095之间的数值表示。通过简单的算法就可以得出真实的电压值。

?

????????ADC功能的应用非常广泛,读光敏电阻可以得出光线强弱数值,读热敏电阻可得出温度值,读电池电压可得出电池电量状态。

1.?F4单片机ADC简介

?

????????STM32F407系列单片机内部有3个独立ADC功能,每个ADC有16个外部输入通道,可设置12位、10位、8位、6位多种转换分辨率,可设置单次和连续转换模式,可以在多通道之间自动轮回采样。

?

????????ADC功能除了16个外部模拟电压输入通道,其中通道16 (ADC_IN16)可读取单片机内部的温度传感器,芯片内置的温度传感器是一个热敏电阻,可提供温度的模拟电压值,我们使用ADC采集此电压值便可得出粗略的芯片内部温度值。通道17(ADC_IN17)连接的是内部参考电压电路,VREFINT可提供一个相对恒定的电压值,用单片机ADC读取这个电压值可用于校准ADC的采样精度。

?

????????VDDA和VSSA是单片机内部模拟电路部分(包括ADC功能)的电源,通常会将其与逻辑电源VDD和VSS并联,VREF+和VREF-是模拟参考电压输入端口,ADC转换的电压范围将由这两个端口提供,在应用中通常会将VREF-与VSSA连接在一起,将VREF+与VDDA连接在一起。使模拟电源电压作为参考电压使用,这里需要注意VREF+端口上的电压值必须大于1.8V且不超过VDDA的电压值。ADCx_IN是从0~15共16个模拟输入通道,可在CubeMX端口视图中将通道映射到复用的GPIO端口。

????????假如VREF与3.3V逻辑电源连接,则ADC可读取的电压范围是0V~3.3V,每个ADC功能都具有12位分辨率,即4096级精度。0V~3.3V电压转换成对应的数值范围是0~4095。

2. ADC硬件电路

?

????????图中可以看出共有两路ADC输入源,开发板上的手调电位器连接到单片机的PC3端口,当可调电阻调到阻值最小值时,PC3输入电压等于0V 转化数值为0。当可调电阻调到阻值最打值时,PC3输入电压等于3.3V 转化数值为4095。当旋钮在最小和最大值之间旋转,PC3输入电压值在0V~3.3V之间线性变化,转化数值在0~4095之间线性变化。

????????开发板上的光敏电阻可以接收环境光线,光敏电阻连接到单片机的PC2端口。当环境无光时光敏电阻RG1达到最大电阻值,由于电阻上拉作用使PC2端口输入的电压值升高。当环境光线强时光敏电阻RG1达到最小电阻值,由于电路的分压作用使PC2端口输入的电压下降。

????????从以上原理可以看出,只要读取PC2和PC3端口的ADC数值就能判断环境光线强弱变化和电位器的旋钮角度。

3. STM32cubeMX初始化

?

????????时钟树视图中ADC功能时钟连接在APB2外设时钟,比时钟最大不超过84MHz 我在这里设置为72MHz。

????????根据电路原理图中的引脚定义来设置单片机端口。

?

?

?

?

4. 运行函数

????????在第105~106行自动生成了ADC1和ADC2的初始化函数,在CubeMX中设置的参数都变成了这里的初始化代码,单片机上电时会执行这两条初始化程序,把设置内容写入ADC功能寄存器,使PC2和PC3端口变成模拟输入状态,使ADC功能准备就绪。

????????在adc.h文件中是宏定义和函数声明,其中不仅包含了ADC读取函数,还有平均值算法和电压值算法的内容。当前只学习ADC的简单数据读取,暂时不需要考虑adc.h文件中的内容。

????????第13~20行的ADC Read函数,函数的参数是ADC功能的句柄,当参数是&hadc1表示读取的是ADC1的数据,当参数是&hadc2表示读取的的ADC2的数据,函数的返回值是最终读出的12位ADC转换数值。

????????函数内部第14行是调用HAL库函数开启ADC1的转换,此程序执行后单片机内部的ADC功能电路开始采集端口的电压值将其转换为12位数值。由于转换的过程需要等待一段时间,所以第15行调用另一个HAL库函数等待ADC转换工作结束。执行这一条程序后程序在此循环等待。当ADC转换结束才继续执行第16行,第16行依然是调用HAL库函数读取ADC转换完成标志位,如果标志位判断为真说明转换成功。转换得出的数值存放到相应寄存器,接下来第17行调用读取ADC数据寄存器的HAL库函数,把数值送到返回值并退出函数。如果第16行判断为假,表示读取失败则不会执行第17行,会执行第19行使返回值等于0xFFFF。因为正常的12位ADC转换数据不会出现OXFFFF这个结果,所以当读取数值是0xFFFF 就表示读取失败。

????????在主函数开始处的第82行定义数组ADC_BUF,用于临时存放转换后的ADC数值。

????????在主循环程序里加入读取ADC数值的程序,在main.c文件的第115~116行调用两次ADC_Read函数,得到的返回值分别存入ADC BUF数组,第117行调用USART1_printf函数把两个数值显示到超级终端,其中“%04d”的意思是用四位十进制显示数值,数值不足四位的用0补充,这样使ADC数值显示为0000~4095,参数中的两个“%04d”按先后顺序对应着逗号后面的ADC_BUF[0]和ADC_BUF[1]两个数值。

5. 实验现象

文章来源:https://blog.csdn.net/m0_61278502/article/details/135255382
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。