Ⅰ、概述

上一篇文章讲述的内容是:三通道逐次转换(单次、单通道软件触发),也就是说3条通道要三次软件触发才能完成转换,而且是通过软件读取转换数值。

本文讲述三通道DMA连续转换(3通道、软件单次触发),也就是说3条通道只需要一次软件触发就能完成转换,使用DMA保存在数值。

上一篇文章实例是使用间断模式单次触发单条通道采集,本文是使用DMA模式单次触发三条通道采集。使用DMA传输的好处就是效率很高,我们直接读取转换的结果就是了,比如想做的示波器实例就是要求效率很高。

实例实验效果:

本文的实验效果和上一篇文章一样,只是实现的方式不一样

通道1接地、通道2接1.5V电源、通道3接VCC

上一篇文章内容:

ADC三通道逐次转换(单次、单通道软件触发)

本文讲述的知识点相对较多,若初次学习STM32的ADC转换功能,可以参考我另外一篇相对简单一点的文章:

STM32F10x_ADC1单通道单次采集

关于本文的更多详情请往下看。

Ⅱ、实例工程下载

笔者针对于初学者提供的例程都是去掉了许多不必要的功能,精简了官方的代码,对初学者一看就明白,以简单明了的工程供大家学习。

笔者提供的实例工程都是在板子上经过多次测试并没有问题才上传至360云盘,欢迎下载测试、参照学习。

提供下载的软件工程是基于Keil(MDK-ARM) V5版本、STM32F103ZE芯片,但F1其他型号也适用(适用F1其他型号: 关注微信,回复“修改型号”)。

STM32F10x_ADC三通道DMA连续转换(3通道、软件单次触发)实例源代码工程:

https://yunpan.cn/cBCmnZ58mI3Pp  访问密码

STM32F1资料:

https://yunpan.cn/crBUdUGdYKam2  访问密码 ca90

Ⅲ、关于ADC

关于ADC的介绍及功能,请下载参考手册查看,笔者这里讲述几点重要的知识:

1.12位分辨率

在STM32所有系列芯片中只有少部分是16位的,如:F373芯片。

12位分辨率意味着我们采集电压的精度可以达到:Vref /4096。

采集电压 = Vref * ADC_DR / 4096;

Vref:参考电压

ADC_DR:读取到ADC数据寄存器的值

由于寄存器是32位的,在配置的时候分左对齐和右对齐,一般我们使用右对齐,也就是对低12位数据为有效数据。

2.转换模式

A.单次和连续转换

单次:单通道单次转换、多通道单次(分多次)转换;

连续:单通道连续转换、多通道连续(循环)转换;

B.双ADC模式

也就是使用到了两个ADC,比如:ADC1和ADC2同时使用也就是双ADC模式。在该模式下可以配置为如下一些模式:同步规则模式、同步注入模式、独立模式等。

3.触发源

触发源就是触发ADC转换的来源,有外部中断线、定时器、软件等触发源。我们初学者常用软件触发,也就是需要转换一次,我们软件启动一次(本文提供实例也是软件触发)。

 

 

Ⅳ、本文实例描述

本文实例中关于ADC部分的配置及知识点,针对初学者相对比较多、理解起来也相对比较难一点。

根据题目“ADC三通道逐次转换(单次、单通道软件触发)”我们不难理解其转换的过程,但如何实现是一个难点。

1、三通道:我们定义了3条通道ADC1的ADC_Channel_1、ADC_Channel_2、ADC_Channel_3.

2.逐次转换:我们使用的是间断模式(规则组),也就是在规则组中定义了触发转换的序列。

3.单次:我们是每触发一次转换一次。

4.单通道:每次触发只转换一条通道。

以简单的示意图来说明其原理:

实例总共有三条通道通道1、通道2、通道3,分别对应顺序,是1、2、3。我们是通过软件来定义的顺序:

ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);

ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_55Cycles5);

ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_55Cycles5);

所以,我们转换保存的顺序:ADC_Buf[0]是通道1的数据、ADC_Buf[1]是通道2的数据、ADC_Buf[2]是通道3的数据

也是按照上面来的。当然,也可以更改顺序。

Ⅴ、源代码分析

笔者以F1标准外设库(同时也建议初学者使用官方的标准外设库)为基础建立的工程,主要以库的方式来讲述(若您的F1芯片与提供工程不一样,可微信回复“修改型号”)。

下面将讲述ADC重要的几点:

1.输入引脚配置

该函数位于adc.c文件下面;

引脚与通道的对应关系请参看你使用芯片的数据手册。

注意:

为什么是“ADC123_IN1”? 而不是ADC1_IN1,或者ADC2_IN1?

原因是ADC1、ADC2和ADC3共用这些引脚。

2. DMA配置

该函数位于adc.c文件下面;

1.外设地址:DMA_PeripheralBaseAddr = (uint32_t)(&(ADC1->DR));

我们使用ADC数据寄存器地址作为DMA的外设地址;

2.内存地址:DMA_MemoryBaseAddr = (uint32_t)ADC_Buf;

这里就是我们定义保存采集值数组的地址;

3.传输方向:DMA_DIR = DMA_DIR_PeripheralSRC;

DMA_DIR_PeripheralSRC:外设 -> 内存

DMA_DIR_PeripheralDST:内存 -> 外设

4.传输长度:DMA_BufferSize = ADC_BUF_SIZE;

ADC_BUF_SIZE是一个宏定义,等于3; 也就是说我们需要转换并保存3组数据(3条通道的值)。

5.外设地址增长:DMA_PeripheralInc = DMA_PeripheralInc_Disable;

由于外设的地址都是ADC数据寄存器,没有改变,所以不需要增长地址;

6.内存地址增长:DMA_MemoryInc = DMA_MemoryInc_Enable;

由于我们定义了一个数字,里面需要保存3个数值,所以需要增长;

【根据传输长度和循环模式,可以循环传输数据】

7.外设数据长度:DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

DMA_PeripheralDataSize_Byte:8位数据

DMA_PeripheralDataSize_HalfWord:16位数据

DMA_PeripheralDataSize_Word:32位数据

由于我们使用16位的数据,所以使用DMA_PeripheralDataSize_HalfWord;

8.内存数据长度:DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

和“外设数据长度”类似;

9.循环模式:DMA_Mode = DMA_Mode_Circular;

这里说的循环就是我们循环采集3组数据(更加传输长度来确定);

10.优先级:DMA_Priority = DMA_Priority_VeryHigh;

优先级应该都明白他的意思,我们只使用一组DMA这个优先级可高可低;

11.优先级:DMA_M2M = DMA_M2M_Disable;

内存传输到内存:否

注意:

为什么我们是使用DMA1_Channel1?

我们使用DMA通道是有要求的,需按照手册提供的规则来(如下图);请参看手册:

3. ADC配置

该函数位于adc.c文件下面;

这个函数是本文的重点,下面依次来讲述源代码内容的意思;

A.初始化基本参数:

工作模式:ADC_Mode = ADC_Mode_Independent;

总共有10种,主要都是针对双ADC下使用。针对初学者这里不多描述,感兴趣的朋友可以先自行研究一下各个模式的使用。

浏览模式:ADC_ScanConvMode = ENABLE;

主要是针对多条通道而言,也就是说你是否有多条通道。

多通道:ENABLE;

单通道:DISABLE;

转换模式:ADC_ContinuousConvMode = DISABLE;

这里是配置是否需要连续转换。

连续转换ENABLE:也就是只需要启动(触发)转换一次,后面就不用再次启动(触发)就可以连续工作了。

单次转换DISABLE:也就是根据一次转换完后需要再次启动(触发)才能工作。

触发方式:ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

触发方式也就是使用什么方法触发ADC转换。哟定时器、外部触发、软件触发,一般常用软件触发。这里有很多种触发方式,详情可以参考其参数。

对其方式:ADC_DataAlign = ADC_DataAlign_Right;

右对其:低12位数据为有效位(常用);

左对其:高12为数据为有效位;

通道数:ADC_NbrOfChannel = 3;

这个参数比较简单,我们定义工作的通道数量。

B.设置规则组通道:

ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);

ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_55Cycles5);

ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_55Cycles5);

我们定义通道1的转换顺序为第1、通道2的转换顺序为第2、通道3的转换顺序为第3;

C.校验:

ADC_ResetCalibration(ADC1);                    //校验复位

while(ADC_GetResetCalibrationStatus(ADC1));    //等待复位完成

ADC_StartCalibration(ADC1);                    //开始ADC1校准

while(ADC_GetCalibrationStatus(ADC1));         //等待校验完成

建议每次上电校正一次。

ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。在校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差。

Ⅵ、说明

关于STM32的ADC转换这一块功能确实交强大也相对来说比较复杂,或许文中讲述的还不够清楚,若有不清楚的可以关注微信,在微信上留言。

关于笔者提供的软件工程实例,可关注微信,在会话框回复“关于工程”,有关于工程结构描述、型号修改等讲述。

以上总结仅供参考,若有不对之处,敬请谅解。

Ⅶ、最后

更多精彩文章我将第一时间在微信公众号里面分享,该文有什么疑问可留言。

本着免费分享的原则,方便大家手机学习知识,定期在微信平台分享技术知识。如果你觉得分享的内容对你有用,又想了解更多相关的文章,请用微信搜索“EmbeddDeveloper” 或者扫描下面二维码、关注,将有更多精彩内容等着你。

STM32F10x_ADC三通道DMA连续转换(3通道、软件单次触发)的更多相关文章

  1. STM32F10x_ADC三通道逐次转换(单次、单通道软件触发)

    Ⅰ.概述 本文讲述关于STM32功能比较强大的ADC模块.ADC(Analog to Digital Converter)也就是模拟量转化为数字量,而STM32的ADC模块功能比较多,本文主要讲述“三 ...

  2. 1--STM32 ADC1与ADC2 16通道DMA采集笔记(原创)

    最近在搞ADC,网上还是很多资源的,以下为参考链接:1.对STM32 ADC单次转换模式 连续转换模式 扫描模式的理解:https://www.cnblogs.com/zhanghankui/p/51 ...

  3. Halcon学习之三:有关图像通道的函数(R是三通道,B是1通道,G二通道),排列顺序BGR

    黑白摄像机会返回每个像素所对应的能量采用结果,这些结果组成了一幅单通道灰度值图像,而对于RGB彩色摄像机,它将返回每个像素所对应的三个采样结果,也就是一幅三通道图像.下面这些是与图像通道有关的函数: ...

  4. conda中重要的三个概念:环境、通道和包

    基本使用conda必须要了解的三个概念:虚拟环境.通道和包. conda提供了在python环境下重要的编程环境管理功能,包括环境隔离和依赖包管理. 环境隔离通过虚拟环境实现,与此相关的命令有: co ...

  5. STM32F207 两路ADC连续转换及GPIO模拟I2C给MT9V024初始化参数

    1.为了更好的方便调试,串口必须要有的,主要打印一些信息,当前时钟.转换后的电压值和I2C读出的数据. 2.通过GPIO 模拟I2C对镁光的MT9V024进行参数初始化.之前用我以前公司SP0A19芯 ...

  6. Java NIO中的通道Channel(一)通道基础

    什么是通道Channel 这个说实话挺难定义的,有点抽象,不过我们可以根据它的用途来理解: 通道主要用于传输数据,从缓冲区的一侧传到另一侧的实体(如文件.套接字...),反之亦然: 通道是访问IO服务 ...

  7. pipelineDB学习笔记-3. Continuous Transforms (连续转换)

    以下内容为本人根据pipelineDB官网内容进行翻译,如有不妥之处请指正,谢谢大家 Continuous Transforms (连续转换) 一.定义: Continuous Transforms ...

  8. 使用opencv为没有透明通道的图像加入透明通道

    在图像处理中,我们经常需要处理带透明通道的图片,比如为图片或视频添加水印,为图片或视频添加字幕.贴图等.然而,我们的素材图片未必总是带有透明通道.比如,素材的背景本该透明的地方,却是黑色和白色.有时, ...

  9. hibernate 三种状态的转换

    一.遇到的神奇的事情 使用jpa操作数据库,当我使用findAll()方法查处一个List的对象后,给对这个list的实体进行了一些操作,并没有调用update 或者 saveOrUpdate方法,更 ...

随机推荐

  1. Java Nashorn--Part 3

    jjs 的 -Scripting 选项 jjs shell 是一个不错的方法来测试一些基本的 JavaScript,或者于不太熟悉的 JavaScript包进行交互(主要是指 javax.script ...

  2. Python 文件 write() 方法

    概述 Python 文件 write() 方法用于向文件中写入指定字符串. 在文件关闭前或缓冲区刷新前,字符串内容存储在缓冲区中,这时你在文件中是看不到写入的内容的. 语法 write() 方法语法如 ...

  3. 例说Linux内核链表(一)

    介绍 众所周知,Linux内核大部分是使用GNU C语言写的.C不同于其它的语言,它不具备一个好的数据结构对象或者标准对象库的支持. 所以能够借用Linux内核源代码树的循环双链表是一件非常值得让人高 ...

  4. 使用 sqlyog 导入导出数据显示 lost connection to mysql server during query

    mysql中经常需要备份数据,在使用 sqlyog 进行备份数据库为转储文件,然后在其他数据库中导入发生 lost connection 经过查询大量资料是数据库配置的 max_allowed_pac ...

  5. java、oracle对CLOB处理

    oracle CLOB字段转换位VARCHAR 1.实际上处理CLOB字段的时候,直接TO_CHAR,当长度超过4000的时候,会报错,提示列被截取: CLOB转varchar2:select to_ ...

  6. Atitit opencv 模板匹配

    Atitit opencv 模板匹配 1.1. 图片1 1.2. Atitit opencv 模板匹配  6中匹配算法貌似效果区别不大1 1.3. 对模板缩放的影响 一般的缩放可以,太大了就歇菜了.. ...

  7. vivado2015.4 simulator 存储所有信号到 .wdb 文件 并打开波形文件查看波形

    OS WIN7vivado 2015.4vivado自带的仿真器 vivado project 包含一个block design, block design 中包含AXIPCIE, MIG, INTE ...

  8. postgres json

    https://www.postgresql.org/docs/9.6/static/functions-json.html Search Documentation:  Home → Documen ...

  9. how many shards and replicas should be set for Elastic Search

    https://cpratt.co/how-many-shards-should-elasticsearch-indexes-have/ https://blog.trifork.com/2014/0 ...

  10. GGGGCCCC

    Evaluating and improving remembered sets in the HotSpot G1 garbage collector http://www.diva-portal. ...