求助帖,AD采集时,在ADC输入adc0804引脚图加一个基准电压有什么用

第30章 &&&&ADC&电压采集
全套集视频教程和页教程请到秉火论坛下载:
野火视频教程优酷观看网址:
本章参考资料:《中文参考手册》章节。
学习本章时,配合《中文参考手册》章节一起阅读,效果会更佳,特别是涉及到寄存器说明的部分。
30.1 ADC简介
有个,每个有位、位、位和位可选,每个有个外部通道。另外还有两个内部源和通道挂在上。具有独立模式、双重模式和三重模式,对于不同转换要求几乎都有合适的模式可选。功能非常强大,具体的我们在功能框图中分析每个部分的功能。
30.2 ADC功能框图剖析
图 01 单个ADC功能框图
掌握了的功能框图,就可以对有一个整体的把握,在编程的时候可以做到了然如胸,不会一知半解。框图讲解采用从左到右的方式,跟采集数据,转换数据,传输数据的方向大概一致。
1.&&&&①电压输入范围
输入范围为:&&。由、、、、这四个外部引脚决定。
我们在设计原理图的时候一般把和接地,把和接,得到的输入电压范围为:。
如果我们想让输入的电压范围变宽,去到可以测试负电压或者更高的正电压,我们可以在外部加一个电压调理电路,把需要转换的电压抬升或者降压到,这样就可以测量了。
2.&&&&②输入通道
我们确定好输入电压之后,那么电压怎么输入到?这里我们引入通道的概念,的多达个通道,其中外部的个通道就是框图中的、。这个通道对应着不同的口,具体是哪一个口可以从手册查询到。其中还有内部通道:的通道连接到内部的,通道连接到了内部参考电压连接,通道连接到了芯片内部的温度传感器或者备用电源。和的通道、、全部连接到了内部的。
图 02 STM32F429IGT6 ADC 通道
外部的个通道在转换的时候又分为规则通道和注入通道,其中规则通道最多有路,注入通道最多有路。那这两个通道有什么区别?在什么时候使用?
规则通道:顾名思意,规则通道就是很规矩的意思,我们平时一般使用的就是这个通道,或者应该说我们用到的都是这个通道,没有什么特别要注意的可讲。
注入,可以理解为插入,插队的意思,是一种不安分的通道。它是一种在规则通道转换的时候强行插入要转换的一种。如果在规则通道转换过程中,有注入通道插队,那么就要先转换完注入通道,等注入通道转换完成后,再回到规则通道的转换流程。这点跟中断程序很像,都是不安分的主。所以,注入通道只有在规则通道存在时才会出现。
3.&&&&③转换顺序
规则序列寄存器有个,分别为、、。控制着规则序列中的第一个到第六个转换,对应的位为:,第一次转换的是位,如果通道想第一次转换,那么在写即可。控制着规则序列中的第到第个转换,对应的位为:,如果通道想第个转换,则写即可。控制着规则序列中的第到第个转换,对应位为:,如果通道想第个转换,则写即可。具体使用多少个通道,由的位决定,最多个通道。
图 03 规则序列寄存器
注入序列寄存器只有一个,最多支持个通道,具体多少个由的决定。如果的值小于的话,则跟决定转换顺序的设置不一样,第一次转换的不是,而是,(),跟刚好相反。如果(个转换),那么转换的顺序是从开始,而不是从开始,这个要注意,编程的时候不要搞错。当等于时,跟一样。
图 04 注入序列寄存器
4.&&&&④触发源
通道选好了,转换的顺序也设置好了,那接下来就该开始转换了。转换可以由控制寄存器的这个位来控制,写的时候开始转换,写的时候停止转换,这个是最简单也是最好理解的开启转换的控制方式,理解起来没啥技术含量。
除了这种庶民式的控制方法,还支持外部事件触发转换,这个触发包括内部定时器触发和外部触发。触发源有很多,具体选择哪一种触发源,由控制寄存器的和位来控制。用于选择规则通道的触发源,用于选择注入通道的触发源。选定好触发源之后,触发源是否要激活,则由控制寄存器的和这两位来激活。
如果使能了外部触发事件,我们还可以通过设置控制寄存器的和来控制触发极性,可以有种状态,分别是:禁止触发检测、上升沿检测、下降沿检测以及上升沿和下降沿均检测。
5.&&&&⑤转换时间
输入时钟由经过分频产生,最大值是,典型值为,分频因子由通用控制寄存器的设置,可设置的分频系数有、、和,注意这里没有分频。对于我们一般设置。所以程序一般使用分频或者分频。
需要若干个周期完成对输入的电压进行采样,采样的周期数可通过采样时间寄存器和中的位设置,控制的是通道,控制的是通道。每个通道可以分别用不同的时间采样。其中采样周期最小是个,即如果我们要达到最快的采样,那么应该设置采样周期为个周期,这里说的周期就是。
的总转换时间跟的输入时钟和采样时间有关,公式为:
Tconv = 采样时间 + 12个周期
当,即为,时钟为分频,采样时间设置为个周期,那么总的转换时为:个周期。
一般我们设置,经过预分频器能分频到最大的时钟只能是,采样周期设置为个周期,算出最短的转换时间为,这个才是最常用的。
6.&&&&⑥数据寄存器
一切准备就绪后,转换后的数据根据转换组的不同,规则组的数据放在寄存器,注入组的数据放在。如果是使用双重或者三重模式那规矩组的数据是存放在通用规矩寄存器内的。
规则数据寄存器ADC_DR
规则组数据寄存器只有一个,是一个位的寄存器,只有低位有效并且只是用于独立模式存放转换完成数据。因为的最大精度是位,是位有效,这样允许存放数据时候选择左对齐或者右对齐,具体是以哪一种方式存放,由的位设置。假如设置精度为位,如果设置数据为左对齐,那转换完成数据存放在寄存器的位内;如果为右对齐,则存放在寄存器的位内。
规则通道可以有个这么多,可规则数据寄存器只有一个,如果使用多通道转换,那转换的数据就全部都挤在了里面,前一个时间点转换的通道数据,就会被下一个时间点的另外一个通道转换的数据覆盖掉,所以当通道转换完成后就应该把数据取走,或者开启模式,把数据传输到内存里面,不然就会造成数据的覆盖。最常用的做法就是开启传输。
如果没有使用传输,我们一般都需要使用状态寄存器获取当前转换的进度状态,进而进行程序控制。
注入数据寄存器ADC_JDRx
注入组最多有个通道,刚好注入数据寄存器也有个,每个通道对应着自己的寄存器,不会跟规则寄存器那样产生数据覆盖的问题。是位的,低位有效,高位保留,数据同样分为左对齐和右对齐,具体是以哪一种方式存放,由的位设置。
通用规则数据寄存器ADC_CDR
规则数据寄存器是仅适用于独立模式的,而通用规则数据寄存器是适用于双重和三重模式的。独立模式就是仅仅适用三个的其中一个,双重模式就是同时使用和,而三重模式就是三个同时使用。在双重或者三重模式下一般需要配合数据传输使用。
7.&&&&⑦中断
转换结束中断
数据转换结束后,可以产生中断,中断分为四种:规则通道转换结束中断,注入转换通道转换结束中断,模拟看门狗中断和溢出中断。其中转换结束中断很好理解,跟我们平时接触的中断一样,有相应的中断标志位和中断使能位,我们还可以根据中断类型写相应配套的中断服务程序。
模拟看门狗中断
当被转换的模拟电压低于低阈值或者高于高阈值时,就会产生中断,前提是我们开启了模拟看门狗中断,其中低阈值和高阈值由和设置。例如我们设置高阈值是,那么模拟电压超过的时候,就会产生模拟看门狗中断,反之低阈值也一样。
如果发生传输数据丢失,会置位状态寄存器的位,如果同时使能了溢出中断,那在转换结束后会产生一个溢出中断。
规则和注入通道转换结束后,除了产生中断外,还可以产生请求,把转换好的数据直接存储在内存里面。对于独立模式的多通道转换使用传输非常有必须要,程序编程简化了很多。对于双重或三重模式使用传输几乎可以说是必要的。有关请求需要配合《中文参考手册》控制器这一章节来学习。一般我们在使用的时候都会开启传输。
8.&&&&⑧电压转换
模拟电压经过转换后,是一个相对精度的数字值,如果通过串口以进制打印出来的话,可读性比较差,那么有时候我们就需要把数字电压转换成模拟电压,也可以跟实际的模拟电压(用万用表测)对比,看看转换是否准确。
我们一般在设计原理图的时候会把的输入电压范围设定在:,如果设置为位的,那么位满量程对应的就是,位满量程对应的数字值是:。数值对应的就是。如果转换后的数值为,对应的模拟电压为,那么会有这么一个等式成立:,。
30.3 ADC初始化结构体详解
标准库函数对每个外设都建立了一个初始化结构体为外设名称,结构体成员用于设置外设工作参数,并由标准库函数调用这些设定参数进入设置外设相应的寄存器,达到配置外设工作环境的目的。
结构体和库函数配合使用是标准库精髓所在,理解了结构体每个成员意义基本上就可以对该外设运用自如了。结构体定义在文件中,库函数定义在文件中,编程时我们可以结合这两个文件内注释使用。
ADC_InitTypeDef结构体
ADC_InitTypeDef结构体定义在stm32f4xx_adc.h文件内,具体定义如下:
1 typedef struct {
uint32_t ADC_R //ADC分辨率选择
FunctionalState ADC_ScanConvM //ADC扫描选择
FunctionalState ADC_ContinuousConvM //ADC连续转换模式选择
5 uint32_t ADC_ExternalTrigConvE //ADC外部触发极性
uint32_t ADC_ExternalTrigC //ADC外部触发选择
uint32_t ADC_DataA //输出数据对齐方式
uint8_t ADC_NbrOfC //转换通道数目
9 } ADC_InitTypeD
:配置的分辨率,可选的分辨率有位、位、位和位。分辨率越高,转换数据精度越高,转换时间也越长;分辨率越低,转换数据精度越低,转换时间也越短。
:可选参数为和,配置是否使用扫描。如果是单通道转换使用,如果是多通道转换使用。
:可选参数为和,配置是启动自动连续转换还是单次转换。使用配置为使能自动连续转换;使用配置为单次转换,转换一次后停止需要手动控制才重新启动转换。
:外部触发极性选择,如果使用外部触发,可以选择触发的极性,可选有禁止触发检测、上升沿触发检测、下降沿触发检测以及上升沿和下降沿均可触发检测。
:外部触发选择,图中列举了很多外部触发条件,可根据项目需求配置触发来源。实际上,我们一般使用软件自动触发。
:转换结果数据对齐模式,可选右对齐或者左对齐。一般我们选择右对齐模式。
:转换通道数目。
ADC_CommonInitTypeDef结构体
ADC除了有ADC_InitTypeDef初始化结构体外,还有一个ADC_CommonInitTypeDef通用初始化结构体。ADC_CommonInitTypeDef结构体内容决定三个ADC共用的工作环境,比如模式选择、ADC时钟等等。
ADC_CommonInitTypeDef结构体也是定义在stm32_f4xx.h文件中,具体定义如下:
1 typedef struct {
uint32_t ADC_M //ADC模式选择
uint32_t ADC_P //ADC分频系数
uint32_t ADC_DMAAccessM //DMA模式配置
uint32_t ADC_TwoSamplingD //采样延迟
6 } ADC_InitTypeD
:工作模式选择,有独立模式、双重模式以及三重模式。
:时钟分频系数选择,时钟是有分频而来,分频系数决定时钟频率,可选的分频系数为、、和。最大时钟配置为。
:模式设置,只有在双重或者三重模式才需要设置,可以设置三种模式,具体可参考参考手册说明。
ADC_TwoSamplingDelay:2个采样阶段之前的延迟,仅适用于双重或三重交错模式。
30.4 独立模式单通道采集实验
的功能繁多,我们设计三个实验尽量完整的展示的功能。首先是比较基础实用的单通道采集,实现开发板上电位器的动触点输出引脚电压的采集并通过串口打印至端串口调试助手。单通道采集适用转换完成中断,在中断服务函数中读取数据,不使用传输,在多通道采集时才使用传输。
30.4.1 硬件设计
开发板板载一个贴片滑动变阻器,电路设计见图 05。
图 05 开发板电位器部分原理图
贴片滑动变阻器的动触点通过连接至芯片的通道引脚。当我们使用旋转滑动变阻器调节旋钮时,其动触点电压也会随之改变,电压变化范围为,亦是开发板默认的电压采集范围。
30.4.2 软件设计
这里只讲解核心的部分代码,有些变量的设置,头文件的包含等并没有涉及到,完整的代码请参考本章配套的工程。
我们编写两个驱动文件,和,用来存放所用引脚的初始化函数以及配置相关函数。
1.&&&&编程要点
1)&&&&初始化配置ADC目标引脚为模拟输入模式;
2)&&&&使能ADC时钟;
3)&&&&配置通用ADC为独立模式,采样4分频;
4)&&&&设置目标ADC为12位分辨率,1通道的连续转换,不需要外部触发;
5)&&&&设置ADC转换通道顺序及采样时间;
6)&&&&配置使能ADC转换完成中断,在中断内读取转换完数据;
7)&&&&启动ADC转换;
8)&&&&使能软件触发ADC转换。
ADC转换结果数据使用中断方式读取,这里没有使用DMA进行数据传输。
2.&&&&代码分析
代码清单 01 ADC宏定义
1 #define Rheostat_ADC_IRQ ADC_IRQn
2 #define Rheostat_ADC_INT_FUNCTION ADC_IRQHandler
4 #define RHEOSTAT_ADC_GPIO_PORT GPIOC
5 #define RHEOSTAT_ADC_GPIO_PIN GPIO_Pin_3
6 #define RHEOSTAT_ADC_GPIO_CLK RCC_AHB1Periph_GPIOC
8 #define RHEOSTAT_ADC ADC1
9 #define RHEOSTAT_ADC_CLK RCC_APB2Periph_ADC1
10 #define RHEOSTAT_ADC_CHANNEL ADC_Channel_13
使用宏定义引脚信息方便硬件电路改动时程序移植。
ADC GPIO初始化函数
代码清单 02 ADC GPIO初始化
1 static void Rheostat_ADC_GPIO_Config(void)
GPIO_InitTypeDef GPIO_InitS
// 使能 GPIO 时钟
RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_GPIO_CLK, ENABLE);
// 配置 IO
GPIO_InitStructure.GPIO_Pin = RHEOSTAT_ADC_GPIO_PIN;
// 配置为模拟输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
// 不上拉不下拉
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(RHEOSTAT_ADC_GPIO_PORT, &GPIO_InitStructure);
使用到时候都必须开启对应的时钟,用于转换功能必须配置为模拟输入模式。
配置ADC工作模式
代码清单 03 ADC工作模式配置
1 static void Rheostat_ADC_Mode_Config(void)
ADC_InitTypeDef ADC_InitS
ADC_CommonInitTypeDef ADC_CommonInitS
// 开启ADC时钟
RCC_APB2PeriphClockCmd(RHEOSTAT_ADC_CLK , ENABLE);
// -------------------ADC Common 结构体参数初始化--------------------
// 独立ADC模式
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_I
// 时钟为fpclk x分频
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
// 禁止DMA直接访问模式
ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_D
// 采样时间间隔
ADC_CommonInitStructure.ADC_TwoSamplingDelay=
ADC_TwoSamplingDelay_10C
ADC_CommonInit(&ADC_CommonInitStructure);
// -------------------ADC Init 结构体参数初始化---------------------
// ADC 分辨率
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
// 禁止扫描模式,多通道采集才需要
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
// 连续转换
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
//禁止外部边沿触发
ADC_InitStructure.ADC_ExternalTrigConvEdge =
ADC_ExternalTrigConvEdge_N
//使用软件触发,外部触发不用配置,注释掉即可
//ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T1_CC1;
//数据右对齐
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_R
//转换通道 1个
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(RHEOSTAT_ADC, &ADC_InitStructure);
//------------------------------------------------------------------
// 配置 ADC 通道转换顺序为1,第一个转换,采样时间为56个时钟周期
ADC_RegularChannelConfig(RHEOSTAT_ADC, RHEOSTAT_ADC_CHANNEL,
1, ADC_SampleTime_56Cycles);
// ADC 转换结束产生中断,在中断服务程序中读取转换值
ADC_ITConfig(RHEOSTAT_ADC, ADC_IT_EOC, ENABLE);
// 使能ADC
ADC_Cmd(RHEOSTAT_ADC, ENABLE);
//开始adc转换,软件触发
ADC_SoftwareStartConv(RHEOSTAT_ADC);
首先,使用和结构体分别定义一个初始化和通用类型变量,这两个结构体我们之前已经有详细讲解。
我们调用开启时钟。
接下来我们使用结构体变量来配置为独立模式、分频系数为、不需要设置模式、个周期的采样延迟,并调用函数完成通用工作环境配置。
我们使用结构体变量来配置为位分辨率、单通道采集不需要扫描、启动连续转换、使用内部软件触发无需外部触发事件、使用右对齐数据格式、转换通道为,并调用函数完成工作环境配置。
函数用来绑定通道转换顺序和时间。它接收个形参,第一个形参选择外设,可为、或;第二个形参通道选择,总共可选个通道;第三个形参为转换顺序,可选为到;第四个形参为采样周期选择,采样周期越短,转换数据输出周期就越短但数据精度也越低,采样周期越长,转换数据输出周期就越长同时数据精度越高。对应通道,这里我们选择即周期的采样时间。
利用转换完成中断可以非常方便的保证我们读取到的数据是转换完成后的数据而不用担心该数据可能是正在转换时"不稳定"的数据。我们使用函数使能转换完成中断,并在中断服务函数中读取转换结果数据。
函数控制转换启动和停止。
最后,如果使用软件触发需要调用函数进行使能配置。
ADC中断配置
代码清单 04 ADC中断配置
1 static void Rheostat_ADC_NVIC_Config(void)
NVIC_InitTypeDef NVIC_InitS
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = Rheostat_ADC_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
在Rheostat_ADC_NVIC_Config函数中我们配置了ADC转换完成中断,使用中断同时需要配置中断源和中断优先级。
ADC中断服务函数
代码清单 05 ADC中断服务函数
1 void ADC_IRQHandler(void)
if (ADC_GetITStatus(RHEOSTAT_ADC,ADC_IT_EOC)==SET) {
// 读取ADC的转换值
ADC_ConvertedValue = ADC_GetConversionValue(RHEOSTAT_ADC);
ADC_ClearITPendingBit(RHEOSTAT_ADC,ADC_IT_EOC);
中断服务函数一般定义在文件内,我们只使能了转换完成中断,在转换完成后就会进入中断服务函数,我们在中断服务函数内直接读取转换结果保存在变量在中定义中。
函数是获取转换结果值的库函数,只有一个形参为外设,可选为、或,该函数还返回一个位的转换结果值。
代码清单 06 主函数
1 int main(void)
/*初始化USART1*/
Debug_USART_Config();
/* 初始化滑动变阻器用到的DAC,ADC采集完成会产生ADC中断,
7 在stm32f4xx_it.c文件中的中断服务函数更新ADC_ConvertedValue的值 */
Rheostat_Init();
printf("\r\n ----这是一个ADC实验(NO DMA传输)----\r\n");
while (1) {
Delay(0xffffee);
printf("\r\n The current AD value = 0x%04X \r\n",
ADC_ConvertedValue);
printf("\r\n The current AD value = %f V \r\n",ADC_Vol);
ADC_Vol =(float)(ADC_ConvertedValue*3.3/4096); // 读取转换的AD值
主函数先调用函数配置调试串口相关参数,函数定义在文件中。
接下来调用函数进行初始化配置并启动。函数是定义在文件中,它只是简单的分别调用、和。
函数只是一个简单的延时函数。
在中断服务函数中我们把转换结果保存在变量中,根据我们之前的分析可以非常清楚的计算出对应的电位器动触点的电压值。
最后就是把相关数据打印至串口调试助手。
30.4.3 下载验证
用线连接开发板""接口跟电脑,在电脑端打开串口调试助手,把编译好的程序下载到开发板。在串口调试助手可看到不断有数据从开发板传输过来,此时我们旋转电位器改变其电阻值,那么对应的数据也会有变化。
30.5 独立模式多通道采集实验
30.5.1 硬件设计
开发板已通过排针接口把部分通道引脚引出,我们可以根据需要选择使用。实际使用时候必须注意保存引脚是单独使用的,不可能与其他模块电路共用同一引脚。
30.5.2 软件设计
这里只讲解核心的部分代码,有些变量的设置,头文件的包含等并没有涉及到,完整的代码请参考本章配套的工程。
跟单通道例程一样,我们编写两个驱动文件,和,用来存放所用引脚的初始化函数以及配置相关函数,实际上这两个文件跟单通道实验的文件是非常相似的。
1.&&&&编程要点
1)&&&&初始化配置ADC目标引脚为模拟输入模式;
2)&&&&使能ADC时钟和DMA时钟;
3)&&&&配置DMA从ADC规矩数据寄存器传输数据到我们指定的存储区;
4)&&&&配置通用ADC为独立模式,采样4分频;
5)&&&&设置ADC为12位分辨率,启动扫描,连续转换,不需要外部触发;
6)&&&&设置ADC转换通道顺序及采样时间;
7)&&&&使能DMA请求,DMA在AD转换完自动传输数据到指定的存储区;
8)&&&&启动ADC转换;
9)&&&&使能软件触发ADC转换。
转换结果数据使用方式传输至指定的存储区,这样取代单通道实验使用中断服务的读取方法。实际上,多通道采集一般使用数据传输方式更加高效方便。
2.&&&&代码分析
代码清单 07 多通道ADC相关宏定义
1 //转换的通道个数
2 #define RHEOSTAT_NOFCHANEL 4
4 #define RHEOSTAT_ADC_DR_ADDR ((u32)ADC3+0x4c)
5 #define RHEOSTAT_ADC_GPIO_PORT GPIOF
6 #define RHEOSTAT_ADC_GPIO_CLK RCC_AHB1Periph_GPIOF
7 #define RHEOSTAT_ADC ADC3
8 #define RHEOSTAT_ADC_CLK RCC_APB2Periph_ADC3
10 #define RHEOSTAT_ADC_GPIO_PIN1 GPIO_Pin_6
11 #define RHEOSTAT_ADC_CHANNEL1 ADC_Channel_4
13 #define RHEOSTAT_ADC_GPIO_PIN2 GPIO_Pin_7
14 #define RHEOSTAT_ADC_CHANNEL2 ADC_Channel_5
16 #define RHEOSTAT_ADC_GPIO_PIN3 GPIO_Pin_8
17 #define RHEOSTAT_ADC_CHANNEL3 ADC_Channel_6
19 #define RHEOSTAT_ADC_GPIO_PIN4 GPIO_Pin_9
20 #define RHEOSTAT_ADC_CHANNEL4 ADC_Channel_7
22 // DMA2 数据流0 通道2
23 #define RHEOSTAT_ADC_DMA_CLK RCC_AHB1Periph_DMA2
24 #define RHEOSTAT_ADC_DMA_CHANNEL DMA_Channel_2
25 #define RHEOSTAT_ADC_DMA_STREAM DMA2_Stream0
定义个通道进行多通道实验,并且定义相关配置。
ADC GPIO初始化函数
代码清单 08 ADC GPIO初始化
1 static void Rheostat_ADC_GPIO_Config(void)
GPIO_InitTypeDef GPIO_InitS
// 使能 GPIO 时钟
RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_GPIO_CLK, ENABLE);
// 配置 IO
GPIO_InitStructure.GPIO_Pin = RHEOSTAT_ADC_GPIO_PIN1 |
RHEOSTAT_ADC_GPIO_PIN2 |
RHEOSTAT_ADC_GPIO_PIN3 |
RHEOSTAT_ADC_GPIO_PIN4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; //不上拉不下拉
GPIO_Init(RHEOSTAT_ADC_GPIO_PORT, &GPIO_InitStructure);
使用到GPIO时候都必须开启对应的GPIO时钟,GPIO用于AD转换功能必须配置为模拟输入模式。
配置ADC工作模式
代码清单 09 ADC工作模式配置
1 static void Rheostat_ADC_Mode_Config(void)
DMA_InitTypeDef DMA_InitS
ADC_InitTypeDef ADC_InitS
ADC_CommonInitTypeDef ADC_CommonInitS
// 开启ADC时钟
RCC_APB2PeriphClockCmd(RHEOSTAT_ADC_CLK , ENABLE);
// 开启DMA时钟
RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_DMA_CLK, ENABLE);
// ------------------DMA Init 结构体参数初始化------------------------
// 选择 DMA 通道,通道存在于数据流中
DMA_InitStructure.DMA_Channel = RHEOSTAT_ADC_DMA_CHANNEL;
// 外设基址为:ADC 数据寄存器地址
DMA_InitStructure.DMA_PeripheralBaseAddr = RHEOSTAT_ADC_DR_ADDR;
// 存储器地址
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ADC_ConvertedV
// 数据传输方向为外设到存储器
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToM
// 缓冲区大小,指一次传输的数据项
DMA_InitStructure.DMA_BufferSize = RHEOSTAT_NOFCHANEL;
// 外设寄存器只有一个,地址不用递增
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_D
// 存储器地址递增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E
//DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_D
// // 外设数据大小为半字,即两个字节
DMA_InitStructure.DMA_PeripheralDataSize =
DMA_PeripheralDataSize_HalfW
// 存储器数据大小也为半字,跟外设数据大小相同
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfW
// 循环传输模式
DMA_InitStructure.DMA_Mode = DMA_Mode_C
// DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
DMA_InitStructure.DMA_Priority = DMA_Priority_H
// 禁止DMA FIFO ,使用直连模式
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_D
// FIFO 阈值大小,FIFO模式禁止时,这个不用配置
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfF
// 存储器突发单次传输
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_S
// 外设突发单次传输
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_S
//初始化DMA数据流,流相当于一个大的管道,管道里面有很多通道
DMA_Init(RHEOSTAT_ADC_DMA_STREAM, &DMA_InitStructure);
// 使能DMA数据流
DMA_Cmd(RHEOSTAT_ADC_DMA_STREAM, ENABLE);
// -------------------ADC Common 结构体参数初始化--------------------
// 独立ADC模式
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_I
// 时钟为fpclk x分频
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
// 禁止DMA直接访问模式
ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_D
// 采样时间间隔
ADC_CommonInitStructure.ADC_TwoSamplingDelay =
ADC_TwoSamplingDelay_10C
ADC_CommonInit(&ADC_CommonInitStructure);
// -------------------ADC Init 结构体参数初始化---------------------
// ADC 分辨率
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
// 开启扫描模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
// 连续转换
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
//禁止外部边沿触发
ADC_InitStructure.ADC_ExternalTrigConvEdge =
ADC_ExternalTrigConvEdge_N
//使用软件触发,外部触发不用配置,注释掉即可
//ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T1_CC1;
//数据右对齐
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_R
//转换通道 x个
ADC_InitStructure.ADC_NbrOfConversion = RHEOSTAT_NOFCHANEL;
ADC_Init(RHEOSTAT_ADC, &ADC_InitStructure);
//------------------------------------------------------------------
// 配置 ADC 通道转换顺序和采样时间周期
ADC_RegularChannelConfig(RHEOSTAT_ADC, RHEOSTAT_ADC_CHANNEL1,
1, ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(RHEOSTAT_ADC, RHEOSTAT_ADC_CHANNEL2,
2, ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(RHEOSTAT_ADC, RHEOSTAT_ADC_CHANNEL3,
3, ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(RHEOSTAT_ADC, RHEOSTAT_ADC_CHANNEL4,
4, ADC_SampleTime_56Cycles);
// 使能DMA请求 after last transfer (Single-ADC mode)
ADC_DMARequestAfterLastTransferCmd(RHEOSTAT_ADC, ENABLE);
// 使能ADC DMA
ADC_DMACmd(RHEOSTAT_ADC, ENABLE);
// 使能ADC
ADC_Cmd(RHEOSTAT_ADC, ENABLE);
//开始adc转换,软件触发
ADC_SoftwareStartConv(RHEOSTAT_ADC);
首先,我们使用了定义了一个初始化类型变量,该结构体内容我们在篇已经做了非常详细的讲解;另外还使用和结构体分别定义一个初始化和通用类型变量,这两个结构体我们之前已经有详细讲解。
调用开启时钟以及开启时钟。
我们需要对进行必要的配置。首先设置外设基地址就是的规则数据寄存器地址;存储器的地址就是我们指定的数据存储区空间,是我们定义的一个全局数组名,它是一个无符号位含有个元素的整数数组;规则转换对应只有一个数据寄存器所以地址不能递增,而我们定义的存储区是专门用来存放不同通道数据的,所以需要自动地址递增。的规则数据寄存器只有低位有效,实际存放的数据只有位而已,所以设置数据大小为半字大小。配置为连续转换模式也设置为循环传输模式。设置好相关参数后就使能的通道。
接下来我们使用结构体变量来配置为独立模式、分频系数为、不需要设置模式、个周期的采样延迟,并调用函数完成通用工作环境配置。
我们使用结构体变量来配置为位分辨率、使能扫描模式、启动连续转换、使用内部软件触发无需外部触发事件、使用右对齐数据格式、转换通道为,并调用函数完成工作环境配置。
函数用来绑定通道转换顺序和采样时间。分别绑定四个通道引脚并设置相应的转换顺序。
函数控制是否使能的请求,如果使能请求,并调用函数使能,则在转换完成后就请求实现数据传输。
函数控制转换启动和停止。
最后,如果使用软件触发需要调用函数进行使能配置。
代码清单 010 主函数
1 int main(void)
/*初始化USART1*/
Debug_USART_Config();
/* 初始化滑动变阻器用到的DAC
7 ,ADC数据采集完成后直接由DMA运输数据到ADC_ConvertedValue变量
DMA直接改变ADC_ConvertedValue的值*/
Rheostat_Init();
printf("\r\n ----这是一个ADC实验(多通道采集)----\r\n");
while (1) {
Delay(0xffffff);
ADC_ConvertedValueLocal[0]=(float)(ADC_ConvertedValue[0]*3.3/4096);
ADC_ConvertedValueLocal[1]=(float)(ADC_ConvertedValue[1]*3.3/4096);
ADC_ConvertedValueLocal[2]=(float)(ADC_ConvertedValue[2]*3.3/4096);
ADC_ConvertedValueLocal[3]=(float)(ADC_ConvertedValue[3]*3.3/4096);
printf("\r\n CH1_PF6 value = %fV\r\n",ADC_ConvertedValueLocal[0]);
printf("\r\n CH2_PF7 value = %fV\r\n",ADC_ConvertedValueLocal[1]);
printf("\r\n CH3_PF8 value = %fV\r\n",ADC_ConvertedValueLocal[2]);
printf("\r\n CH4_PF9 value = %fV\r\n",ADC_ConvertedValueLocal[3]);
printf("\r\n");
主函数先调用USARTx_Config函数配置调试串口相关参数,函数定义在bsp_debug_usart.c文件中。
接下来调用Rheostat_Init函数进行ADC初始化配置并启动ADC。Rheostat_Init函数是定义在bsp_adc.c文件中,它只是简单的分别调用Rheostat_ADC_GPIO_Config()和Rheostat_ADC_Mode_Config ()。
Delay函数只是一个简单的延时函数。
我们配置了DMA数据传输所以它会自动把ADC转换完成后数据保存到数组ADC_ConvertedValue内,我们只要直接使用数组就可以了。经过简单地计算就可以得到每个通道对应的实际电压。
最后就是把相关数据打印至串口调试助手。
30.5.3 下载验证
将待测电压通过杜邦线接在对应引脚上,用线连接开发板""接口跟电脑,在电脑端打开串口调试助手,把编译好的程序下载到开发板。在串口调试助手可看到不断有数据从开发板传输过来,此时我们改变输入电压值,那么对应的数据也会有变化。
30.6 三重ADC交替模式采集实验
转换包括采样阶段和转换阶段,在采样阶段才对通道数据进行采集;而在转换阶段只是将采集到的数据进行转换为数字量输出,此刻通道数据变化不会改变转换结果。独立模式的采集需要在一个通道采集并且转换完成后才会进行下一个通道的采集。双重或者三重的机制使用两个或以上同时采样两个或以上不同通道的数据或者使用两个或以上交叉采集同一通道的数据。双重或者三重模式较独立模式一个最大的优势就是转换速度快。
我们这里只介绍三重交替模式,关于双重或者三重的其他模式与之类似,可以参考三重交替模式使用。三重交替模式是针对同一通道的使用三个交叉采集,就是在采样完等几个时钟周期后开始采样,此时处在转换阶段,当采样完成再等几个时钟周期后就进行采样此时和处在转换阶段,如果采样完成并且已经转换完成那么就可以准备下一轮的循环,这样充分利用转换阶段时间达到增快采样速度的效果。转换过程见图,利用的转换阶段时间另外一个进行采样,而不用像独立模式必须等待采样和转换结束后才进行下一次采样及转换。
图 06 三重ADC交叉模式
30.6.1 硬件设计
三重交叉模式是针对同一个通道的采集模式,这种情况跟小节的单通道实验非常类似,只是同时使用三个对同一通道进行采集,所以电路设计与之相同即可,具体可参考图。
30.6.2 软件设计
这里只讲解核心的部分代码,有些变量的设置,头文件的包含等并没有涉及到,完整的代码请参考本章配套的工程。
跟单通道例程一样,我们编写两个驱动文件,和,用来存放所用引脚的初始化函数以及配置相关函数,实际上这两个文件跟单通道实验的文件非常相似。
1.&&&&编程要点
1)&&&&初始化配置ADC目标引脚为模拟输入模式;
2)&&&&使能ADC1、ADC2、ADC3以及DMA时钟;
3)&&&&配置DMA控制将ADC通用规矩数据寄存器数据转存到指定存储区;
4)&&&&配置通用ADC为三重ADC交替模式,采样4分频,使用DMA模式2;
5)&&&&设置ADC1、ADC2和ADC3为12位分辨率,禁用扫描,连续转换,不需要外部触发;
6)&&&&设置ADC1、ADC2和ADC3转换通道顺序及采样时间;
7)&&&&使能ADC1的 DMA请求,在ADC转换完后自动请求DMA进行数据传输;
8)&&&&启动ADC1、ADC2和ADC3转换;
9)&&&&使能软件触发ADC转换。
ADC转换结果数据使用DMA方式传输至指定的存储区,这样取代单通道实验使用中断服务的读取方法。
2.&&&&代码分析
代码清单 011 多通道ADC相关宏定义
1 #define RHEOSTAT_ADC_CDR_ADDR ((uint32_t)0x)
3 #define RHEOSTAT_ADC_GPIO_PORT GPIOC
4 #define RHEOSTAT_ADC_GPIO_PIN GPIO_Pin_3
5 #define RHEOSTAT_ADC_GPIO_CLK RCC_AHB1Periph_GPIOC
7 #define RHEOSTAT_ADC1 ADC1
8 #define RHEOSTAT_ADC1_CLK RCC_APB2Periph_ADC1
9 #define RHEOSTAT_ADC2 ADC2
10 #define RHEOSTAT_ADC2_CLK RCC_APB2Periph_ADC2
11 #define RHEOSTAT_ADC3 ADC3
12 #define RHEOSTAT_ADC3_CLK RCC_APB2Periph_ADC3
13 #define RHEOSTAT_ADC_CHANNEL ADC_Channel_13
15 #define RHEOSTAT_ADC_DMA_CLK RCC_AHB1Periph_DMA2
16 #define RHEOSTAT_ADC_DMA_CHANNEL DMA_Channel_0
17 #define RHEOSTAT_ADC_DMA_STREAM DMA2_Stream0
双重或者三重ADC需要使用通用规则数据寄存器ADC_CDR,这点跟独立模式不同。定义电位器动触点引脚作为三重ADC的模拟输入。
ADC GPIO初始化函数
代码清单 012 ADC GPIO初始化
1 static void Rheostat_ADC_GPIO_Config(void)
GPIO_InitTypeDef GPIO_InitS
// 使能 GPIO 时钟
RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_GPIO_CLK, ENABLE);
// 配置 IO
GPIO_InitStructure.GPIO_Pin = RHEOSTAT_ADC_GPIO_PIN;
// 配置为模拟输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
// 不上拉不下拉
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(RHEOSTAT_ADC_GPIO_PORT, &GPIO_InitStructure);
使用到时候都必须开启对应的时钟,用于转换功能必须配置为模拟输入模式。
配置三重ADC交替模式
代码清单 013 三重ADC交替模式配置
1 static void Rheostat_ADC_Mode_Config(void)
DMA_InitTypeDef DMA_InitS
ADC_InitTypeDef ADC_InitS
ADC_CommonInitTypeDef ADC_CommonInitS
// 开启ADC时钟
RCC_APB2PeriphClockCmd(RHEOSTAT_ADC1_CLK , ENABLE);
RCC_APB2PeriphClockCmd(RHEOSTAT_ADC2_CLK , ENABLE);
RCC_APB2PeriphClockCmd(RHEOSTAT_ADC3_CLK , ENABLE);
// ------------------DMA Init 结构体参数初始化-----------------------
// ADC1使用DMA2,数据流0,通道0,这个是手册固定死的
// 开启DMA时钟
RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_DMA_CLK, ENABLE);
// 外设基址为:ADC 数据寄存器地址
DMA_InitStructure.DMA_PeripheralBaseAddr = RHEOSTAT_ADC_CDR_ADDR;
// 存储器地址,实际上就是一个内部SRAM的变量
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)ADC_ConvertedV
// 数据传输方向为外设到存储器
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToM
// 缓冲区大小为3,缓冲区的大小应该等于存储器的大小
DMA_InitStructure.DMA_BufferSize = 3;
// 外设寄存器只有一个,地址不用递增
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_D
// 存储器地址自动递增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E
// // 外设数据大小为字,即四个字节
DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_W
// 存储器数据大小也为字,跟外设数据大小相同
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_W
// 循环传输模式
DMA_InitStructure.DMA_Mode = DMA_Mode_C
// DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
DMA_InitStructure.DMA_Priority = DMA_Priority_H
// 禁止DMA FIFO ,使用直连模式
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_D
// FIFO 大小,FIFO模式禁止时,这个不用配置
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfF
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_S
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_S
// 选择 DMA 通道,通道存在于流中
DMA_InitStructure.DMA_Channel = RHEOSTAT_ADC_DMA_CHANNEL;
//初始化DMA流,流相当于一个大的管道,管道里面有很多通道
DMA_Init(RHEOSTAT_ADC_DMA_STREAM, &DMA_InitStructure);
// 使能DMA流
DMA_Cmd(RHEOSTAT_ADC_DMA_STREAM, ENABLE);
// -------------------ADC Common 结构体参数初始化--------------------
// 三重ADC交替模式
ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_I
// 时钟为fpclk2 4分频
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
// 禁止DMA直接访问模式
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_2;
// 采样时间间隔
ADC_CommonInitStructure.ADC_TwoSamplingDelay =
ADC_TwoSamplingDelay_10C
ADC_CommonInit(&ADC_CommonInitStructure);
// -------------------ADC Init 结构体参数初始化----------------------
// ADC 分辨率
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
// 禁止扫描模式,多通道采集才需要
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
// 连续转换
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
//禁止外部边沿触发
ADC_InitStructure.ADC_ExternalTrigConvEdge =
ADC_ExternalTrigConvEdge_N
//使用软件触发,外部触发不用配置,注释掉即可
//ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T1_CC1;
//数据右对齐
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_R
//转换通道 1个
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(RHEOSTAT_ADC1, &ADC_InitStructure);
// 配置 ADC 通道转换顺序为1,第一个转换,采样时间为3个时钟周期
ADC_RegularChannelConfig(RHEOSTAT_ADC1, RHEOSTAT_ADC_CHANNEL,
1, ADC_SampleTime_3Cycles);
//------------------------------------------------------------------
ADC_Init(RHEOSTAT_ADC2, &ADC_InitStructure);
// 配置 ADC 通道转换顺序为1,第一个转换,采样时间为3个时钟周期
ADC_RegularChannelConfig(RHEOSTAT_ADC2, RHEOSTAT_ADC_CHANNEL,
1, ADC_SampleTime_3Cycles);
//------------------------------------------------------------------
ADC_Init(RHEOSTAT_ADC3, &ADC_InitStructure);
// 配置 ADC 通道转换顺序为1,第一个转换,采样时间为3个时钟周期
ADC_RegularChannelConfig(RHEOSTAT_ADC3, RHEOSTAT_ADC_CHANNEL,
1, ADC_SampleTime_3Cycles);
// 使能DMA请求 after last transfer (multi-ADC mode)
ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
// 使能ADC DMA
ADC_DMACmd(RHEOSTAT_ADC1, ENABLE);
// 使能ADC
ADC_Cmd(RHEOSTAT_ADC1, ENABLE);
ADC_Cmd(RHEOSTAT_ADC2, ENABLE);
ADC_Cmd(RHEOSTAT_ADC3, ENABLE);
//开始adc转换,软件触发
ADC_SoftwareStartConv(RHEOSTAT_ADC1);
ADC_SoftwareStartConv(RHEOSTAT_ADC2);
ADC_SoftwareStartConv(RHEOSTAT_ADC3);
首先,我们使用了DMA_InitTypeDef定义了一个DMA初始化类型变量,该结构体内容我们在DMA篇已经做了非常详细的讲解;另外还使用ADC_InitTypeDef和ADC_CommonInitTypeDef结构体分别定义一个ADC初始化和ADC通用类型变量,这两个结构体我们之前已经有详细讲解。
调用RCC_APB2PeriphClockCmd()开启ADC时钟以及RCC_AHB1PeriphClockCmd()开启DMA时钟。
我们需要对DMA进行必要的配置。首先设置外设基地址就是ADC的通用规则数据寄存器地址;存储器的地址就是我们指定的数据存储区空间,ADC_ConvertedValue是我们定义的一个全局数组名,它是一个无符号32位有三个元素的整数数字;ADC规则转换对应只有一个数据寄存器所以地址不能递增,我们指定的存储区也需要递增地址。ADC的通用规则数据寄存器是32位有效,我们配置ADC为DMA模式2,设置数据大小为字大小。ADC配置为连续转换模式DMA也设置为循环传输模式。设置好DMA相关参数后就使能DMA的ADC通道。
接下来我们使用ADC_CommonInitTypeDef结构体变量ADC_CommonInitStructure来配置ADC为三重ADC交替模式、分频系数为4、需要设置DMA模式2、10个周期的采样延迟,并调用ADC_CommonInit函数完成ADC通用工作环境配置。
我们使用ADC_InitTypeDef结构体变量ADC_InitStructure来配置ADC1为12位分辨率、不使用扫描模式、启动连续转换、使用内部软件触发无需外部触发事件、使用右对齐数据格式、转换通道为1,并调用ADC_Init函数完成ADC1工作环境配置。ADC2和ADC3使用与ADC1相同配置即可。
ADC_RegularChannelConfig函数用来绑定ADC通道转换顺序和采样时间。绑定ADC通道引脚并设置相应的转换顺序。
ADC_MultiModeDMARequestAfterLastTransferCmd函数控制是否使能ADC的DMA请求,如果使能请求,并调用ADC_DMACmd函数使能DMA,则在ADC转换完成后就请求DMA实现数据传输。三重模式只需使能ADC1的DMA通道。
ADC_Cmd函数控制ADC转换启动和停止。
最后,如果使用软件触发需要调用ADC_SoftwareStartConvCmd函数进行使能配置。
代码清单 014 主函数
1 int main(void)
/*初始化USART1*/
Debug_USART_Config();
7 初始化滑动变阻器用到的DAC,ADC数据采集完成后直接由DMA运输数据到
ADC_ConvertedValue变量DMA直接改变ADC_ConvertedValue的值*/
Rheostat_Init();
printf("\r\n ----这是一个ADC实验(DMA传输)----\r\n");
while (1) {
Delay(0xffffee);
ADC_ConvertedValueLocal[0] =
(float)((uint16_t)ADC_ConvertedValue[0]*3.3/4096);
ADC_ConvertedValueLocal[1] =
(float)((uint16_t)ADC_ConvertedValue[2]*3.3/4096);
ADC_ConvertedValueLocal[2] =
(float)((uint16_t)ADC_ConvertedValue[1]*3.3/4096);
printf("\r\n The current AD value = 0x%08X \r\n",
ADC_ConvertedValue[0]);
printf("\r\n The current AD value = 0x%08X \r\n",
ADC_ConvertedValue[1]);
printf("\r\n The current AD value = 0x%08X \r\n",
ADC_ConvertedValue[2]);
printf("\r\n The current ADC1 value = %f V \r\n",
ADC_ConvertedValueLocal[0]);
printf("\r\n The current ADC2 value = %f V \r\n",
ADC_ConvertedValueLocal[1]);
printf("\r\n The current ADC3 value = %f V \r\n",
ADC_ConvertedValueLocal[2]);
主函数先调用函数配置调试串口相关参数,函数定义在文件中。
接下来调用函数进行初始化配置并启动。函数是定义在文件中,它只是简单的分别调用和。
函数只是一个简单的延时函数。
我们配置了数据传输所以它会自动把转换完成后数据保存到数组变量内,根据模式的数据存放规则,的低位存放数据、高位存放数据,的低位存放数据、高位存放数据,的低位存放数据、高位存放数据,我们可以根据需要提取出对应的转换结果数据。经过简单地计算就可以得到每个对应的实际电压。
最后就是把相关数据打印至串口调试助手。
30.6.3 下载验证
保证开发板相关硬件连接正确,用线连接开发板""接口跟电脑,在电脑端打开串口调试助手,把编译好的程序下载到开发板。在串口调试助手可看到不断有数据从开发板传输过来,此时我们旋转电位器改变其电阻值,那么对应的数据也会有变化。
30.7 每课一问
1、如果设置ADC分辨率为6、8或者10位时,输入电压值如何计算?
2、根据独立模式单通道采集实验设计实现相同功能,要求使用外部硬件触发转换方式。
3、编写一个双重ADC交替模式程序,实现类似三重ADC交替模式实验功能,要求使用DMA模式2实现程序功能。
阅读(...) 评论()

我要回帖

更多关于 stm32adc通道引脚 的文章

 

随机推荐