STM32的ADC使用非常灵活,采样触发方面:既支持软件触发,定时器或其他硬件电路自动触发,也支持转换完成后自动触发下一通道/轮转换。转换结果存储方面:既支持软件读取和转存,也支持DMA自动存储转换结果。STM32书籍介绍的最多的是“软件触发 + 查询法读取转换结果的方式”,对采集温度、湿度这样近乎直流的信号而言,这种方法足够应付。但当应用需要提升A/D转换的采样率时,这种做法就逐渐无法满足求了:1、软件需要通过频繁的查询或中断来确定在采样间隔时到达时及时触发下一轮A/D转换,处理器的其他工作被频繁打断,软件开发难度增加。2、定时器定时中断/查询法的定时精度/抖动时间大概是处理器执行数条指令的时间,对于STM32而言,当采样率大于10KSPS以后,采样定时抖动造成信噪比降低将使A/D的信噪比降低到与10位A/D相当(具体数学分析详见本人之前博文:(https://www.cnblogs.com/helesheng/p/8880492.html)。
STM32提供两种方法来解决这个问题:方法一:让ADC不停歇的连续进行转换,转换结果则通过DMA直接搬运到内存中。由于ADC进行一次转换的时间可以由ADC时钟CLKADC频率和采样保持时间精确确定,这种方法有效的降低了转换间隔时间的孔径抖动,提高了信噪比,尤其适合200KSPS以上的高采样率。有兴趣的读者可以参考我在博文:https://www.cnblogs.com/helesheng/p/8880492.html中给出的代码。由于无法连续调节CLKADC频率和采样保持时间,但这种方法的缺陷是无法连续调节采样率,如20.05KSPS,44.1KSPS等常用但非整数的采样率是无法被产生的。本文介绍的方法二,是由定时器3的TRGO信号直接出发A/D转换的方法可以有效的在低于200KSPS以下时实现采样率的连续调节。由于使用定时器硬件直接出发A/D转换,无需软件参与,这种方法也能够有效的避免采样间隔的孔径抖动。另外,为了避免软件频繁参与转换结果读取造成的执行效率降低和开发难度增大问题,本文提供了通过DMA读取自动连续转换结果的代码。
以下原创内容欢迎网友转载,但请注明出处: https://www.cnblogs.com/helesheng
 
一、ADC模块配置
 1 RCC_ADCCLKConfig(RCC_PCLK2_Div8);   //设置ADC分频因子8 72M/8=9,ADC最大时间不能超过14M  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC1工作在独立模式
2
3 ADC_InitStructure.ADC_ScanConvMode = ENABLE;//模数转换工作在扫描模式(多通道)
4 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//ADC工作在非连续模式
5 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;//定时器3的TRGO触发转换
6 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//ADC数据右对齐
7 ADC_InitStructure.ADC_NbrOfChannel = 2;//转换的ADC通道的数目为2
8 ADC_Init(ADC1, &ADC_InitStructure);//要把以下参数初始化ADC_InitStructure
9 ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_13Cycles5);//ADC1通道6 ,采样时间为13.5个周期
10 ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_13Cycles5);//ADC1通道7 ,采样时间为13.5个周期
11 ADC_DMACmd(ADC1, ENABLE); //使能ADC1的DMA传输方式
12 ADC_Cmd(ADC1, ENABLE);//使能ADC1
13 ADC_ResetCalibration(ADC1);//重置ADC1的校准寄存器
14 while(ADC_GetResetCalibrationStatus(ADC1));
15 ADC_StartCalibration(ADC1); //开始校准ADC1
16 while(ADC_GetCalibrationStatus(ADC1)); //等待校准完成
17 ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC1软件转换
其中值得注意的是:
1、ADC被配置为由外部信号触发,而触发信号是TIM3产生的TRGO。注意STM32不支持其他定时器的TRGO作为ADC的触发源。
2、ADC被配置为非连续工作模式( ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;)所谓“连续工作模式”,就是前面提到了通过配置每次A/D转换时间实现采样定时的工作方式。如果该模式被使能,就意味着ADC会在被一次触发后就逐通道、不停歇的进行连续的转换,而不会等到下次定时器触发信号TRGO再启动A/D转换。
3、ADC被配置为多通道扫描模式(ADC_InitStructure.ADC_ScanConvMode = ENABLE;),这样ADC会在每次被TIM3触发后依次完成规则通道组中每个通道的一轮转换
二、DMA的配置
 1   DMA_DeInit(DMA1_Channel1);
2 DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;//传输的源头地址
3 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;//目标地址
4 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外设作源头
5 DMA_InitStructure.DMA_BufferSize = 2000;//数据长度为2000
6 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址寄存器不递增
7 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址递增
8 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设传输以字节为单位
9 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//内存以字为单位
10 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//循环模式
11 DMA_InitStructure.DMA_Priority = DMA_Priority_High;//4优先级之一的(高优先)
12 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //非内存到内存
13 DMA_Init(DMA1_Channel1, &DMA_InitStructure);//根据以上参数初始化DMA_InitStructure
14
15 DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);//配置DMA1通道1传输完成中断
16 DMA_Cmd(DMA1_Channel1, ENABLE);//使能DMA1
其中值得注意的是:
1、DMA被配置为外设到内存方式,每次传输的数据宽度是半字(16位)。
2、缓冲长度为2000个半字(DMA_InitStructure.DMA_BufferSize = 2000;),由于前面配置了两个通道,缓冲区将一次能存放1000次采样的结果。
2、使用循环模式(DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;),使能了DMA1中断(DMA_Init(DMA1_Channel1, &DMA_InitStructure);)这样将在完成1000次采样后触发DMA中断,以便软件一次性读取这1000次转换的结果。而下一次ADC转换完成后结果将从头覆盖这个缓冲区的内容。
与之配套的中断控制器配置程序如下:
1 NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
2 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级设置为1
3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//子优先级设置为1
4 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//中断使能
5 NVIC_Init(&NVIC_InitStructure);//按指定参数初始化中断
其中抢占优先级和子优先级可以根据应用实际需要确定。
DMA中断服务程序如下:
 1 void DMA1_Channel1_IRQHandler(void)
2 {
3 if(DMA_GetITStatus(DMA1_IT_TC1))//判断通道1是否传输完成
4 {
5 DMA_ClearITPendingBit(DMA1_IT_TC1); //清除通道1传输完成标志位
6
7 ////////////此处应编写代码从DMA指向的内存区读走数据,否则可能被覆盖//////////
8
9
10 }
11 }
三、TIM3配置
TIM3配置代码如下:
 1 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能TIM3时钟
2
3 TIM_TimeBaseStructure.TIM_Period = 1000-1;
4 TIM_TimeBaseStructure.TIM_Prescaler = 72-1;
5 TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; //采样分频TIM_CKD_DIV1
6 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
7 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
8
9 TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);//设置输出TRGO信号
10 TIM_Cmd(TIM3, ENABLE);
其中值得注意的是:
1、周期寄存器和预分频寄存器配置后,将TIM3的溢出频率确定为1KHz。而这些值可以根据应用需要的采样率自己确定。
2、TIM3溢出后将输出TRGO信号(TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);)。
 
 
 
 
 
 
 

STM32定时器触发ADC多通道连续采样,DMA缓存结果的更多相关文章

  1. STM32 ADC多通道规则采样和注入采样

    layout: post tags: [STM32] comments: true 文章目录 layout: post tags: [STM32] comments: true 什么是ADC? STM ...

  2. 关于Stm32定时器+ADC+DMA进行AD采样的实现

    Stm32的ADC有DMA功能这都毋庸置疑,也是我们用的最多的!然而,如果我们要对一个信号(比如脉搏信号)进行定时采样(也就是隔一段时间,比如说2ms),有三种方法: 1.使用定时器中断每隔一定时间进 ...

  3. ADC配置成定时器触发的启发

    百度文库:https://wenku.baidu.com/view/99d39413f78a6529647d5344.html STM32关于使用定时器触发ADC转换的解决办法和详细说明 本人在使用S ...

  4. stm32之ADC应用实例(单通道、多通道、基于DMA)

    文本仅做记录.. 硬件:STM32F103VCT6 开发工具:Keil uVision4 下载调试工具:ARM仿真器 网上资料很多,这里做一个详细的整合.(也不是很详细,但很通俗).  所用的芯片内嵌 ...

  5. STM32 ADC多通道转换DMA模式与非DMA模式两种方法(HAL库)

    一.非DMA模式(转) 说明:这个是自己刚做的时候百度出来的,不是我自己做出来的,因为感觉有用就保存下来做学习用,原文链接:https://blog.csdn.net/qq_24815615/arti ...

  6. stm32之ADC应用实例(单通道、多通道、基于DMA)-转载精华帖,最后一部分的代码是精华

    硬件:STM32F103VCT6    开发工具:Keil uVision4    下载调试工具:ARM仿真器网上资料很多,这里做一个详细的整合.(也不是很详细,但很通俗).所用的芯片内嵌3个12位的 ...

  7. stm32 ADC模数转换 ADC多通道 ADC DMA

    通过调节电位器,改变AD转换值和电压值 STM32F1 ADC 配置步骤 1.使能GPIO时钟和ADC时钟 2.配置引脚模式为模拟输入 3.配置ADC的分频因子 4.初始化ADC参数,ADC_Init ...

  8. STM32之ADC实例(基于DMA方式)

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/zouleideboke/article/details/75112224 ADC简介: ADC(An ...

  9. STM32—ADC多通道采集电压

    文章目录 ADC详解 程序说明 函数主体 引脚配置 ADC和DMA配置 主函数 ADC详解 前面的博客中详细介绍了STM32中ADC的相关信息,这篇博客是对ADC内容的一个总结提升,ADC的详细介绍: ...

随机推荐

  1. 【LeetCode】232. Implement Queue using Stacks 解题报告(Python & Java)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 Python解法 Java解法 日期 [LeetCo ...

  2. MySQL与Oracle 差异比较之二函数

    函数 编号 类别 ORACLE MYSQL 注释 1 数字函数 round(1.23456,4) round(1.23456,4) 一样:ORACLE:select round(1.23456,4) ...

  3. Windows服务注册(需要指定config文件的情况下)

    最近,遇到一个问题:需要将telegraf在Win平台下注册为windows服务(避免误操作关闭CMD窗口): 尝试了网上的几种注册Windows服务的方法,发现无法将telegraf这种需要在CMD ...

  4. 【嵌入式】arduino IDE串口监视器可以正常使用但其他软件发送串口指令没有反应的问题

    解决办法: 1.检查 波特率baudrate 是否一致 2.检查 数据位长度databits 是否一致 3.检查 停止位长度stopbits 是否一致 4.检查 奇偶校验位 是否一致 5.(特殊)是否 ...

  5. Proximal Algorithms 5 Parallel and Distributed Algorithms

    目录 问题的结构 consensus 更为一般的情况 Exchange 问题 Global exchange 更为一般的情况 Allocation Proximal Algorithms 这一节,介绍 ...

  6. 强强联袂!腾讯云TDSQL与国双战略签约,锚定国产数据库巨大市场

    日前,腾讯云计算(北京)有限责任公司与北京国双科技有限公司签署了<国产数据库产品战略合作协议>,双方将在数据库技术方面展开深度合作,通过分布式交易型数据库的联合研发.产品服务体系建设.品牌 ...

  7. [学习笔记] RabbitMQ的简单使用

    安装依赖 # composer.json { "require": { "php-amqplib/php-amqplib": ">=2.9.0& ...

  8. android-tools下的uiautomatorviewer截图,提示“Unexpected error while obtaining UI hierarchy”

    使用原来工具下的uiautomatorviewer对android 5.1.0的手机,进行截图,是正常的,切换到android10截图,就报错"Unexpected error while ...

  9. 怎样修改自己的登录shell

    问题 我只是Linux系统的普通用户,没有权限调用chsh命令修改自己的登录shell. bash-4.1$ chsh --help Usage: chsh [ -s shell ] [ --list ...

  10. SQL高级优化(四)之SQL优化

    SQL优化 一.SQL优化简介 解释:对于特定的要求,使用更有的SQL策略或索引策略,以达到让结果呈现的时间更短,从而提升操作效率的过程就是SQL优化. SQL优化包含在数据库级别优化中.我们平常所说 ...