stm32和同类单片机用ADC采集多通道信号量

发布者:RainbowJoy最新更新时间:2024-10-08 来源: cnblogs关键字:stm32  ADC采集 手机看文章 扫描二维码
随时随地手机看文章

在此之前,使用stm32的ADC采集信号,使用到的通道就只有一个,用的时候也是别人写好的代码,没去研究,然而最近用GD32F350单片机作一个电源板时,要采集6个通道的信号,所以就仔细看了手册,有规则通道和注入通道两个概念,按概念,规则通道是按顺序采集,注入通道可以最多设备四个,有独立的保存采集数据的寄存器。如果超过4个就不能没每个每个通道对应一个数据寄存器;如果是规则通道,当通道数大于一时是可以先设置采集通道再读数据,但是我想要的是像手册上说大的一次就把6个通道的数据采集出来,但是规则通道只有一个数据寄存器,如何知道每一次采集的数据是对应哪一个通道呢?最后问了一个做电源有经验的人,他说使用DMA,设置数据长度为6个,然后每个通道采集的的数据就按顺序存到指定的地址了,真是一语惊醒梦中人啊。看看代码吧:


void dma_config(void)

{

    dma_parameter_struct dma_init_struct;


        rcu_periph_clock_enable(RCU_DMA);

    /* initialize DMA channel0 */

    dma_deinit(DMA_CH0);

    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;

    dma_init_struct.memory_addr = (uint32_t)ad_value;//指定DMA数据空间地址

    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;

    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;

    dma_init_struct.number = 48;

    dma_init_struct.periph_addr = (uint32_t)&(ADC_RDATA);

    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;

    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;

    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;

    dma_init(DMA_CH0, dma_init_struct);

    

    /* configure DMA mode */

    dma_circulation_enable(DMA_CH0);

    dma_memory_to_memory_disable(DMA_CH0);

    

    /* enable DMA channel0 */

    dma_channel_enable(DMA_CH0);

    dma_interrupt_enable(DMA_CH0, DMA_INT_FTF);

    nvic_irq_enable(DMA_Channel0_IRQn , 0U, 0U);//配置中断优先级

}


void ADCSampleInit(void)

{


//    rcu_periph_clock_enable(RCU_GPIOB);    

//    gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_15);

// gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_15);

    

    dma_config();    

    // ADCCLK = PCLK2/6

    rcu_adc_clock_config(RCU_ADCCK_APB2_DIV4);// ADC时钟27MHz

    rcu_periph_clock_enable(RCU_ADC);

    rcu_periph_clock_enable(RCU_GPIOA);

    

    //PA2,3,4,5,6

    gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE,

                                GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6);

    

    // ADC channel length config 设置规则组的数量,转换扫描时按此数量扫描

    adc_channel_length_config(ADC_REGULAR_CHANNEL, 6);


    /* ADC regular channel config */

    adc_regular_channel_config(0, ADC_CHANNEL_2, ADC_SAMPLETIME_1POINT5);

    adc_regular_channel_config(1, ADC_CHANNEL_3, ADC_SAMPLETIME_1POINT5);

    adc_regular_channel_config(2, ADC_CHANNEL_4, ADC_SAMPLETIME_1POINT5);

    adc_regular_channel_config(3, ADC_CHANNEL_5, ADC_SAMPLETIME_1POINT5);

    adc_regular_channel_config(4, ADC_CHANNEL_6, ADC_SAMPLETIME_1POINT5);

    //Vrefin

    adc_regular_channel_config(5, ADC_CHANNEL_17, ADC_SAMPLETIME_13POINT5);//ADC_SAMPLETIME_13POINT5 1515 //ADC_SAMPLETIME_28POINT5 1462

    //adc_regular_channel_config(5, ADC_CHANNEL_16, ADC_SAMPLETIME_13POINT5);

    // Vrefin enable

    adc_tempsensor_vrefint_enable();

    /* ADC external trigger enable */

    adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);

    /* ADC external trigger source config */

    adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE);

        

    /* ADC data alignment config */

    adc_data_alignment_config(ADC_DATAALIGN_RIGHT);//数据为右对齐

    /* enable ADC interface */

    adc_enable();

    /* ADC calibration and reset calibration */

    adc_calibration_enable();

    /* ADC SCAN function enable */

    adc_special_function_config(ADC_SCAN_MODE, ENABLE);//使能扫描模式

    /* ADC continuous mode function enable */        

    adc_special_function_config(ADC_CONTINUOUS_MODE, ENABLE); //连续模式

    /* ADC DMA function enable */

    adc_dma_mode_enable();//使用ADC DMA, ADC的数据将会存入DMA模块中,这是定义的DMA数据空间为ad_value[]

    

    adc_software_trigger_enable(ADC_REGULAR_CHANNEL);// 软件出发一次采样


原来就这个简单。

这里还要注意一个问题,就是采样时间,采样时间越短,输入的阻抗越小,这是如果你的信号是经过电阻分压后接入单片机的,那输入阻抗会改变电路设计上的分压比例,这时就要通过测量校准实际的比例值,比如电压经过300k+200K的电阻接到地,从两个电阻中间取信号,按电阻比例算分压比例是2/(3+2)=0.4,但若设置采样时间为1.5T,实际测出的比例是0.3355。


另一个是基准电压问题,如果VDDA不怎么稳定,会导致调试代码是容易中断,还有就是采集到的信号和实际偏差很大,这是可以通过采集弹片内部1.2V基准电压Vrefin得到的值反推出实际的VDDA的值,即实际采样值Vin=1.2xVrefinADC/VrefinADC.


关键字:stm32  ADC采集 引用地址:stm32和同类单片机用ADC采集多通道信号量

上一篇:stm32——ucos的中断使用
下一篇:stm32变更外部晶振时时钟配置

推荐阅读最新更新时间:2024-11-12 14:43

STM32串口用中断还是用轮询
1.从轮询到中断 很多同学都不喜欢用中断,而偏爱用轮询的操作方式。 这是不是和我们的天性有关呢?每个人都喜欢一切尽在掌握中,肯定都不喜欢被打断。我们常常都有这样的经验:正在跟别人说一件事,然后突然有个电话打进来,Call打完后突然记不起来刚才讲到哪了!这种糟糕的体验对我们影响是如此深刻,以至于我们认定机器可能也是这样吧,频繁的中断会不会把事情搞乱呢?好在机器虽然大部分时间都比人笨一些,但在处理这种问题上却能做到一丝不苟。机器在中断来的时候总会老老实实地先把当前正在做的记录下来,然后转去处理中断事件,中断处理完后分毫不差地恢复原来的工作。 仔细想一想,我们是不是也可以在接电话前先用个小本儿记录一下正在讲的事情呢?我们为什么没有这么做
[单片机]
STM32的通用定时器
STM32F1 的定时器非常多,由 2 个基本定时器(TIM6、TIM7)、4 个通用定时器(TIM2-TIM5)和 2 个高级定时器(TIM1、TIM8)组成。 1、定时器有哪些,以及对应有什么功能 (1)基本定时器: 功能最为简单,类似于 51 单片机内定时器。 (2)通用定时器: 是在基本定时器的基础上扩展而来,增加了输入捕获(可以测量输入信号的脉宽)与输出比较(产生输出波形)等功能。 (3)高级定时器: 是在通用定时器基础上扩展而来,增加了可编程死区互补输出、重复计数器、带刹车(断路)功能,这些功能主要针对工业电机控制方面。 2、通用定时器配置 #include stm32f10x.h
[单片机]
RT-Thread的STM32系列外设驱动添加 ---- 以PWM外设为例
一、准备 官方教程:STM32系列外设驱动添加指南.md。 PWM驱动官方文档:RT-Thread设备和驱动 之 PWM设备。 本博客基于的BSP为stm32f103-dofly-lyc8,可到官网下载,BSP制作教程:RT-Thread ---- STM32系列BSP的制作教程总结。 二、个人总结 1、按照教程步骤,按PWM设备驱动的需求更改。 2、STMCubeMx配置如下: 3、在Kconfig中添加pwm驱动。代码如下 4、menuconfig 中勾选 5、scons --target=mdk5 生成新工程。 6、代码示例,是一盏LED灯亮度渐变。 #define LE
[单片机]
RT-Thread的<font color='red'>STM32</font>系列外设驱动添加 ---- 以PWM外设为例
STM32在线升级OTA
简介 本文主要讲解在线升级(OTA)的基础知识, 主要是针对IAP OTA从原理分析, 分区划分, 到代码编写和实验验证等过程阐述这一过程. 帮助大家加深对OTA的认识. 1. OTA基础知识 什么是BootLoader? BootLoader可以理解成是引导程序, 它的作用是启动正式的App应用程序. 换言之, BootLoader是一个程序, App也是一个程序, BootLoader程序是用于启动App程序的. STM32中的程序在哪儿? 正常情况下, 我们写的程序都是放在STM32片内Flash中(暂不考虑外扩Flash). 我们写的代码最终会变成二进制文件, 放进Flash中 感兴趣的话可以在Keil De
[单片机]
<font color='red'>STM32</font>在线升级OTA
关于stm32通信协议:软件模拟SPI、软件模拟I2C的总结
趁着帮老师代上嵌入式实验课的机会,又重新熟悉了一遍stm32的通信协议:串口协议、SPI协议、I2C协议、RS485协议。大概半年前,是过了一遍的,但也只停留于读了遍代码,跑了下例程,最近又过了一遍(自己仔细的看了一遍,老师还给我们讲了一遍,自己又讲了一遍),然后还写了一遍软件模拟SPI、软件模拟I2C的代码,才彻底的懂了个皮毛 ,:)。稍微总结下吧,总结的不好,都是自己的理解,仅供参考,主要说软件模拟SPI、I2C,硬件SPI和硬件I2C就不说了。 串口协议 串口协议没什么可说的,现在常用的串口协议,是基于以前的RS232的协议,因为RS232的引脚太多而改进过来的。 物理层只用三根引脚:TXD、RXD、GND(最好接,不然
[单片机]
一阶互补滤波应用到stm32 ADC采集
大家都知道,adc采集,不管分辨率高低,特别是采集电压电流的值都是有一定漂移的,比如漂移个100mv左右是很正常的现象。 很多人都是用平均滤波法,这里我想说的是其实没有用,我之前就一直用的这个,真心效果很差。 其实这个问题可以用 平均滤波 加 一阶互补滤波 比较完美的滤除波动。 我这边只用平均滤波漂移在100mv,加上互补滤波后漂移基本只有10mv。已经算是相当完美了。 放小10倍的话,你的ad值基本都完全恒定了。 下面是代码,一阶互补滤波思想我就不介绍了,其实就是一个权重的问题,你更相信哪一时刻的值?不懂的自行百度。 void DEVICE_INFO::TX_updata() { //使用一阶
[单片机]
一个关于STM32 CAN出错恢复的话题
最近有个STM32 用户咨询: 最近在使用stm32f105做双can通信,can驱动芯片使用的TJA1042,发现将canH canL 短路再放开以后,can出错恢复不回来?之前在K40上使用的时候没有这个问题,不知道这个情况大家有什么指导建议啊? 另外,他还附上了基于STM32CUBEMX工具配置的相关代码如下: hcan1.Instance = CAN1; hcan1.Init.Prescaler = 2; hcan1.Init.Mode = CAN_MODE_NORMAL; hcan1.Init.SJW = CAN_SJW_1TQ; hcan1.Init.BS1 = CAN_BS1_8TQ; hc
[单片机]
一个关于<font color='red'>STM32</font> CAN出错恢复的话题
基于STM32的便携式二氧化碳监测仪设计
CO2浓度的检测方法大致分化学方法和物理方法。CO2浓度检测方法有滴定法、热催化法、气敏法、电化学法,这些属于化学方法,这些方法普遍存在价格贵,普适性差等问题,且测量精度较低。而物理的方法有超声波法、气相色谱法以及众多借助于光学来实现检测的方法。也有像光声光谱法这种化学和物理结合的方法。吸收光谱法的依据是不同化学结构的气体分子对不同波长的辐射的吸收程度不同,CO2气体分子对特定波长的红外光有强烈的吸收。 目前各种检测用的CO2传感器主要有固体电解质式、钛酸钡复合氧化物电容式、电导变化型厚膜式等,这些传感器存在对气体的选择性差、易出现误报、需要频繁校准、使用寿命较短等不足。而红外吸收型CO2传感器具有测量范围宽、灵敏度高、响应
[单片机]
基于<font color='red'>STM32</font>的便携式二氧化碳监测仪设计
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved