我是靠谱客的博主 听话樱桃,这篇文章主要介绍【WB32库开发】第14章 (上) ADC电压采集——单通道采集14.1 认识WB32的ADC14.2 ADC中断转换实验14.2.1 预处理文件、宏定义文件与函数声明14.2.2 ADC结构体配置及其相关配置14.2.3 ADC中断服务函数14.2.3 中断初始化结构体成员配置14.3 实验结果14.4 补充实验与结果,现在分享给大家,希望可以做个参考。

14.1 认识WB32的ADC

WB32有1个ADC,精度为12位,这个ADC有16个外部通道,分别对应着16个不同的IO口,具体可见WB32数据手册中管脚功能描述表。

ADC的输入电压范围为0-3.3V,若输入的电压过高或过低,可以设计一个外部调理电路,把需要转换的输入电压降低或升高到0-3.3V,这样WB32的ADC就可以测量了。

确定好输入电压后,即可通过输入通道检测输入电压了,但我们还需注意这16个外部通道在转换时还分为规则通道和注入通道;
规则通道为我们常用的通道,而注入通道是一种在规则通道转换时强行插入进行转换的通道,也就是说当规则通道转换过程中有注入通道插队,那么就先转换完注入通道,再继续转换规则通道;这和我们的中断有相似之处;

注入通道只会在有规则通道的时候才会存在。

此外,想要用好ADC还需要了解转换顺序、触发源、转换时间、中断(三种情况:转换完成中断、模拟看门狗中断、DMA请求)和电压转换等,老样子,在例程中带大家一起学习。

14.2 ADC中断转换实验

本节使用固件库ADC中ADC_Interrupt工程,讲解如何配置ADC独立模式单通道采集,单通道采集适用AD转换完成中断,在中断服务函数中读取数据(单通道也可通过DMA的方式来读取,本例主要为展示此方法,在日常使用中可多用DMA来完成ADC采集,使用DMA传输数值的方式不会影响MCU正在运行的程序)。

14.2.1 预处理文件、宏定义文件与函数声明

复制代码
1
2
3
4
5
6
7
8
#include "wb32f10x.h" #include <stdio.h> //若使用Printf或Scanf函数,必须包含此头文件 #include "bsp_uart1.h" //使用UART1,必须包含其对应头文件 ADC_InitTypeDef ADC_InitStructure; //将ADC_InitTypeDef宏定义为ADC_InitStructure void NVIC_Configuration(void); //中断设置函数,由用户自定义

本节使用到WB32的ADC,就必须配置ADC初始化结构体成员,宏定义名称大家已经见到很多了,请务必习惯这种写法。

14.2.2 ADC结构体配置及其相关配置

这里笔者将有关ADC输出的所有代码全部在这里进行注释。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/* 初始化UART1 */ uart1_init(72000000, 115200); /* 使能ADC, GPIOA 时钟 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_BMX1 |RCC_APB1Periph_ADC |RCC_APB1Periph_GPIOA, ENABLE); /* 设置PA3 (ADC Channel3) 为模拟模式 */ GPIO_Init(GPIOA, GPIO_Pin_3, GPIO_MODE_ANA); /* 中断配置函数,由用户自定义 ------------------------------------------------------*/ NVIC_Configuration(); /* ADC 模拟模式相关配置函数,了解有如下配置即可---------------------------------------*/ PWR_UnlockANA(); ANCTL_SARADCCmd(ENABLE); PWR_LockANA(); /* ADC结构体成员配置 */ ADC_InitStructure.ADC_ScanConvMode = DISABLE; //ADC扫描模式选择,单通道为DISABLE,多通道为ENABLE ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //ADC单次转换或者连续转换选择,这里DISABLE配置为单次转换 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //ADC转换触发信号选择,一般设置None为软件自动触发 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //转换结果对齐模式,一般选择右对齐 ADC_InitStructure.ADC_NbrOfChannel = 1; //AD转换通道树木,根据实际设置,本次为单通道,即为1 ADC_Init(&ADC_InitStructure); //初始化ADC初始化结构体成员 /* ADC规则通道设置。这里配置为通道三、第一个转换,此采样时间为7.5个时钟周期 */ ADC_RegularChannelConfig(ADC_Channel_3, 1, ADC_SampleTime_7Cycles5); /* ADC转换结束产生中断,在中断服务函数中读取转换值 */ ADC_ITConfig(ADC_IT_EOC, ENABLE); /* 使能ADC外部触发转换 */ ADC_ExternalTrigConvCmd(ENABLE); /* 使能ADC */ ADC_Cmd(ENABLE); /* 开始ADC校准 */ ADC_StartCalibration(); /* 检查校准是否完成 */ while(ADC_GetCalibrationStatus()); /* 使能ADC复位校准寄存器 */ ADC_ResetCalibration(); /* 检查ADC校准寄存器是否复位完成 */ while(ADC_GetResetCalibrationStatus()); /* 没有使用外部触发,故使用软件触发ADC转换 */ ADC_SoftwareStartConvCmd(ENABLE);

在学习时大家看到这么多的代码是很头疼的,但实际上在WB32标准库下,这些代码都是有迹可循的,需要大家不断的学习和总结。

14.2.3 ADC中断服务函数

在上部分的程序中,我们看到了一条代码ADC_ITConfig(ADC_IT_EOC, ENABLE);这条代码的注释已经标明了其功能,即ADC转换完成后,硬件会将ADC_IT_EOC这个中断标志位自动置1,告诉WB32可以执行对应的中断服务函数了:

复制代码
1
2
3
4
5
6
7
8
9
void ADC_IRQHandler(void) { if(ADC_GetITStatus(ADC_IT_EOC) != RESET) //判断ADC是否转换完成 { ADC_ClearITPendingBit(ADC_IT_EOC); //转换完成后清除该中断位 printf("rADC Channel 3: %-5d", ADC_GetADValue(ADC->DR)); //通过ADC_GetADValue这个函数将得到的数值打印出来 } }

14.2.3 中断初始化结构体成员配置

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 配置并使能ADC中断 */ NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }

此结构体大家务必熟悉,这个结构体在使用到中断时必须配置。

14.3 实验结果

代码编译烧录到WB32中,连接好串口,打开串口调试助手。

首先在PA3浮空时按下复位按键,接着将PA3接入GND时按下复位按键,最后将PA3接入3.3V时按下复位按键;这三次的得到的数值如图显示:
在这里插入图片描述

我们可以看到PA3浮空时ADC读到的数值为52,PA3接入GND时ADC读到的数值为52,PA3接入3.3V时ADC读到的数值为4093。

解释一下,因为ADC是12位的,那么12位满量程对应的就是3.3V,12位满量程对应的数字值为2^12(即4096),数值0对应的就是0V。

注意:
1)我们读出的数值并没有很完美的达到0与4096,这是由于误差和芯片的固有设计决定的,可以忽略。

2)在引脚浮空时,根据硬件设计的不同有可能读出不同的值,属于正常情况。

14.4 补充实验与结果

本例程读出的数据不太直观,为此我们新建一个变量用来存放ADC读取的值,并将此值通过运算转换为电压进行显示:

仅需修改ADC中断服务函数部分:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
void ADC_IRQHandler(void) { float ADC_V_Value = 0; if(ADC_GetITStatus(ADC_IT_EOC) != RESET) { ADC_ClearITPendingBit(ADC_IT_EOC); ADC_V_Value = ADC_GetADValue(ADC->DR); printf("rADC Channel 3: %5.0f rn", ADC_V_Value); printf("rADC Channel 3 Voltage: %1.1f Vrn",(3.3 * ADC_V_Value) / 4096); } }

实验结果如下:
在这里插入图片描述
还是按照先测浮空,接着测GND,最后测3.3V的顺序;

可以看到,除了测得的浮空值略有不同(不影响结果),PA3测得的GND的电压值与3.3V的电压值都是十分准确的。

注意:此例程可以测试0-3.3V内的电压值,若超过3.3V,例如需测量的范围为0-10V,则需要通过外部调理电路将其降压为0-3.3V。

最后

以上就是听话樱桃最近收集整理的关于【WB32库开发】第14章 (上) ADC电压采集——单通道采集14.1 认识WB32的ADC14.2 ADC中断转换实验14.2.1 预处理文件、宏定义文件与函数声明14.2.2 ADC结构体配置及其相关配置14.2.3 ADC中断服务函数14.2.3 中断初始化结构体成员配置14.3 实验结果14.4 补充实验与结果的全部内容,更多相关【WB32库开发】第14章内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(101)

评论列表共有 0 条评论

立即
投稿
返回
顶部