STM32F103C8T6四路AD采集数据显示在oled屏上非DMA传输方式附百度网盘下载链接
本文采用四路AD采集光照强度、烟雾浓度、一氧化碳、空气质量等四个物理量,并采用中位值平均滤波(防脉冲干扰平均滤波法)算法对偶然出现的脉冲性干扰,消除由其引起的采样值偏差。
STM32F103C8T6有两个ADC,12位ADC是一种逐次逼近型模拟数字转换器。它有多达18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐的方式存储在16位数据寄存器中。
-
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 与否
u16 ADC_GetConversionValue(ADC_TypeDef* ADCx) :返回最近一次 ADCx 规则组的转换结果
方法:“中位值滤波法" “算术平均滤波法”
连续采样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);
-
}
本实验用到了 MQ-2 烟雾传感器、MQ-7一氧化碳传感器、MQ-135空气质量传感器和光敏电阻传感器。传感器这里就不再介绍啦,大家有传感器就应该有资料的,直接连在对应的引脚就可以用啦。
4. 实验现象
链接:https://pan.百度.com/s/1SpTvf2CjtPRw3GmdaW4xTA
提取码:1k6q
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgabjhe
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13