野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 327|回复: 0

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

[复制链接]
发表于 2024-8-21 20:01:25 | 显示全部楼层 |阅读模式
各位大佬,我用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[i];
    }
    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[i] = PT100_BUFF.pt100_Val[0];
        }


回复

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-9-19 09:29 , Processed in 0.067789 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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