单片机:实现数字滤波(附带源码)

单片机:实现数字滤波

1. 项目背景与目标

数字滤波是处理信号噪声和提高信号质量的重要技术,广泛应用于各种信号处理场景,如温度传感器、压力传感器、音频处理等。在嵌入式系统中,数字滤波主要用于对采集到的模拟信号进行去噪或平滑处理,以便提取有效信息。

常见的数字滤波方法包括:

  • 平均滤波:通过计算多个数据点的平均值来消除噪声。
  • 中值滤波:通过选择数据窗口中的中位数来过滤异常值。
  • 低通滤波:对高频信号进行衰减,仅保留低频信号。

本项目将实现一种简单的平均滤波算法,使用STM32单片机对传感器数据进行滤波处理。

2. 硬件设计
2.1 硬件组件
  • 单片机:例如STM32系列单片机,内置ADC模块。
  • 模拟信号源:例如温度传感器(如LM35)、光敏电阻等。
  • 显示设备(可选):LCD或串口显示用于展示滤波后的数据。
2.2 硬件连接
  • 模拟信号源:连接到STM32的ADC输入引脚(例如PA0、PA1等)。
  • 显示设备:如LCD、数码管或通过串口输出结果。
3. 数字滤波原理

本项目使用的是平均滤波方法。其基本思想是通过对信号序列进行平滑处理,消除高频噪声。具体做法是对信号进行一个滑动窗口操作,计算该窗口内信号的平均值,并将其作为输出。

假设采样信号序列为x[n],其滤波结果y[n]为:

其中,M是滑动窗口的大小,通常为3、5、7等。

4. 软件设计
4.1 设计思路
  1. 配置ADC读取模拟信号。
  2. 对读取到的ADC值进行平均滤波处理。
  3. 将滤波后的结果通过串口或显示设备输出。
4.2 代码实现
#include "stm32f4xx_hal.h"
#include <stdio.h>

#define ADC_CHANNEL   ADC_CHANNEL_0  // 选择通道0(PA0)

// ADC句柄
ADC_HandleTypeDef hadc1;

// 滤波窗口大小
#define FILTER_WINDOW_SIZE 5

// 滤波数据缓冲区
uint32_t adc_buffer[FILTER_WINDOW_SIZE] = {0};
uint8_t filter_index = 0;

// 初始化ADC
void ADC_Init(void) {
    __HAL_RCC_ADC1_CLK_ENABLE();  // 启用ADC1的时钟

    // 配置ADC输入引脚
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOA_CLK_ENABLE();  // 启用GPIOA时钟

    // 配置PA0为模拟输入模式
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // 配置ADC参数
    hadc1.Instance = ADC1;
    hadc1.Init.Resolution = ADC_RESOLUTION_12B;  // 12位分辨率
    hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;  // 单通道模式
    hadc1.Init.ContinuousConvMode = DISABLE;  // 非连续转换模式
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;  // 外部触发模式
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;  // 数据对齐方式:右对齐
    hadc1.Init.NbrOfConversion = 1;  // 进行单次转换
    hadc1.Init.DMAContinuousRequests = DISABLE;  // 不使用DMA

    // 初始化ADC
    HAL_ADC_Init(&hadc1);

    // 配置ADC通道(选择通道0,PA0)
    ADC_ChannelConfig();
}

// 配置ADC通道
void ADC_ChannelConfig(void) {
    ADC_ChannelConfTypeDef sConfig = {0};
    sConfig.Channel = ADC_CHANNEL;  // 设置通道
    sConfig.Rank = ADC_REGULAR_RANK_1;  // 第1通道
    sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;  // 设置采样时间
    sConfig.Offset = 0;

    // 配置ADC通道
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}

// 获取ADC值
uint32_t ADC_Read(void) {
    // 启动ADC转换
    HAL_ADC_Start(&hadc1);

    // 等待ADC转换完成
    if (HAL_ADC_PollForConversion(&hadc1, 1000) == HAL_OK) {
        // 获取ADC值
        return HAL_ADC_GetValue(&hadc1);
    }
    return 0;  // 如果转换失败,返回0
}

// 计算滤波后的结果
uint32_t Filter_Average(void) {
    uint32_t sum = 0;
    for (uint8_t i = 0; i < FILTER_WINDOW_SIZE; i++) {
        sum += adc_buffer[i];
    }
    return sum / FILTER_WINDOW_SIZE;
}

// 更新滤波缓冲区
void Filter_Update(uint32_t new_value) {
    adc_buffer[filter_index] = new_value;
    filter_index = (filter_index + 1) % FILTER_WINDOW_SIZE;  // 环形缓冲区
}

// 主函数
int main(void) {
    HAL_Init();  // 初始化HAL库
    ADC_Init();  // 初始化ADC

    // 主循环
    while (1) {
        uint32_t adc_value = ADC_Read();  // 获取ADC采样值

        // 更新滤波器数据
        Filter_Update(adc_value);

        // 获取滤波后的值
        uint32_t filtered_value = Filter_Average();

        // 输出ADC值和滤波后的值(通过串口或其他方式)
        printf("Raw ADC Value: %lu, Filtered Value: %lu\n", adc_value, filtered_value);

        HAL_Delay(500);  // 每隔500ms进行一次采样
    }
}
5. 代码解释
  1. ADC初始化

    • ADC_Init()函数中,初始化了ADC模块并配置了PA0引脚为模拟输入。配置了ADC为12位分辨率,单通道模式,并且设置了适当的采样时间。
  2. 滤波窗口和缓冲区

    • 使用一个大小为FILTER_WINDOW_SIZE(在本例中为5)的环形缓冲区adc_buffer[]来存储最近的几个ADC采样值。
    • filter_index用于控制缓冲区的写入位置,确保新的数据会覆盖旧的数据,保持缓冲区的最新数据。
  3. 平均滤波

    • Filter_Average()函数计算缓冲区中所有值的平均值,即对采样值进行平滑处理。这里的FILTER_WINDOW_SIZE定义了滤波窗口的大小,通常选择3、5、7等小值,来平衡滤波效果与实时性。
  4. 更新滤波缓冲区

    • Filter_Update()函数将新采样值添加到缓冲区,并更新filter_index,实现环形缓冲区的效果。
  5. 主循环

    • 在主循环中,通过ADC_Read()函数获取ADC值,然后通过Filter_Update()函数更新缓冲区,最后使用Filter_Average()获得滤波后的结果。
    • 结果通过printf()输出,可以使用串口调试工具观察原始ADC值和滤波后的值。
6. 滤波效果

假设输入信号存在一定噪声,未经滤波的ADC值可能会呈现波动。通过平均滤波后,输出的值会更加平滑,噪声得到有效抑制。例如,在一个连续变化的模拟信号中,经过滤波后的信号曲线将更加平滑,减少了高频噪声的影响。

7. 优化与扩展
  1. 其他滤波方法

    • 除了简单的平均滤波外,还可以使用其他滤波方法,如中值滤波、低通滤波等,这些方法能更好地应对不同类型的噪声。
  2. 滤波窗口动态调整

    • 根据实际需要,可以动态调整滤波窗口的大小,较大的窗口可以消除更多噪声,但会延迟响应。
  3. 实时性能优化

    • 对于高频信号的实时处理,使用硬件DMA(直接存储器访问)进行ADC数据采样并自动存储至缓冲区,从而减少CPU的负担,提高系统效率。
  4. 低功耗优化

    • 对于电池供电的嵌入式设备,滤波过程中可以结合低功耗模式,减少功耗,延长电池使用寿命。
8. 总结

本项目展示了如何在STM32单片机上实现一个简单的数字滤波功能,采用平均滤波算法对ADC采样的信号进行噪声抑制。通过环形缓冲区存储最近的采样值,并通过平均滤波计算平滑后的结果,能够有效降低信号中的高频噪声。这种方法适用于各种需要平滑信号的应用,如传感器信号处理、音频信号处理等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值