OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6341|回复: 8

ADC+DMA采集,相邻通道有干扰问题

[复制链接]

11

主题

49

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2016-8-24
在线时间
65 小时
发表于 2016-9-8 15:31:55 | 显示全部楼层 |阅读模式
5金钱
采用原子精英板子做的ADC采集程序,用PC0-PC3做为模拟输入引脚,程序已经可以在LCD上显示,但接上PC0接上3.3V后,PC0的数字量为4095,但PC1由原来的1900+变为2800+,另两个引脚的值变化不大,或者PC1接上3.3V后,效果类似于PC0接上3.3V的效果。

ADC的代码:
#include "adc.h"
#include "delay.h"
#define M 4 //4路AD
          
                  
//初始化ADC
//ADC1_CH10-->C0       
//ADC1_CH11-->C1       
//ADC1_CH12-->C2
//ADC1_CH13-->C3       


void  Adc_Init(void)
{
       GPIO_InitTypeDef  GPIO_InitStructure;
            ADC_InitTypeDef  ADC_InitStructure;
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC| RCC_APB2Periph_ADC1 , ENABLE );   
                                                                  //RCC_APB2Periph_GPIOx,x=GPIOx
            RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //72M/6=12,ADC最大时间不能超过14M   
        //PC0--ADC_IN10  PC1--ADC_IN11  PC2--ADC_IN12  PC3--ADC_IN13                  
        //PC0~3  4路作为模拟通道输入引脚                        
            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;         //PC0/1/2/3 作为模拟通道输入引脚
            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;               
                   GPIO_Init(GPIOC, &GPIO_InitStructure);

//**************************************ADC设置

                   ADC_DeInit(ADC1);  //将外设 ADC1 的全部寄存器重设为缺省值
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC工作模式:ADC1和ADC2工作在独立模式
        ADC_InitStructure.ADC_ScanConvMode =ENABLE;        //多信道扫描模式
        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;  //模数转换工作在连续转换模式
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;   //外部触发转换关闭
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐
        ADC_InitStructure.ADC_NbrOfChannel = 4;        //此处开6个信道(可开的为1~16)
        ADC_Init(ADC1, &ADC_InitStructure);        //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器

                //ADC常规信道配置
        //ADC1,ADC通道x,规则采样顺序值为y,采样时间为239.5周期
        ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5 );               
        ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5 );
        ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_239Cycles5 );               
        ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5 );

         // 开启ADC的DMA支持(要实现DMA功能,还需独立配置DMA通道等参数)
          ADC_DMACmd(ADC1, ENABLE);       //使能ADC1的DMA传输         
         ADC_Cmd(ADC1, ENABLE);           //使能指定的ADC1
         ADC_ResetCalibration(ADC1);        //复位指定的ADC1的校准寄存器
         while(ADC_GetResetCalibrationStatus(ADC1));        //获取ADC1复位校准寄存器的状态,设置状态则等待
         ADC_StartCalibration(ADC1);                //开始指定ADC1的校准状态
         while(ADC_GetCalibrationStatus(ADC1));                //获取指定ADC1的校准程序,设置状态则等待
}                                  

DMA的代码 :
#include "dma.h"

//DMA1的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从外设模式->存储器/16位数据宽度/存储器增量模式
//DMA_CHxMA通道CHx                   //cpar:外设地址 //cmar:存储器地址//cndtr:数据传输量
void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{          
  DMA_InitTypeDef DMA_InitStructure;
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);        //使能DMA时钟
       
  DMA_DeInit(DMA_CHx);   //将DMA的通道1寄存器重设为缺省值

       
        DMA_InitStructure.DMA_PeripheralBaseAddr = cpar;  //DMA外设基地址
        DMA_InitStructure.DMA_MemoryBaseAddr = cmar;  //DMA内存基地址
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //数据传输方向,从外设发送到内存  DMA_CCRX位4
        DMA_InitStructure.DMA_BufferSize = cndtr;  //DMA通道的DMA缓存的大小
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  //外设数据宽度为16位
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //内存数据宽度为16位
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //工作在循环缓存模式
        DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道 x拥有高优先级
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
        DMA_Init(DMA_CHx, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器                 
}


主函数的代码:
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "adc.h"
#include "dma.h"
         
#define ADC1_DR_Address    ((uint32_t)0x4001244C)
#define N 10 //取50次平均值
#define M 4 //4路AD
u16 value[N][M];//存储ADC转换后N*M个数字量的数据
u16 aftervalue[M];//存储M个通道数字量的平均值
float avalue[M];//滤波后的通道采样电压值
u8 i=0,j=0;

////////////////滤波函数/////////////////////////////////////////////////////////////////////////                       
void filter(void)
{
        int sum = 0;//sum 通道采样数值的总和
        u8 count;//
        for(i=0;i<M;i++)//每个通道进行循环滤波
        {
                for(count=0;count<N;count++)//采样N次循环
                {
                         sum+=value[count][i];//计算出N次采样值的总和
    }
    aftervalue[i]=sum/N;//求出通道数字量的平均值
    sum=0;//清零便于下次重新计算
  }
}
/////////////////////////////主程序////////////////////////////////////////////////////////////       
int main(void)
{
        u8 x=0;
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
        delay_init();                     //延时函数初始化          
        uart_init(115200);                 //串口初始化为115200
        LED_Init();                                  //初始化与LED连接的硬件接口
        LCD_Init();
        Adc_Init();                                  //ADC初始化
        POINT_COLOR=RED;//设置字体为红色
        LCD_ShowString(60,8,200,16,16,"WARSHIP_STM32");       
        LCD_ShowString(60,24,200,16,16,"ADC+DMA TEST");       

        //显示提示信息
        POINT_COLOR=BLUE;//设置字体为蓝色
        LCD_ShowString(60,40,200,16,16,"ADC_CH0_VAL:");
        LCD_ShowString(60,56,200,16,16,"ADC_CH1_VAL:");
        LCD_ShowString(60,72,200,16,16,"ADC_CH2_VAL:");
        LCD_ShowString(60,88,200,16,16,"ADC_CH3_VAL:");          

        POINT_COLOR=BRRED;
        LCD_ShowString(60,168,200,16,16,"ADC_CH0_VOL:0.000V");       
        LCD_ShowString(60,184,200,16,16,"ADC_CH1_VOL:0.000V");       
        LCD_ShowString(60,200,200,16,16,"ADC_CH2_VOL:0.000V");       
        LCD_ShowString(60,216,200,16,16,"ADC_CH3_VOL:0.000V");       
         
        MYDMA_Config(DMA1_Channel1,(u32)&ADC1->DR,(u32)&value,M*N);//初始化DMA
        ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件打开ADC转换
        DMA_Cmd(DMA1_Channel1, ENABLE);        //打开DMA功能

  while(1)
        {               
                filter();//滤波,此处函数一定不能省,否则ADC不能正常工作
                POINT_COLOR=BLUE;//设置字体为蓝色
                LCD_ShowxNum(156,40,aftervalue[0],4,16,0);//显示ADC的值       
                LCD_ShowxNum(156,56,aftervalue[1],4,16,0);//显示ADC的值       
                LCD_ShowxNum(156,72,aftervalue[2],4,16,0);//显示ADC的值       
                LCD_ShowxNum(156,88,aftervalue[3],4,16,0);//显示ADC的值                       

               
///////////////计算出每个通道数字量对应的电压值的整数部分/////
                for(i=0;i<M;i++)
                {
       avalue[i]=(float)aftervalue[i]*(3.3/4096);
                         aftervalue[i]=avalue[i];
    }

/////////////////显示整数部分/////////////////////               
                LCD_ShowxNum(156,168, aftervalue[0],1,16,0);//显示电压值
                LCD_ShowxNum(156,184, aftervalue[1],1,16,0);//显示电压值
                LCD_ShowxNum(156,200, aftervalue[2],1,16,0);//显示电压值
                LCD_ShowxNum(156,216, aftervalue[3],1,16,0);//显示电压值

               
//////////////计算出每个通道数字量对应的电压值的小数部分///////
                for(i=0;i<M;i++)
                {
       avalue[i]-=aftervalue[i];
                         avalue[i]*=1000;//放大1000倍进行显示
    }
/////////////////显示小数部分////////////////////               
                        LCD_ShowxNum(172,168,avalue[0],3,16,0X80);
                        LCD_ShowxNum(172,184,avalue[1],3,16,0X80);
                        LCD_ShowxNum(172,200,avalue[2],3,16,0X80);
                        LCD_ShowxNum(172,216,avalue[3],3,16,0X80);

                x++;
                if(x==12)x=0;
                LED0=!LED0;         
                delay_ms(200);                       
        }               
          
}
请教各位大神,是怎么回事!!!!!!




PC1接3.3V

PC1接3.3V

PC0接3.3V

PC0接3.3V

引脚悬空

引脚悬空

最佳答案

查看完整内容[请看2#楼]

1, PC0接3.3V,PC1接GND,读取结果如何? 2,单独测试PC0,PC1(不用DMA),测试结果如何?
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165516
金钱
165516
注册时间
2010-12-1
在线时间
2116 小时
发表于 2016-9-8 15:31:56 | 显示全部楼层
1, PC0接3.3V,PC1接GND,读取结果如何?
2,单独测试PC0,PC1(不用DMA),测试结果如何?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

11

主题

49

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2016-8-24
在线时间
65 小时
 楼主| 发表于 2016-9-8 15:33:03 | 显示全部楼层
怎么字母变表情了。。。。
回复

使用道具 举报

11

主题

49

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2016-8-24
在线时间
65 小时
 楼主| 发表于 2016-9-8 15:46:17 | 显示全部楼层
@正点原子 原子哥,帮忙看下,什么问题
回复

使用道具 举报

11

主题

49

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2016-8-24
在线时间
65 小时
 楼主| 发表于 2016-9-8 18:49:50 | 显示全部楼层
正点原子 发表于 2016-9-8 17:28
1, PC0接3.3V,PC1接GND,读取结果如何?
2,单独测试PC0,PC1(不用DMA),测试结果如何?

原子哥,经过测试:
纯ADC多路采集,会有,但没有加DMA的大,干扰在0.2V左右,PC0为3.098左右V,PC1为0V,PC2变化不大,是正常悬空的跳动。

ADC+DMA采集的,干扰在0.5V左右,PC0为3.299V,PC1为0V,PC2就只有1V了。

回复

使用道具 举报

11

主题

49

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2016-8-24
在线时间
65 小时
 楼主| 发表于 2016-9-8 18:53:19 | 显示全部楼层
本帖最后由 qjk9520 于 2016-9-8 19:45 编辑
正点原子 发表于 2016-9-8 17:28
1, PC0接3.3V,PC1接GND,读取结果如何?
2,单独测试PC0,PC1(不用DMA),测试结果如何?

纯ADC采集我也就变了这里了,ADC_InitStructure.ADC_NbrOfChannel = 4; 这里改为1了。
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;  这里改为disable
ADC_InitStructure.ADC_ScanConvMode =ENABLE;这里改为disable
其它的就是基本的变化了。。
回复

使用道具 举报

11

主题

49

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2016-8-24
在线时间
65 小时
 楼主| 发表于 2016-9-9 09:09:10 | 显示全部楼层
正点原子 发表于 2016-9-8 17:28
1, PC0接3.3V,PC1接GND,读取结果如何?
2,单独测试PC0,PC1(不用DMA),测试结果如何?

原子哥,早上测试又有新发现,之前的扫描周期为239.5,纯ADC的干扰在0.2V左右,改为55.5后,相邻通道的干扰在0.4的样子,DMA的没有变化。是我程序有问题吗,我仔细调过,也对照过,查过资料,也不知道哪里有问题了,麻烦告诉我下。
回复

使用道具 举报

2

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
91
金钱
91
注册时间
2016-7-21
在线时间
26 小时
发表于 2016-9-13 15:47:44 | 显示全部楼层
请问,滤波函数为什么不能省?
回复

使用道具 举报

1

主题

8

帖子

0

精华

新手上路

积分
40
金钱
40
注册时间
2019-4-29
在线时间
15 小时
发表于 2020-2-15 14:31:50 | 显示全部楼层
我也是受其他通道干扰 解决方法出来了吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-20 17:03

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表