精华内容
下载资源
问答
  • 基于STM32电压信号采集及DMA读取
    千次阅读
    2020-12-31 08:49:40

    【实例简介】

    基于STM32的电压信号采集及DMA读取,对需要采集传感器信号的人很有帮助

    【实例截图】

    【核心代码】

    ADCDMA

    ├── Lib

    │   ├── cmsis

    │   │   ├── core_cm3.c

    │   │   ├── core_cm3.h

    │   │   ├── stm32f10x.h

    │   │   └── system_stm32f10x.h

    │   ├── inc

    │   │   ├── misc.h

    │   │   ├── stm32f10x_adc.h

    │   │   ├── stm32f10x_bkp.h

    │   │   ├── stm32f10x_can.h

    │   │   ├── stm32f10x_cec.h

    │   │   ├── stm32f10x_crc.h

    │   │   ├── stm32f10x_dac.h

    │   │   ├── stm32f10x_dbgmcu.h

    │   │   ├── stm32f10x_dma.h

    │   │   ├── stm32f10x_exti.h

    │   │   ├── stm32f10x_flash.h

    │   │   ├── stm32f10x_fsmc.h

    │   │   ├── stm32f10x_gpio.h

    │   │   ├── stm32f10x_i2c.h

    │   │   ├── stm32f10x_iwdg.h

    │   │   ├── stm32f10x_pwr.h

    │   │   ├── stm32f10x_rcc.h

    │   │   ├── stm32f10x_rtc.h

    │   │   ├── stm32f10x_sdio.h

    │   │   ├── stm32f10x_spi.h

    │   │   ├── stm32f10x_tim.h

    │   │   ├── stm32f10x_usart.h

    │   │   └── stm32f10x_wwdg.h

    │   ├── src

    │   │   ├── misc.c

    │   │   ├── stm32f10x_adc.c

    │   │   ├── stm32f10x_bkp.c

    │   │   ├── stm32f10x_can.c

    │   │   ├── stm32f10x_cec.c

    │   │   ├── stm32f10x_crc.c

    │   │   ├── stm32f10x_dac.c

    │   │   ├── stm32f10x_dbgmcu.c

    │   │   ├── stm32f10x_dma.c

    │   │   ├── stm32f10x_exti.c

    │   │   ├── stm32f10x_flash.c

    │   │   ├── stm32f10x_fsmc.c

    │   │   ├── stm32f10x_gpio.c

    │   │   ├── stm32f10x_i2c.c

    │   │   ├── stm32f10x_iwdg.c

    │   │   ├── stm32f10x_pwr.c

    │   │   ├── stm32f10x_rcc.c

    │   │   ├── stm32f10x_rtc.c

    │   │   ├── stm32f10x_sdio.c

    │   │   ├── stm32f10x_spi.c

    │   │   ├── stm32f10x_tim.c

    │   │   ├── stm32f10x_usart.c

    │   │   └── stm32f10x_wwdg.c

    │   └── startup

    │   └── arm

    │   ├── startup_stm32f10x_cl.s

    │   ├── startup_stm32f10x_hd.s

    │   ├── startup_stm32f10x_hd_vl.s

    │   ├── startup_stm32f10x_ld.s

    │   ├── startup_stm32f10x_ld_vl.s

    │   ├── startup_stm32f10x_md.s

    │   ├── startup_stm32f10x_md_vl.s

    │   └── startup_stm32f10x_xl.s

    ├── MDK_Project

    │   ├── JLinkLog.txt

    │   ├── JLinkSettings.ini

    │   ├── List

    │   │   ├── Project.map

    │   │   └── startup_stm32f10x_cl.lst

    │   ├── Out

    │   │   ├── core_cm3.crf

    │   │   ├── core_cm3.d

    │   │   ├── core_cm3.o

    │   │   ├── main.crf

    │   │   ├── main.d

    │   │   ├── main.o

    │   │   ├── Project.axf

    │   │   ├── Project.hex

    │   │   ├── Project.htm

    │   │   ├── Project.lnp

    │   │   ├── Project.plg

    │   │   ├── Project.sct

    │   │   ├── Project.tra

    │   │   ├── startup_stm32f10x_cl.d

    │   │   ├── startup_stm32f10x_cl.o

    │   │   ├── stm32f10x_adc.crf

    │   │   ├── stm32f10x_adc.d

    │   │   ├── stm32f10x_adc.o

    │   │   ├── stm32f10x_dma.crf

    │   │   ├── stm32f10x_dma.d

    │   │   ├── stm32f10x_dma.o

    │   │   ├── stm32f10x_gpio.crf

    │   │   ├── stm32f10x_gpio.d

    │   │   ├── stm32f10x_gpio.o

    │   │   ├── stm32f10x_it.crf

    │   │   ├── stm32f10x_it.d

    │   │   ├── stm32f10x_it.o

    │   │   ├── stm32f10x_rcc.crf

    │   │   ├── stm32f10x_rcc.d

    │   │   ├── stm32f10x_rcc.o

    │   │   ├── stm32f10x_usart.crf

    │   │   ├── stm32f10x_usart.d

    │   │   ├── stm32f10x_usart.o

    │   │   ├── system_stm32f10x.crf

    │   │   ├── system_stm32f10x.d

    │   │   ├── system_stm32f10x.o

    │   │   ├── systick.crf

    │   │   ├── systick.d

    │   │   ├── systick.o

    │   │   ├── usart.crf

    │   │   ├── usart.d

    │   │   └── usart.o

    │   ├── Project_Target 1.dep

    │   ├── Project.uvgui.Administrator

    │   ├── Project.uvgui_Administrator.bak

    │   ├── Project.uvopt

    │   ├── Project_uvopt.bak

    │   ├── Project.uvproj

    │   └── Project_uvproj.bak

    ├── Readme.txt

    └── User

    ├── main.c

    ├── stm32f10x_conf.h

    ├── stm32f10x_it.c

    ├── stm32f10x_it.h

    ├── system_stm32f10x.c

    ├── SysTick

    │   ├── systick.c

    │   └── systick.h

    └── USART

    ├── usart.c

    └── usart.h

    12 directories, 121 files

    更多相关内容
  • 包含程序、仿真 采集电压并通过串口打印出来
  • STM32做的电压采集系统文献参考,《基于STM32的多路电压采集研究_宋敬卫》
  • 通过串口调试助手设定电压值(十六进制),用ADC采集显示在串口助手上
  • STM32在速度、功耗方面性能都更加优越,并且STM32价格较低,在成本上也有优势。适合于控制电子设备的设计。使用12位ADC,能够满足一定的测量精度,对于较高的测量要求,则需要使用更高精确度的ADC。但是使用高精度 ...
  • adc采集端口的电压,基础练习适合新手观看,各个文件单独分开易于移植
  • 1.引言近年来,数据采集及其应用受到了人们越来越广泛的关注,数据采集系统也有了迅速的发展,它可以广泛的应用于各种领域。...ADC用于直接采集模拟电压并将模拟信号转换成数字信号,它直接影响着数据采集
  • 基于STM32F103单片机电流电压采集系统设计.pdf
  • STM32采样电压

    2019-11-01 21:03:22
    趁着实习的时候写了一个测电压值得程序,我用的是最小系统板,MCU是stm32f103rct6,这个是照着正点原子的教程自己改的,因为他的太复杂了,我就把简化到只有采样电压值得功能,自己测试是通过串口打印显示了出来,如...
  • AD初始化程序,使用DMA,采集电池电压,非常好用,采集速度快,已经验证
  • STM32 精准采集ADC电压,误差分析

    千次阅读 2022-01-03 15:16:33
    STM32 大部分系列都是使用SAR 逐次逼近型电压采集 VIN是采集的模拟输入口,VREF表示参考电压。Sa PIN和内部ADC的开关。Sb 接地开关。 电压采集阶段 电压采集阶段就是内部电容充电的过程。Sb闭合后ADC内部(这里称之...

    ADC模块采集电压流程

    数字世界和模拟世界的桥梁,对于嵌入式软件而言,大家止于采集功能的实现。

    本文目的在于深入理解ADC,积累技术做出更加稳定优秀的产品。

    在这里插入图片描述
    STM32 大部分系列都是使用SAR 逐次逼近型电压采集
    VIN是采集的模拟输入口,VREF表示参考电压。Sa PIN和内部ADC的开关。Sb 接地开关。

    电压采集阶段
    在这里插入图片描述
    电压采集阶段就是内部电容充电的过程。Sb闭合后ADC内部(这里称之为采样保存电路,并不是转换器核心)的电容会进行充电,这个过程需要消耗一定的时间。一但采集完成,相当于复制了一份模拟输入引脚的 电压值。采集阶段完成后这个时候VIN已经不需要了,也就是说这个Pin 上的电压已经采集完毕。
    在这里插入图片描述
    等效电路就是VIN对电容2C进行充电。
    前面说道这里是采用保持电路,所以有保持阶段
    在这里插入图片描述
    这个阶段就是各个电容充电完毕,在ADC核心转换器工作前的这断时间。这个时候VIN PIN模拟输入引脚已经和ADC断开了。Sb开路。
    也就是说实际上ADC 转换核心转换的是采样保持电路的电压。所以务必要根据手册,明确采样阶段最小用时,确保充电阶段完成。
    在这里插入图片描述
    其等效电路入上图所示电容器一断的电压为-VIN

    转换阶段
    这个阶段的重点在于每次二分。
    在这里插入图片描述

    在这里插入图片描述
    这里设计到一些电路的知识,如果是软件开发会比较难懂
    在这里插入图片描述
    在这里插入图片描述

    具体的过程讲起来比较复杂,软件工程师只需要对其逐次逼近转换的二分思路有理解即可。

    这个可能会因为各个芯片的转换核心而异

    在这里插入图片描述
    本节重点:
    1.ADC的采样保持电路 ,采集VIN电压,形成副本供ADC转换核心使用
    2.电压转换逐次逼近转换的二分思路 0.5+0.25+0.125+…=1
    在这里插入图片描述
    关于采样时间,采样时间是电容充电的过程,如上图所示,实线代表充电过程虚线代表放电。
    t =RC, C 为采样电容,R为充电回路的电阻。
    一般来说需要5 RC采样时间,这样内部电容可以精准的采集到输入电压。
    在这里插入图片描述
    5RC 时间大概采集到两端电压的99.3%
    在这里插入图片描述
    6RC 时间大概采集到两端电压的99.8%
    这个电压值永远都无法充电到100%V,一般来说5RC的时间,认为充满。

    5RC 充满到99.3%,还有千分之七的电压未采集。 7/1000
    一般的ADC 12位 1/4049的采样精度。这个时候需要去看产品的设计要求。一般情况下不需要做补偿。

    ADC module 转换误差

    对于STM32 ADC,电压的最小可检测增量变化用LSB表示为:

    1 LSB 表示ADC模块可分辨的最小电压
    12 位ADC 其一个单位表示V* 1/4096
    10 位ADC 其一个单位表示V* 1/1024

    为了后面书写方便 1LSB的系数表示为 12 位ADC P = 1/4096 ,10 位ADC P= 1/1024

    满量程转换电压V
    V 满量程转换电压,这部分不同的ADC和电路有不同的设计
    V =(VREF+)-(VREF-) 一般采用这种

    V =(VREF+)-(VSSD)
    其中VSSD可以为GND。这取决于电路设计。

    resault = Vin/V *P 其中Vin为需要采集的电压
    Vin在不同的ADC模块中有不同的配置
    Vin = Vi -VGND,对地电压
    Vin = Vp -Vn 差分输入电压。
    Vin = Vp- Vref-
    一般而言是最后一种,取决于电路的连接情况和ADC模块。

    把ADC作为一个系统而言,Vin是系统的输入,resault 是系统的输出

    V是系统内部的电压,其如果变化,那么输出结果变化。转换结果的稳定性就会受到影响。
    在这里插入图片描述
    ADC器件内部的误差

    1.偏移误差 offset

    offset一般指的是偏移误差,较正确值产生的一段位移。

    理想情况下,当模拟输入介于0.5 LSB和1.5 LSB之间时,数字输出应为1。

    V >0.5 LSB 输出1,V<0.5LSB 输出0,实际上 V>0.5LSB +W 时输出才为1,V<0.5LSB +W 为0
    就会有下面的曲线,W>0 也就是Eo >0
    在这里插入图片描述

    w < 0 时
    在这里插入图片描述
    可通过应用固件轻松校准偏移误差。也就是在ADC初始化的时候 calibration

    ADC Calibration 是一个很复杂的学问。我们只需要记得,一定要开启。

    增益误差是指ADC实际传输特性曲线和理想传输特性曲线的偏差程度。增益误差的单位是%FSR(满量程值)。如果没有校准,那么增益误差会限制信号输出的准确性
    在这里插入图片描述
    红线为理想ADC的传输特性曲线,蓝线为实际ADC的传输特性曲线。
    当然蓝色曲线在红色上方误差为 + ,再下方是为 -

    微分线性误差
    手册用 Linearity error 来表示。他表示了ADC器件在所有的数值点上对应的模拟值,和真实值之间误差最大的那一点的误差值。
    输出数值偏离线性最大的距离
    在这里插入图片描述
    积分线性误差为任何实际转换和端点相关线间的最大偏离。
    在这里插入图片描述
    总未调整误差
    总未调整误差( TUE)为实际和理想传输曲线间的最大偏离。此参数指定可能发生的会导致
    理想数字输出与实际数字输出之间最大偏离的总误差。
    在这里插入图片描述

    ADC环境导致的误差

    其中有很多是硬件工程师需要关注的问题,软件工程师需要对误差的来源有认识。
    在必要的情况下,要求硬件工程师一起参与问题的分析。

    1.参考电压噪声:电源的噪声导致参考电压波动,从而对ADC转换值产生影像
    2.参考电压/电源调节:负载及其输出阻抗导致电源输出下降,影响到参考电压

    3.外部参考电压参数
    当使用外部参考电压源( VREF+引脚上)时,该外部参考源有一些重要参数。必须考虑三个
    参考电压规格:温度漂移、电压噪声和长期稳定性

    4.模拟输入信号噪声
    在采样时间内,小而高频率的信号变化可导致较大转换误差。

    5.最大输入信号幅度的ADC动态范围匹配不佳
    被采集的信号电压波动范围,占ADC总量程的比例。

    6.模拟信号源电阻的影响
    在源和引脚之间的模拟信号源的阻抗或串联电阻( RAIN),可能会因为流入引脚的电流而导
    致其上的电压降。通过电阻为RADC的开关控制内部采样电容( CADC)的充电。
    在这里插入图片描述
    7.PCB源电容和寄生电容的影响
    在转换模拟信号时,必须考虑源电容和模拟输入引脚上的寄生电容
    一般情况下低频信号不用考虑,当然需要结合RC时间常数来考虑
    在这里插入图片描述
    8.注入电流的影响
    任何模拟引脚(或紧邻的数字输入引脚)上的负注入电流都可能在ADC输入中产生泄漏电流。
    在这里插入图片描述

    9.温度影响
    温度对ADC精度有重要影响。它主要产生两种重要误差:偏移误差漂移和增益误差漂移。这些误差可以在微控制器固件中得到补偿
    一般来说会制作一张温度和转换值的对应表格,用来修正温度对ADC的影像。

    10.I/O引脚串扰
    由于I/O之间的电容耦合,切换I/O可能会在ADC的模拟输入中产生一些噪声。彼此距离很
    近或交叉的PCB走线可能会产生串扰。
    内部切换数字信号和I/O会产生高频噪声。由于电流浪涌,切换高灌电流I/O可能导致电源
    电压小幅下降。 PCB上与模拟输入走线交叉的数字走线可能影响模拟信号

    在这里插入图片描述
    11.EMI产生的噪声
    在这里插入图片描述

    如何得到最佳ADC精度

    ADC自校准功能或通过微控制器固件可以轻松补偿偏移误差和增益误差。

    参考电压/电源噪声最小化(硬件设计),一般来说使用噪声小的电源,增加滤波电路。

    MCU端去耦,引脚间产生耦合
    在这里插入图片描述

    参考电压/电源调节
    电源的负载会产生变化,需要保证电压供给VREF 不会应为负载变化而变动

    模拟输入信号噪声消除

    1.多次求平均值
    2.添加外部滤波器
    3.添加白噪声或三角波扫描来改善分辨率。软件工程师只需要去求平均值。
    4.将ADC动态范围与最大信号幅度进行匹配
    在这里插入图片描述
    使用前置放大器。相对来说使用Gain的器件会引入误差,需要考虑是否划算。
    在这里插入图片描述
    5.模拟源电阻 (硬件方法)
    6.源频率条件 vs. 源和寄生电容 (硬件 方法)
    7.温度影响补偿 前面说过用查表
    8.注入电流最小化(硬件方法)
    9.I/O引脚串扰最小化
    在这里插入图片描述
    10.减少EMI所致噪声(硬件方法)
    11.将模拟和数字布局分开(硬件方法)
    12.隔离模拟和数字电路电源(硬件方法)

    提高精度的软件方法

    1.平均采样 多次采样会消耗跟多时间
    2.数字滤波
    3.AC测量的快速傅里叶变换
    4.ADC校准:偏移、增益、位权重校准
    5.使CPU生成的内部噪声最小化
    软件上比较高端的操作,在采样和转换周期数字静默

    实践方法

    1.多次求平均值

    在这里插入图片描述
    多次就平均值的 方法比较常见。采样N次,求N次采样的平均值。如果N为2的倍数,可以用位移的方法快速求得平均值。
    在这里插入图片描述
    总转换时间 = (采样数 * ADC 转换时间) + 计算时间
    额外的开销在与采样次数 和 计算时间。

    uint16_t ADC_GetSampleAvgN(uint8_t N)
    {
    uint32_t avg_sample =0x00;
    uint16_t adc_sample[8]={0,0,0,0,0,0,0,0};
    uint8_t index=0x00;
    /* 得到 N 个 ADC 采样 */
    for (index=0x00; index<N; index++)
    {
    /* ADC 开始转换 */
    ADC_SoftwareStartConv(ADC1);
    /* 等待转换结束 */
    while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);
    /* 储存 ADC 采样 */
    adc_sample[index] = ADC_GetConversionValue(ADC1);
    }
    /* 累加 N 个 ADC 采样 */
    for (index=0; index<N; index++)
    {
    avg_sample += adc_sample[index];
    }
    /* 计算 N 个 ADC 采样的均值 */
    avg_sample /= N;
    /* 返回均值 */
    return avg_sample;
    }
    

    基于先取 N 个 ADC 采样,将它们从最大值到最小值 (或相反顺序)排序,然后删除两端的 X 个采样。
    此平均方法比之前一个更有效,因为它删除了会影响平均的两端值,而且它在执行时间和转换精度之间给出了一个较好的折中。
    在这里插入图片描述
    同样额外的开销是计算时间。

    ADC 的软件滤波方法

    1.限制幅度滤波
    两次采样值的差值如果过大,则认为最近一次的值采集误差较大,舍去。

    该方法需要对采样值的变化幅度有所认知。也就是信号在采样间隔下的波动范围。采样值的波动超过原始信号的波动幅度认为采集到的数据
    收到干扰,故舍弃采样值。

    2.中间值
    采样多次,按照数值大小排列,去中间值为采样值

    对于信号的波动速度比较慢的信号效果比较好

    3.求平均值
    采样多次直接求平均

    采样多次意味着时间跨度较长,平均值的意义是一段时间的中间值。所以灵敏度比较低
    适合随机扰动的系统

    4.递推平均

    按照时间顺序,设定窗口大小,移动窗口进行采样

    5.中值平均

    采样N个值,去掉最大最小
    计算平均值

    6.限幅平均
    根据1方法,求平均值

    7.一阶低通
    y=K本次结果+(1-K)上次结果

    8.加权平均
    采样多次,每次采样的结果分配权重,取得平均值

    9。消抖
    在一段时间内采样值波动幅度在可接收范围内,认为抖动消除

    10.限制幅度消除抖动
    1,9方法结合

    展开全文
  • (2)本资源使用stm32自带的ADC采集外部输入的正弦信号(外加信号需要偏置,因为32自带ADC采集0~3.3V)。 (3)采用stm32官方DSP库的FFT算法处理数据(64,256,1024点处理) (4)计算正弦波失真度。 (5) 采样频率...
  • STM32F103RC采集交流信号有效值,平均值,采用DMA转换。
  • ads1256程序,stm32使用,调试好,可以直接使用
  • 咳咳,这一篇来玩一下STM32的ADC(Analog to Digital Converter),也就是可以把输入的模拟量转换为数字量,这样就可以做个电压表了,再加上一些辅助电路,就能够自己做一个万用表了,非常完美。(嗯,这篇我们只做...
  • DMA2_Stream0 ->PAR = (u32)ADC1+0x4C; // 外设地址 ADC1->DR DMA2_Stream0 ->M0AR = (u32)ADCVal; // 存储器地址 内部SDRAM的变量 DMA2_Stream0 ->NDTR = 3; // 一次传输数量 DMA2_Stream0 ->FCR = 0x21; // ...

    在这里插入图片描述

     // 不爱用函数库, 又臭又长, 查个功能操作,有时要翻两三个文件一百几十行代码, 最重要是对芯片没感觉,像隔着媒人沟妹子 ~~ 
     // 难道你们不觉得寄存器操作=逻辑直观+代码清晰, 特别在查错调试时, 贼爽贼爽的~~~
     // 为毛寄存器操作这么少人用, 代码文章更少, 全网也没多少的样子~~
     // 帮顶一个么~~ 
        u16 ADCVal[3];               // 结果存放数组, 应用时自行参考修改    [0] 通道7    [1]通道6     [2]芯片内温度        
        void ADC_Init(void)
        {
            // 1_GPIO
            GPIOA->MODER |=  0X3<<(2*7);  // PA7 模拟输入
            GPIOA->PUPDR &=~(0X3<<(2*7)); // 不上拉,不下拉
            GPIOA->MODER |=  0x3<<2*6;    // PA6 模拟输入
            GPIOA->PUPDR &=~(0x3<<2*6);                   
            // 2_DMA
            RCC->AHB1ENR |= 0x1<<22;              // 使能DMA2时钟  
            DMA2_Stream0 ->CR   = 0;              // EN    [0]     禁止数据流 ,才能写寄存器 
            DMA2_Stream0 ->PAR  = (u32)ADC1+0x4C; // 外设地址      ADC1->DR
            DMA2_Stream0 ->M0AR = (u32)ADCVal;    // 存储器地址    内部SDRAM的变量
            DMA2_Stream0 ->NDTR = 3;              // 一次传输数量      
            DMA2_Stream0 ->FCR  = 0x21;           // 复位值        FIFO所有配置失效    
              DMA2_Stream0 ->CR |= 0<< 6;         // DIR   [7:6]   传输方向       0_PtM, 1_Mtp, 2_MtM
              DMA2_Stream0 ->CR |= 1<< 8;         // CIRC  [8]     循环模式       0_禁止 1_使能
              DMA2_Stream0 ->CR |= 0<< 9;         // PINC  [9]     外设递增       0_外设地址指针固定  1_递增
              DMA2_Stream0 ->CR |= 1<<10;         // MINC  [10]    存储器递增     0_存储器指针固定    1_递增
              DMA2_Stream0 ->CR |= 1<<11;         // PSIZE [12:11] 外设数据大小   0_8位  1_16位  10_32位
              DMA2_Stream0 ->CR |= 1<<13;         // MSIZE [14:13] 存储器数据大小 0_8位  1_16位  10_32位
              DMA2_Stream0 ->CR |= 1<<16;         // PL    [17:16] 优先级         0_低 1_中 2_高 3_最高
              DMA2_Stream0 ->CR |= 0<<21;         // PBURST[22:21] 外设突发传输   0_单次 1_4节拍 2_8节拍 3_16节拍
              DMA2_Stream0 ->CR |= 0<<23;         // MBURST[24:23] 存储器突发传输 0_单次 1_4节拍 2_8节拍 3_16节拍
              DMA2_Stream0 ->CR |= 0<<25;         // CHSEL [27:25] 通道选择
              DMA2_Stream0 ->CR |= 1<<0;          // EN    [0]     使能数据流, 使能后DMA大部份寄存器都不能写
            // 3_ADC时钟使能
            RCC->APB2ENR  |=  0x1<<8;     // 使能 ADC1 时钟
            RCC->APB2RSTR |=  0x1<<8;     // ADCx复位
            RCC->APB2RSTR &=~(0x1<<8);    // 复位结束
            // 4_通用控制寄存器
            ADC->CCR   = 0;               // MULTI  [ 4: 0]   模式选择     0_独立模式        
            ADC->CCR  |= 0<<8;            // DELAY  [11: 8]   2 个采样阶段之间的延迟;这些位在双重或三重交错模式下使用 .
            ADC->CCR  |= 0<<13;           // DDS    [13]      DMA禁止选择  0_一次      1_[14]==1时,连续      (对于多个 ADC 模式)
            ADC->CCR  |= 0<<14;           // DMA    [15:14]   直接存储器访问模式       0_禁止DMA模式         (对于多个 ADC 模式)
            ADC->CCR  |= 1<<16;           // ADCPRE [17:16]   预分频器 ;ADCCLK=PCLK2/4=90/4=22.5Mhz,ADC时钟不要超过36Mhz
            ADC->CCR  |= 0<<22;           // Vbat   [22]      VBAT通道     0_关闭      1_使能                 [22] 和 [23] 同时使能时, [22]生效
            ADC->CCR  |= 1<<23;           // TSVREFE[23]      温度传感器   0_关闭      1_使能    ADC1_通道18  [22] 和 [23] 同时使能时, [22]生效
            // 5_ADC工作模式
            ADC1->CR1  = 0;               // 00000000
            ADC1->CR1 |= 1<<8 ;           // SCAN    [8 ]     扫描模式     0_禁止      1_使能(多通道时用)       
            ADC1->CR1 |= 0<<24;           // RES     [25:24]  分辨率       0_12位      
            ADC1->CR2  = 0;               // 00000000
            ADC1->CR2 |= 1<<1 ;           // CONT    [1]      连续转换     0_单次      1_连续    
            ADC1->CR2 |= 1<<8;            // DMA     [8]      直接内存存取 0_禁止DMA   1_使用DMA                               (对于单一 ADC 模式)
            ADC1->CR2 |= 1<<9 ;           // DDS     [9]      连续DMA请求  0_只一次    1_只要发生数据转换且 DMA = 1,便发出请求 (对于单一 ADC 模式)
            ADC1->CR2 |= 0<<11;           // ALIGN   [11]     数据对齐     0_右对齐
            ADC1->CR2 |= 0<<24;           // EXTSEL  [27:24]  触发时件     [29:28]==0  本寄存器无效,随便                        (规则通道)
            ADC1->CR2 |= 0<<28;           // EXTEN   [29:28]  外部触发使能 0_禁止      1_上升沿    2_下降沿     3_上升下降      (规则通道)
            // 6_采样时间/规则次序
            ADC1->SMPR1  = 0;             // 清零   [0:0:0]   SMPR1:18-10 , SMPR2:9-0  
            ADC1->SMPR1 |= 5<<(3*(18-10));// 通道18           内部温度
            ADC1->SMPR2  = 0;             // 清零   [0:0:0]   SMPR1:18-10 , SMPR2:9-0        
            ADC1->SMPR2 |= 5<<3*7;        // 采样时间         0_3个周期   1_15   2_28   3_56   4_84   5_112   6_144  7_480
            ADC1->SMPR2 |= 5<<3*6;        // 111:480 个周期      
            
            ADC1->SQR1   = 0;             // 清零  [0:0:0:0:0]
            ADC1->SQR1  |= 2<<20;         // L     [23:20]   转换总数, x+1 个转换在规则序列中
            ADC1->SQR3   = 0;             // 清零  SQR1:第16~13个 , SQR2:第12~7个 , SQR3:第6~1个
            ADC1->SQR3  |= 7<<(5*0);      // 序列1 = ch7
            ADC1->SQR3  |= 6<<(5*1);      // 序列2 = ch6  
            ADC1->SQR3  |= 18<<(5*2);     // 序列3 = ch18
            // 7_开始转换
            ADC1->CR2 |= 0x1<<0;          // 使能 ADC 
            ADC1->CR2 |= 0x1<<30;         // 开始 AD转换         
            printf("ADC     配置完成\n");
        }
    
    展开全文
  • 当使用电池直接供电 或 外部供电低于LDO的输入电压时,会造成STM32 VDD电压不稳定,忽高忽低。 此时通过使用STM32的内部参考电压功能(Embedded internal reference voltage),可以准确的测量ADC管脚对应的电压值,...
  • STM32F103_ADC电压采集

    千次阅读 多人点赞 2021-07-12 16:39:32
    ADC寄存器 1 、STM32 ADC 简介 STM32 的 ADC 是 12 位逐次逼近型的模拟数字转换器。 它有 18 个通道,可测量 16 个...STM32F103 系列最少都拥有 2 个 ADC,我们选择的 STM32F103ZET 包含有 3 个 ADC。STM32 的 ADC

    ADC寄存器
    在这里插入图片描述

    1 、STM32 ADC 简介

    STM32 的 ADC 是 12 位逐次逼近型的模拟数字转换器。 它有 18 个通道,可测量 16 个外部和 2 个内部信号源。各通道的
    A/D 转换可以单次、连续、扫描或间断模式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。
    模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。
    STM32F103 系列最少都拥有 2 个 ADC,我们选择的 STM32F103ZET 包含有 3 个 ADC。STM32 的 ADC 最大的转换速率为 1Mhz,也就是转换时间为 1us(在 ADCCLK=14M,采样周期为 1.5 个 ADC 时钟下得到),不要让 ADC 的时钟超过 14M,否则将导致结果准确度下降。
    STM32 将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。规则通道相当于你正常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你的执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之后,规则通道才得以继续转换。

    简单来说STM32f103系列有3个ADC,精度为12位,每个ADC最多有16个外部通道。其中ADC1和ADC2都有16个外部通道,ADC3一般有8个外部通道,各通道的A/D转换可以单次、连续、扫描或间断执行,ADC转换的结果可以左对齐或右对齐储存在16位数据寄存器中。ADC的输入时钟不得超过14MHz,其时钟频率由PCLK2分频产生(72MHZ)

    2 ADC功能框图讲解

    在这里插入图片描述在这里插入图片描述

    引脚说明
    在这里插入图片描述
    2.0.电压输入范围

    ADC所能测量的电压范围就是VREF- ≤ VIN ≤ VREF+,把 VSSA 和 VREF-接地,把 VREF+和 VDDA 接3V3,得到ADC 的输入电压范围为: 0~3.3V。

    2.1、输入通道
    ADC的信号输入就是通过通道来实现的,信号通过通道输入到单片机中,单片机经过转换后,将模拟信号输出为数字信号。STM32中的ADC有着18个通道,其中外部的16个通道已经在框图中标出,如下:
    在这里插入图片描述

    这16个通道对应着不同的IO口
    在这里插入图片描述
    外部的16个通道在转换时又分为规则通道和注入通道,其中规则通道最多有16路,注入通道最多有4路(注入通道貌似使用不多),下面简单介绍一下两种通道:
    规则通道
    规则通道顾名思义就是,最平常的通道、也是最常用的通道,平时的ADC转换都是用规则通道实现的。
    注入通道
    注入通道是相对于规则通道的,注入通道可以在规则通道转换时,强行插入转换,相当于一个“中断通道”吧。当有注入通道需要转换时,规则通道的转换会停止,优先执行注入通道的转换,当注入通道的转换执行完毕后,再回到之前规则通道进行转换。

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    总结
    在这里插入图片描述

    注入通道转换顺序
    和规则通道转换顺序的控制一样,注入通道的转换也是通过注入寄存器来控制,只不过只有一个JSQR寄存器来控制,控制关系如下:
    在这里插入图片描述

    在这里插入图片描述

    注:只有当JL=4的时候,注入通道的转换顺序才会按照JSQ1、JSQ2、JSQ3、JSQ4的顺序执行。当JL<4时,注入通道的转换顺序恰恰相反,也就是执行顺序为:JSQ4、JSQ3、JSQ2、JSQ1。

    ·

    2.ADC开关控制即触发源

    通过设置ADC_CR2寄存器的ADON位可给ADC上电。当第一次设置ADON位时,它将ADC从断 电状态下唤醒。
    ADC上电延迟一段时间后(tSTAB),再次设置ADON位时开始进行转换。
    通过清除ADON位可以停止转换,并将ADC置于断电模式。在这个模式中,ADC几乎不耗电(仅 几个μA)。

    ADC转换的输入、通道、转换顺序都已经说明了,但ADC转换是怎么触发的呢?就像通信协议一样,都要规定一个起始信号才能传输信息,ADC也需要一个触发信号来实行模/数转换。
    其一就是通过直接配置寄存器触发,通过配置控制寄存器CR2的ADON位,写1时开始转换,写0时停止转换。在程序运行过程中只要调用库函数,将CR2寄存器的ADON位置1就可以进行转换,比较好理解。
    另外,还可以通过内部定时器或者外部IO触发转换,也就是说可以利用内部时钟让ADC进行周期性的转换,也可以利用外部IO使ADC在需要时转换,具体的触发由控制寄存器CR2决定。
    ADC_CR2寄存器的详情如下:
    在这里插入图片描述

    3、 ADC时钟

    3.1、转换时间
    ADC的每一次信号转换都要时间,这个时间就是转换时间,转换时间由输入时钟和采样周期来决定。

    输入时钟 由于ADC在STM32中是挂载在APB2总线上的,所以ADC得时钟是由PCLK2(72MHz)经过分频得到的,分频因子由 RCC 时钟配置寄存器RCC_CFGR 的位 15:14 ADCPRE[1:0]设置,可以是 2/4/6/8
    分频,一般配置分频因子为8,即8分频得到ADC的输入时钟频率为9MHz。

    采样周期 采样周期是确立在输入时钟上的,配置采样周期可以确定使用多少个ADC时钟周期来对电压进行采样,采样的周期数可通过 ADC采样时间寄存器 ADC_SMPR1 和 ADC_SMPR2 中的 SMP[2:0]位设置,ADC_SMPR2 控制的是通道 0~9, ADC_SMPR1 控制的是通道 10~17。每个通道可以配置不同的采样周期,但最小的采样周期是1.5个周期,也就是说如果想最快时间采样就设置采样周期为1.5.

    转换时间 转换时间=采样时间+12.5个周期
    12.5个周期是固定的,一般我们设置 PCLK2=72M,经过 ADC 预分频器能分频到最大的时钟只能是 12M,采样周期设置为 1.5 个周期,算出最短的转换时间为 1.17us。

    由时钟控制器提供的ADCCLK时钟和PCLK2(APB2时钟)同步。RCC控制器为ADC时钟提供一个专用的可编程预分频器(STM32F103xx增强型产品:时钟为56MHz时为1μs(时钟为72MHz为1.17μs)
    在这里插入图片描述

    4.数据寄存器

    转换完成后的数据就存放在数据寄存器中,但数据的存放也分为规则通道转换数据和注入通道转换数据的。
    规则数据寄存器
    规则数据寄存器负责存放规则通道转换的数据,通过32位寄存器ADC_DR来存放。
    在这里插入图片描述
    注入数据寄存器
    注入通道转换的数据寄存器有4个,由于注入通道最多有4个,所以注入通道转换的数据都有固定的存放位置,不会跟规则寄存器那样产生数据覆盖的问题。 ADC_JDRx 是 32 位的,低 16 位有效,高 16 位保留,数据同样分为左对齐和右对齐,具体是以哪一种方式存放,由ADC_CR2 的 11 位 ALIGN 设置。
    在这里插入图片描述

    5、ADC看门狗

    在这里插入图片描述

    从框图中可以知道数据转换完成之后可以产生中断,有三种情况:
    规则通道转换完成中断
    规则通道数据转换完成之后,可以产生一个中断,可以在中断函数中读取规则数据寄存器的值。这也是单通道时读取数据的一种方法。
    注入通道转换完成中断
    注入通道数据转换完成之后,可以产生一个中断,并且也可以在中断中读取注入数据寄存器的值,达到读取数据的作用。
    模拟看门狗事件
    当输入的模拟量(电压)不再阈值范围内就会产生看门狗事件,就是用来监视输入的模拟量是否正常。

    以上中断的配置都由ADC_SR寄存器决定:
    在这里插入图片描述

    高阀值(ADC_HTR)
    在这里插入图片描述

    低阈值(ADC_LRT)
    在这里插入图片描述

    6、电压计算

    要知道,转换后的数据是一个12位的二进制数,我们需要把这个二进制数代表的模拟量(电压)用数字表示出来。比如测量的电压范围是0~3.3V,转换后的二进制数是x,因为12位ADC在转换时将电压的范围大小(也就是3.3)分为4096(2^12)份,所以转换后的二进制数x代表的真实电压的计算方法就是:
    y=3.3* x / 4096

    7、 时序图

    如下图所示,ADC在开始精确转换前需要一个稳定时间tSTAB。在开始ADC转换和14个时钟周期后,EOC标志被设置,16位ADC数据寄存器包含转换的结果。
    在这里插入图片描述

    代码示例:

    注:代码使用规则通道,程序使用了ADC1的通道1,对应IO口为PA1。

    初始化IO口

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
    	GPIO_InitTypeDef GPIO_InitStructure; 
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; 
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; 
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;   //设置为模拟输入
    	GPIO_Init(GPIOA, &GPIO_InitStructure); 
    

    ADC配置

    RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC时钟 一般不超过14MHZ 否则精度不准确  72MHZ/6=12MHZ
    	ADC_DeInit(ADC1);  //复位时钟
    	ADC_InitTypeDef ADC_InitStructure;
    	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC 工作模式:独立模式
    	ADC_InitStructure.ADC_ScanConvMode =  DISABLE; //AD 单通道模式;
    	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //AD 单次转换模式
    	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//转换由软件而不是外部触发启动
    	ADC_InitStructure.ADC_DataAlign =  ADC_DataAlign_Right; //ADC 数据右对齐;
    	ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的 ADC 通道的数目 1
    	ADC_Init(ADC1, &ADC_InitStructure); 
    	ADC_Cmd(ADC1,ENABLE);  //使能ADC1
    	ADC_ResetCalibration(ADC1);//重置指定的 ADC 的校准寄存器
    	ADC_StartCalibration(ADC1); //开始指定校准状态
    	while(ADC_GetResetCalibrationStatus(ADC1));   //等待复位校准结束
    	while(ADC_GetCalibrationStatus(ADC1));   //等待校 AD 准结束
    

    获取ADC 函数编写

    u16 Get_Adc(u8 ch)//获取ADC
    {	ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_239Cycles5); //设定ADC规则组	
    	ADC_SoftwareStartConvCmd(ADC1,ENABLE);  //使能软件启动
    	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
    	return 	ADC_GetConversionValue(ADC1);  //返回最后一次规则装换结果
    }
    
    
    u16 Get_Adc_Average(u8 ch,u8 times)  //获取ADC平均值
    {
    u32 temp_val=0;
    u8 t;
    for(t=0;t<times;t++)
    { 
    temp_val+=Get_Adc(ch);
    Delay_ms(5);
    }
    return temp_val/times;
    } 
    

    mian函数,电压计算

    temp=(float)adcx*(3.3/4096);
    

    代码仓库:https://gitee.com/bigtiger_king/stm32f103_ADC/tree/master/

    展开全文
  • 基于STM32F103的 ADC内部单路电压采集C代码,采用中断方式,精度可达1mV以内,使用串口接收数据,采集的数据不断发往串口,打开串口调试助手接收和保存数据。
  • 基于STM32F103的交流采集程序,通过ADC采集+DMA+软件滤波+均方根计算,直接算出交流信号的有效值,亲测好用,算法简单,耗时少,每一步所用时间均在程序中标注,方便使用。
  • 基于stm32f108c8t6的iic的oled屏幕和采集电压.rar
  • stm32F407ADC电压采集串口输出,采用均值滤波对采集的ad值进行处理...
  • STM32 ADC 采集输入电压

    千次阅读 2021-02-04 10:27:42
    1、电路 2.计算电压,adc使用12bit,(配置代码省略) 分压计算:VIN_ADC = R13/(R13+R17) VIN(输入电压) = (3.0*BAT_ADC/4096)*13.3
  • 电压信号采集是电子系统中常用的功能模块,本文针对于交流电压信号的采集,设计出了一种以STM32为核心的低功耗、高性能的交流电压采集系统。系统使用运算放大器对信号进行跟随,利用STM32中内置的ADC对信号进行模数...
  • 基于STM32电压采集系统设计.pdf
  • 解决了网上存在的如下问题:网上很多ADS1115驱动程序移植到STM32F407单片机上虽然可以采集电压,但是采集电压有问题,大部分程序只能采集到高8位,采集不到低8位(低8位始终为0),用万用表添加电压信号,只有当...
  • 1. ①电压输入范围 ADC 输入范围为:VREF- ≤ VIN ≤ VREF+。由 VREF-、VREF+ 、VDDA 、VSSA、这四个外部 引脚决定。 我们在设计原理图的时候一般把 VSSA 和 VREF-接地,把 VREF+和 VDDA 接 3V3,得到 ADC 的输入...
  • 本文介绍了STM32内部参考电压和ADC参考电压区别及使用。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,109
精华内容 2,043
关键字:

stm32电压采集