stm32F407的ADC
stm32连接各种外设的传感器,如:红外测距、温度、气压等传感器,都是通过ADC接口连接的。
一、任务
- 测量按键(WAKE_UP)的按下和放开的电压
- 测量外接的红外测距仪感应的距离和电压
- 两个LED灯分别用于显示测量过程中
二、硬件
- LED:指示灯
- LED7<-->PF7
- LED8<-->PF8
- 红外测距仪
- OUT引脚<-->PF6(此引脚设置为ADC3的IN4)
- GND<-->GND(开发板上任意一个)
- VCC<-->3.3V(开发板上任意一个)
- 轻触开关
- WAKE_UP<-->PA0(此引脚设置为ADC1的IN0)
三、配置
- SYS、RCC、USART等配置同之前的配置;
- ADC配置:Analog标签下
- ADC1:ADC1-->IN0-->Parameter Setting(默认)-->NVIC Setting(启用中断)-->GPIO setting(系统默认引出为PA0引脚)
- ADC3:GPIO-->PF6-->鼠标点击-->ADC3_IN4-->其他设置同ADC1即可
- 在GPIO标签和Analog标签下,都可以启用ADC功能,一个根据ADC的通道进行配置(ADC的通道已经绑定了引脚对应的引脚号),一个是根据GPIO的引脚号进行配置,方式都是一样的。
- ADC的中断功能一定要开启
四、程序流程
同中断、USART、TIM等功能开发,ADC的开发也涉及到中断,因此也是通过调用回调函数实现功能。
main.c-->stm32f4xx_hal_adc.c-->main.c
main.c(启动ADC)
main.c文件中,通过调用ADC中断启动函数,开启ADC功能。
非阻塞式启动ADC(中断,推荐)
HAL_ADC_Start_IT(&hadc3);
阻塞式启动ADC:
HAL_ADC_Start(&hadc1);
main.c(实现回调函数或数据接收)
- 非阻塞式(重写回调函数)
HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
是一个虚函数,在stm32f4xx_hal_adc.c
文件中- 同TIM\USART等,回调函数只有一个,因此,第一步是需要判断传入结构体是哪个ADC接口
- 下面代码中ADC1用于检测按键电压,ADC3用于检测红外测距仪电压
HAL_ADC_GetValue
函数用户获取ADC的值,单位是毫伏- 注意电压的换算方式:ADC是12位,因此最大值4096(2的12次方)
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
if(hadc->Instance==ADC1) {
ADC_Value=HAL_ADC_GetValue(&hadc1);
ADC_Volt=ADC_Value*3.3*1000/4096;
send_USART_Data();
led7_off();
}
if(hadc->Instance==ADC3) {
ADC_Value=HAL_ADC_GetValue(&hadc3);
ADC_Volt=ADC_Value*3.3*1000/4096;
send_USART_Data();
led8_off();
}
}
- 阻塞式调用
阻塞式调用分为两个步骤:启动对应的ADC,然后进行判断ADC是否执行成功,执行成功后就活区ADC的值。
HAL_ADC_Start(&hadc1);
启动ADC1(HAL_ADC_PollForConversion(&hadc1, 10)==HAL_OK)
判断ADC1是在规定超时时间内否执行成功HAL_ADC_GetValue(&hadc1);
获取ADC1的值
void get_ADC_Value() {
HAL_ADC_Start(&hadc1);
led7_on();
if(HAL_ADC_PollForConversion(&hadc1, 10)==HAL_OK) {
ADC_Value=HAL_ADC_GetValue(&hadc1);
ADC_Volt=ADC_Value*3.3*1000/4096;
}
send_USART_Data();
led7_off();
HAL_ADC_Stop(&hadc1);
}
五、其他
- 推荐使用非阻塞模式,更加优雅而且效果更好;
- 开发板自带的adc转换器式12位长度,这也是转换精度
几个常用ADC的函数:
启动函数:
//查询,阻塞方式,启动ADC HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc); //查询,阻塞方式,停止ADC HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc); //中断,非阻塞方式,启动ADC HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc); //中断,非阻塞方式,停止ADC HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc);
读取ADC数据函数 ~~~C uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc);
- 参数1:hadc,ADC实例指针。
- 返回值:uint32_t,ADC转换结果。 ~~~
查询方式,阻塞式A/D转换HAL库函数
HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout); 参数1:hadc,ADC实例指针。 参数2:Timeout,超时时间。 返回值:HAL_StatusTypeDef,函数执行状态。
中断方式,非阻塞式回调
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
ADC的几个概念
* 量程:指ADC所能输入模拟信号的类型和电压范围,即参考电压。信号类型包括单极性和双极性。 * 转换位数:量化过程中的量化位数n。 A/D转换后的输出结果用n位二进制数来表示。 【例】:10位ADC的输出值就是0~1023。 * 分辨率:ADC能够分辨的模拟信号最小变化量。计算公式是,分辨率 = 量程 / 2的n次方 【例】:量程为单极性0-5V,8位ADC的分辨率是,5 / 256 = 0.0195V * 转换时间:ADC完成一次完整的A/D转换所需要的时间,包括采样、保持、量化、编码的全过程。