基于STM32F103C8T6四路AD采集数据显示在oled屏上非DMA传输方式(附百度网盘下载链接)

本文采用四路AD采集光照强度、烟雾浓度、一氧化碳、空气质量等四个物理量,并采用中位值平均滤波(防脉冲干扰平均滤波法)算法对偶然出现的脉冲性干扰,消除由其引起的采样值偏差。

  1. ADC简介

STM32F103C8T6有两个ADC,12位ADC是一种逐次逼近型模拟数字转换器。它有多达18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐的方式存储在16位数据寄存器中。

  1. 主要用到的ADC参数和函数

void ADC1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    ADC_InitTypeDef ADC_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
    
    RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置 ADC 分频因子 6 
    
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    ADC_DeInit(ADC1);    //将外设 ADC1 的全部寄存器重设为缺省值
    
    ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;//连续转化模式设置
    ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//数据左对齐
    ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//软件触发
    ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//独立模式
    ADC_InitStructure.ADC_NbrOfChannel=1;//通道数
    ADC_InitStructure.ADC_ScanConvMode=DISABLE;//扫描模式设置
    ADC_Init(ADC1,&ADC_InitStructure);
    
    ADC_Cmd(ADC1,ENABLE);//使能指定ADC外设
    
    ADC_ResetCalibration(ADC1);//使能复位校准
    while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准结束
    ADC_StartCalibration(ADC1);//开启AD校准
    while(ADC_GetCalibrationStatus(ADC1));//等待AD校准结束
}

u16 Get_ADC_Value(u8 channel)//ADC采样
{    
   ADC_RegularChannelConfig(ADC1,channel,1,ADC_SampleTime_239Cycles5);
     ADC_SoftwareStartConvCmd(ADC1,ENABLE);
     while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
     return ADC_GetConversionValue(ADC1);
}

void ADC_DeInit(ADC_TypeDef* ADCx) :将外设 ADCx 的全部寄存器重设为缺省值 ADC_ContinuousConvMode:用来设置是否开启连续转换模式,单次转换:DISABLE;连续转换:ENABLE,因为我们是单次转换,所以设置为DISABLE

ADC_DataAlign:用来设置 ADC 数据对齐方式是左对齐还是右对齐,ADC转换后的数据被保存到数据寄存器中(ADC_DR)的0~15位或16~32位,数据宽度为16位,ADC转换精度12位。左对齐则是把ADC转换后的数值最高位D12与存储区域的最高位Bit15对齐,存储区域的低4位无意义。右对齐则是ADC转换的数值最低位D0保存在存储区域的最低位Bit0,高四位无意义

ADC_ExternalTrigConv:用来设置启动规则转换组转换的外部事件 ,ADC在收到触发信号后才开始进行模数转换

ADC_Mode:ADC的模式非常多,包括独立模式,注入同步模式等等,而不同的ADC是共用通道的,当两个ADC采集同一个通道的先后顺序、时间间隔不同时,就会有多种模式。我们只使用了一个ADC,所以选择独立模式,参数为 ADC_Mode_Independent。

ADC_NbrOfChannel:保存要进行ADC数据转换的通道数,可以为1 ~ 16个。这里我们是单次采集一个通道,所以值为 1即可

ADC_ScanConvMode:用来设置是否开启扫描模式,当有多个通道需要采集信号时,可以把ADC配置为按一定的顺序轮流采集各通道的值。如果采集多个通道,必须开启此模式。这里我们是单次采集一个通道的信号,这里我们选择不开启 : DISABLE

注:以下函数都没有写形参和返回值,仅仅写出了它的功能,具体参见STM32F103固件库说明手册

ADC_Init():根据 ADC_InitStruct 中指定的参数初始化外设 ADCx 的寄存器

ADC_Cmd():使能或者失能指定的 ADC,:函数 ADC_Cmd 只能在其他 ADC 设置函数之后被调用

ADC_ResetCalibration(): 重置指定的 ADC 的校准寄存器

ADC_GetResetCalibrationStatus(): 获取 ADC 重置校准寄存器的状态 ,返回值: ADC 重置校准寄存器的新状态(SET 或者 RESET) ,当值为RESET时重置成功

ADC_StartCalibration():开始指定 ADC 的校准状态

ADC_GetCalibrationStatus(): 获取指定 ADC 的校准程序 ,返回值: ADC 校准的新状态

ADC_RegularChannelConfig ():设置指定 ADC 的规则组通道,设置它们的转化顺序和采样时间,RANK值是指在进行多通道扫描时,本通道的扫描顺序。例如通道4、5、6、7的RANK值被分配为4、3、2、1,则在ADC扫描时,扫描的顺序为通道7、6、5、4 。

ADC_SampleTime:用于配置本通道的采样周期,这里的周期指的是ADCCLK的时钟周期,ADC时钟频率越高,转换速度就越快,但ADC时钟有上限值,不能超过14Mhz。ADC的时钟(ADCCLK)为ADC预分频器的输出,而ADC预分频器的输入则为高速外设时钟(PCLK2)。PCLK2的常用时钟频率为72Mhz,可设置PCLK2为2、4、6、8分频。因为ADCCLK必须低于14Mhz,所以ADCCLK最高频率为PCLK2的8分频,即ADCCLK = 9Mhz.

STM32的ADC采样时间计算公式:T=采样周期+12.5个周期

本实验中ADC通道的转换时间:T= (239.5+12.5)x(1÷12) = 21us

注:12.5为固定周期

ADC_SoftwareStartConvCmd():使能或者失能指定的 ADC 的软件转换启动功能

ADC_GetFlagStatus();检查制定 ADC 标志位置 1 与否

ADC_FLAG 的值

u16 ADC_GetConversionValue(ADC_TypeDef* ADCx) :返回最近一次 ADCx 规则组的转换结果

  1. 中位值平均滤波(防脉冲干扰平均滤波法)

方法:“中位值滤波法"+“算术平均滤波法”

连续采样N个数据,去掉一个最大值和一个最小值,然后计算N-2个数据的算术平均值,N值的选取:3~14

优点:融合了两种滤波的优点。对于偶然出现的脉冲性干扰,可消除有其引起的采样值偏差。对周期干扰有良好的抑制作用,平滑度高,适于高频振荡的系统。

缺点:测量速度慢。

这里采用了一个二维数组来分别存储四个AD通道的采样值,然后分别进行计算,具体代码如下:

void middleAverageFilter()    //中位值平均滤波(防脉冲干扰平均滤波法)
{
    u16 i,j,k,g;
    u16 temp;
      u16 Sum_Value[ADC_Value_Size] = {0};
    u16 value_buf[ADC_Value_Size][ADC_Value_Number] = {0};
        for(g = 0 ; g < ADC_Value_Size ; g++)
        {
            for(i = 0; i < ADC_Value_Number; i++)
            {
                    value_buf[g][i] = Get_ADC_Value(g+0x04);

            }
        }

    /*从小到大冒泡排序*/    
        for(g = 0 ; g < ADC_Value_Size ; g++)
        {
            for(j = 0; j < ADC_Value_Number-1; j++)
            {
                    for(k = 0; k < ADC_Value_Number-j-1; k++)
                    {
                            if(value_buf[k] > value_buf[k+1])
                            {
                                    temp = value_buf[g][k];
                                    value_buf[g][k] = value_buf[g][k+1];
                                    value_buf[g][k+1] = temp;
                                
                            }
                    }
            }
      }
        for(g = 0 ; g < ADC_Value_Size ; g++)
        {
            for(i = 1; i < ADC_Value_Number-1; i++)
            {
                    Sum_Value[g] += value_buf[g][i];
            } 
      }
    Light_value =4096 - Sum_Value[0]/(ADC_Value_Number-2);
        m7_value=Sum_Value[1]/(ADC_Value_Number-2);
        m135_value =4096 - Sum_Value[2]/(ADC_Value_Number-2);
        m2_value = Sum_Value[3]/(ADC_Value_Number-2);        
}

  1. 传感器

本实验用到了 MQ-2 烟雾传感器、MQ-7一氧化碳传感器、MQ-135空气质量传感器和光敏电阻传感器。传感器这里就不再介绍啦,大家有传感器就应该有资料的,直接连在对应的引脚就可以用啦

4. 实验现象

  1. 百度网盘下载链接

链接:https://pan.baidu.com/s/1SpTvf2CjtPRw3GmdaW4xTA

提取码:1k6q

  • 8
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值