项目所要实现的功能
ADC:Analog-to-Digital Converter
将时间和幅值连续的模拟量转化为时间和幅值离散的数字量
A/D转换一般要经过采样、保持、量化和编码4个过程
量程:指ADC所能输入模拟信号的类型和电压范围,即参考电压。信号类型包括单极性和双极性。
转换位数:量化过程中的量化位数n。 A/D转换后的输出结果用n位二进制数来表示。
【例】:10位ADC的输出值就是0~1023。
分辨率:ADC能够分辨的模拟信号最小变化量。计算公式是,分辨率 = 量程 / 2的n次方
【例】:量程为单极性0-5V,8位ADC的分辨率是,5 / 256 = 0.0195V
转换时间:ADC完成一次完整的A/D转换所需要的时间,包括采样、保持、量化、编码的全过程。
有一个温度测控系统,已知温度传感器在0到100度之间为线性输出,参考电压为5V,采用8为的A/D转换器,0度的时候,测的电压为1.8伏,100度的时候,测的电压为4.3伏。
【问题1】:系统的分辨率是多少?
【问题2】:采集到数据10010001,表示多大电压?温度是多少?
由于温度是线性变化,先求得斜率k,得到温度和电压的关系表达式。
k = (100 – 0)/(4.3-1.8) = 40, y = 40*(x-1.8) (x为采样得到的电压)
由于采用的是8为ADC,参考电压为5V,所以分辨率为:
5 / 256 = 0.0195V = 19.5mV(最小能分辨的电压,分辨率)
0.0195 * 40 = 0.78度(最小能分辨的温度)
因为 10010001B = 91H = 145, 所以 0.0195 * 145 = 2.8275V
该电压信号对应的温度是:(2.83V – 1.8V) * 40 = 41.1摄氏度
共分为三种:轮询、中断和DMA三种模式
开启ADC函数
HAL_ADC_Start(&hadc1); //轮询模式开启ADC
HAL_ADC_Start_IT(&hadc1); //中断模式开启ADC
HAL_ADC_Start_DMA(&hadc1);//DMA模式开启ADC
关闭ADC函数
HAL_ADC_Stop(&hadc1); //轮询模式关闭ADC
HAL_ADC_Stop_IT(&hadc1); //中断模式关闭ADC
HAL_ADC_Stop_DMA(&hadc1);//DMA模式关闭ADC
读取ADC转换值
HAL_ADC_GetValue(&hadc1);
ADC校准函数(通常在ADC初始化之后加上该函数)
MX_ADC1_Init(); //ADC初始化
HAL_ADCEx_Calibration_Start(&hadc1);//AD校准
等待转换结束函数(用于轮询模式)
void HAL_ADC_PollForConversion(&hadc1, 50){//第二个参数为等待时间
//判断转化函数是否结束的条件语句
if(HAL_ADC_PollForConversion(&hadc1,10) == HAL_OK){
/*User Code*/
}
}
ADC中断回调函数(用于中断模式,中断发生则进入该函数)
void HAL_ADC_ConvCpltCallback(&hadc1){
if(hadc->Instance == ADC1){
/*User Code*/
}
}
时钟配置
在RCC中选择HSE,配置时钟树
需要注意的是为确保转化精确度,ADC的时钟不能超过14MHz
如图是ADC Prescaler(ADC预分频器,ADC模块的时钟来源)是12MHz
当然你配置的一旦超过14MHz,STM32CubeMX会报错
ADC配置
如图进行配置,ADC选择通道1,自动配置PA1,其他Setting用默认的即可
简单介绍一下有用的参数
Mode——Independent mode
即独立模式,每个ADC独立工作,好像就看到这一个选项。。。
Data Alignment (数据对齐方式)
一般选择右对齐,除非有特殊要求
Scan Conversion Mode( 扫描模式 )
用到多个通道会自动设置为ENABLE
Number OF Conversion(转换通道数)
用到几个通道就选几,默认自然是1
Continuous Conversion Mode(连续转换模式)
连续不连续的区别在于多个数据转化是全部转换完成再停止,还是转换一个停一下,等待下一个触发转化命令
Rank——Sampling Time(采用周期),默认1.5个周期,不知道干嘛用
其他常规配置就不再赘述,可以看我之前的博客
生成代码即可
由于只需要输出,不需要输入,所以就不用串口收发函数了
这里用printf()函数输出数据信息
/* printf重定向 */
int fputc(int ch ,FILE *f){
uint8_t temp[1] = {ch};
HAL_UART_Transmit(&huart1, temp, 1, 2);
return ch;
}
由于经常使用,这里我们把它写入Keil的Template下,以便随时调用
还有一点需要注意的,使用fput和fgetc函数达到重定向C语言HAL库输入输出函数必须在MDK的工程选项把“Use MicroLIB”勾选上,如图所示
MicoroLIB是缺省C库的备选库,它对标准C库进行了高度优化使代码更少,占用更少资源。
自定义转换函数
void ADC_TO_VOL()
{
HAL_ADC_Start(&hadc1);
LED_ON;
if(HAL_ADC_PollForConversion(&hadc1,10) == HAL_OK)
{
ADC_Value = HAL_ADC_GetValue(&hadc1);
}
printf("ADC 采样值: %d, 电压值: %.4fV \r\n",ADC_Value,ADC_Value*3.3f/4096);
LED_OFF;
}
注意用printf()函数时,要引入stdio.h文件
#include "stdio.h"
然后我们在main函数while循环里写入代码即可,如下所示
while (1)
{
ADC_TO_VOL();
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
写完了,编译运行生成hex文件即可
原理图如下
注意虚拟终端的连线方式,由于只要输出即可,所以我们只要将TX(PA9端口)连RXD
滑动变阻器如何找到?
在元件库里搜索"POT-HG"即可找到带数显的滑动变阻器,普通款就是"POT"
程序没问题
采样结果一直是0,不知道是为什么
我是爱学习的诸葛铁锤,觉得有用的话点个赞哈,啾咪