0x00前言
小葵花妈妈课堂:
由ST数据手册AN4195可知STM32 F1 F3系列ADC为12bit精度的逐级逼近式ADC,属于中速ADC,F1系列拥有16个外部单端输入,而F3系列有15个外部单端/差分ADC和三个内部通道。
学习内容:
1.轮询方式单通道ADC读取电压
2.中断方式单通道ADC读取电压
3.DMA方式单通道ADC读取电压
4.DMA方式多通道ADC读取电压
5.STM32 ADC工作模式介绍
6.STN32 HAL库相关ADC函数
使用硬件:
1.F103C8T6核心板
2.光敏电阻模块(可选)
0x01软件配置
1.配置外部晶振
配置时钟树(根据自己板子情况而定)
2.配置SW Debug接口
注:因为博主ADC选的是IN0通道,占用了PA0,所以 System Wake-UP 就无法选中,如果需要 System Wake-UP 可以使用其他的ADC通道
3.配置USART串口
如果对HAL库串口操作不是很了解。可以参考我的上一篇博客:
【CubeIDE】STM32 HAL库史上最详细教程(一):UART串口收发
3.配置ADC (单通道)
0x02 模式讲解
- 间断/连续模式:
1.如果开启间断模式,每次需要先使用HAL_ADC_Start()(或HAL_ADC_Start_IT(),HAL_ADC_Start_DMA()下文不再赘述)启动转换,需要使用HAL_ADC_PollForConversion()等待转换完成,HAL_ADC_GetState()获取ADC转换状态(若返回值为HAL_OK说明转换完成),转换完成后使用HAL_ADC_GetValue()读取ADC原始值,读取完成后,使用HAL_ADC_Stop()停止转换,如需再次获取ADC数据,需重复执行上述步骤。
2.间断模式的缺点很明显:麻烦~ 优点就是节省系统资源,安全性更高,而间断模式会不断抛出DMA,IT中断,导致系统安全性降低~
3.如果开启连续模式,只需要使用一次HAL_ADC_Start(),开启转换,ADC会马不停蹄的电压转换成数字量,用户只需要调用HAL_ADC_GetValue(),读取ADC原始值
4.连续模式的优缺点和间断模式真好相反~
- 扫描模式(开启/关闭)
1.如果设置了多个ADC转换通道(不是勾选的通道数量,是Number Of Conversion里配置的数量),扫描模式自动开启,且无法关闭,如果只有一个转换通道,则扫描模式默认关闭,且无法开启。
2.假设开启了扫描模式,且RANK1 RANK2 RANK3分别对应IN3 IN2 IN1 通道,则转换一次通道顺序为IN3 IN2 IN1
0x03 ADC单通道采样
(模式:间断模式 非扫描模式)
1.重定向 printf(),不清楚怎么操作见上一篇博客
【CubeIDE】STM32 HAL库史上最详细教程(一):UART串口收发
#include "stdio.h"
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1,100);
return ch;
}
2.打开浮点数转义,CubeIDE 默认不支持浮点数类型进行字符转义(这里困扰了我很久~)
选项目->属性(CubeIDE下拉框没法截图QAQ)
一定要记得点应用啊喂~
3.串口打印电压值
定义两个变量,分别用于储存原始值和转换完的电压值
这里要插一嘴,stm32f1系列是12bit ADC,所以转换完是12位的无符号整型,C语言中没有能够12bit的数据类型,所以取最节省系统资源又能保持数值不变的uint16_t (就是unsigned short)类型,由于ADC采样电压范围是0-3.3v,采样值呈线性分布,假设ADC转换值为Ax 那么实际电压就等于 Ax * 3.3 / 2 ** 12 即 Ax * 3.3 / 4096
串口打印电压值
运行结果
4.使用连续采样模式打印电压值
使能连续模式
别忘了生成代码~
在原来的基础上修改代码
运行结果
5.中断方式读取电压值
(模式:连续模式 非扫描模式)
使能ADC全局中断
在原有的基础上修改代码
运行结果
6.DMA方式读取电压值
(模式:连续模式 非扫描模式)
配置DMA
增大转换周期
CubeIDE默认配置1.5Cycles的转换周期,导致DMA触发的中断干扰CPU导致串口无法正常发送数据。
解决方法有二,一者取消DMA中断,但CubeIDE 图形化配置中 DMA全局中断无法取消,网上有很多大佬通过修改DMA初始化代码取消DMA中断,这样既麻烦还会影响到其他需要DMA的外设,所以博主采取第二种方法,即增大转换时间
如果有不信邪的小伙伴可以试试用默认的1.5Cycles~
在原来的基础上修改代码
运行结果
0x04 ADC DMA方式多通道采样
由数据手册可知,F1和F3系列ADC外设用于储存数据的ADC_DR只有16bit,所以一个ADC配置多个通道的时候,下一个通道的转换数据就会覆盖这次的数据,如果DMA方式进行多通道读取数据就可以解决这个问题(具体怎么个原理我也不知道),所以本文只讨论DMA方式ADC多通道读取数据。
1.配置 ADC多通道
2.定义用于储存 电压和的ADC原始值的变量
Tip: 多通道ADC转换顺序跟RANK有关,详见SCAN模式讲解部分
3.添加代码
运行结果
0xFF 完
既然都看完了,点个赞吧