OpenEdv-开源电子网

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

求救各位大佬关于stm32f030 ADC配置以及数据跳动问题

[复制链接]

3

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
52
金钱
52
注册时间
2024-3-16
在线时间
9 小时
发表于 2024-8-21 20:06:03 | 显示全部楼层 |阅读模式
5金钱
各位大佬,我用stm32f030f4p6 单通道ADC单次采样+DMA中断搬运数据,通过模拟开关4052切换通道采样参考电阻和热电阻电压。已经把采样周期调到最高了还是有几十的跳动,把数据进行中值平均滤波之后,参考电阻的ADC值会好很多基本上跳1~2有时会有4左右上下,但是热电阻还会有十几的跳动。是程序配置有问题,还是ADC单通道单次转换在main里循环开启转换一开始都会不准?改成连续转换得到比如30个值通过DMA搬运到一个数组中,然后切换模拟开关再采集完成所有通道再做滤波会有效果吗。
我下面的代码不知道是不是有问题望指正
#include "adc.h"

ADC_BUFF PT100_BUFF = {0};

void ADC_PT100_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    ADC_InitTypeDef  ADC_InitStruct = {0};
    NVIC_InitTypeDef NVIC_InitStruct = {0};
    DMA_InitTypeDef  DMA_InitStruct = {0};

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);   //开启GPIOC的RCC时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);   //开启ADC1的RCC时钟
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);    //开启DMA1的RCC时钟
    ADC_ClockModeConfig(ADC1, ADC_ClockMode_SynClkDiv4);

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;//单次转换
    ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
    ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//无外部触发
    ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;//精度12位
    ADC_Init(ADC1, &ADC_InitStruct);

    ADC_ChannelConfig(ADC1, ADC_Channel_1, ADC_SampleTime_239_5Cycles);
    ADC_GetCalibrationFactor(ADC1);
    ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_OneShot);
    ADC_DMACmd(ADC1, ENABLE);   
    ADC_Cmd(ADC1, ENABLE);
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));

    DMA_InitStruct.DMA_BufferSize = 1;//初始化NDTR计数值
    DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;//从外设到内存
    DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)PT100_BUFF.pt100_Val;//内存基地址
    DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;//*dis
    DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)(&ADC1->DR);
    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStruct.DMA_Priority = DMA_Priority_High;   
    DMA_Init(DMA1_Channel1, &DMA_InitStruct);
    DMA_Cmd(DMA1_Channel1, ENABLE);

    DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
    NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel1_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
    NVIC_Init(&NVIC_InitStruct);


}
#if 0
uint16_t Get_Channel_Value()
{
    ADC_ChannelConfig(ADC1, ADC_Channel_1 , ADC_SampleTime_239_5Cycles);
    ADC_StartOfConversion(ADC1);
    while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
    return ADC_GetConversionValue(ADC1);
}
#endif
#if 1
void DMA1_Channel1_IRQHandler(void)
{
    if(DMA_GetITStatus(DMA1_IT_TC1))
    {
        DMA_ClearITPendingBit(DMA1_IT_TC1);        
        DMA_Cmd(DMA1_Channel1,DISABLE);
        DMA_SetCurrDataCounter(DMA1_Channel1,1);
//        DMA_ClearITPendingBit(DMA1_IT_TC1);
        DMA_Cmd(DMA1_Channel1,ENABLE);
        PT100_BUFF.adcFlag = 1;
    }
}
#endif
//中值平均滤波
uint16_t Get_Adc_Average(uint16_t ARRY[])
{
    int i,n,m,tmp=0,sum=0;
    for(n=0;n<51;n++)
    {
        for(m=0;m<(51-n);m++)
        {
            if(ARRY[m]>ARRY[m+1])
            {
                tmp = ARRY[m];
                ARRY[m] = ARRY[m+1];
                ARRY[m+1] = tmp;
            }
        }
    }   
    for(i=1;i<51;i++)
    {
        sum+=ARRY;
    }
    return sum/50;     
}




#ifndef __ADC_H__
#define __ADC_H__

#include "stm32F0xx.h"
#include "systick.h"

typedef struct
{
    uint16_t pt100_Val[52];
    uint8_t adcFlag;
}ADC_BUFF;

extern ADC_BUFF PT100_BUFF;

extern void ADC_PT100_Init(void);
extern uint16_t Get_Channel_Value();
extern uint16_t Get_Adc_Average(uint16_t ARRY[]);
#endif



int main()
{   
    Systick_Init(48);
    Delay_Ms(1000);//启动延时
    GPIO_Int();
    GPIOInfrared_Config();
    RCC_GetClocksFreq(&RCC_Clocks);   
    ADC_PT100_Init();
   
    while(1)
    {   
        
        uint16_t adcarr[52] = {0} , adcarr1[52] = {0} , adcarr2[52] = {0} , adcarr3[52] = {0};//存放adc值以用来进行中值平均滤波的存储数组

        GPIO_ResetBits(GPIOA,GPIO_Pin_5);//使能cd4052 INH        
        //cd4052地址选择 A=0,B=0  选择接通通道为X0,Y0 采集PT100_1adc
      
        GPIO_ResetBits(GPIOA,GPIO_Pin_3);
        GPIO_ResetBits(GPIOA,GPIO_Pin_4);
        //Tim_Delay_Us(50);
        Delay_Ms(10);      
        for(i=0;i<52;i++)
        {
            ADC_StartOfConversion(ADC1);//开启规则通道转换
            while(!PT100_BUFF.adcFlag);
            PT100_BUFF.adcFlag = 0;
            adcarr = PT100_BUFF.pt100_Val[0];
        }

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2024-8-31 22:53:48 | 显示全部楼层
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-22 07:20

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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