跳到主要内容

10 IIR操作

up的视频讲解

配置 ADC 与 DMA 采样,导入 IIR 驱动,再用 SerialPie 生成系数并观察滤波波形。

up视频里的实验代码: 👣IIR实验代码

IIR驱动代码: IIR驱动代码

1 🔌 硬件连接(复用)​

可以复用ADC实验连接通过麦克风采集看效果,有信号源的同学将PA1连接设备即可
麦克风输出连接 PA1,串口继续把采样数据送到电脑。
麦克风输出连接 PA1,串口继续把采样数据送到电脑。

2 💻 软件操作​

本节的 ADC、DMA、TIM3 与串口配置沿用上一节的配置,通用步骤使用相同截图;工程命名、驱动导入和滤波器设置见本节的 IIR 截图。

1 CubeMX配置​

新建工程与选择芯片​

打开 STM32CubeMX,点击 File → New Project,搜索 STM32F103C8T6,双击对应芯片创建工程。

CubeMX新建工程
搜索并选择STM32F103C8T6

配置下载接口与时钟​

在 System Core → SYS 中,将 Debug 设置为 Serial Wire。再进入 RCC,将 HSE 设置为 Crystal/Ceramic Resonator。

SYS选择Serial Wire调试接口
RCC选择HSE外部晶振

进入 Clock Configuration,按图将主频设置为 72 MHz。若出现时钟求解提示,按图确认,再核对调整后的主频与 ADC 时钟配置。

时钟树设置72MHz主频

配置ADC​

打开 Analog → ADC1,勾选 IN1(PA1),按图将规则组的外部触发源选择为 Timer 3 Trigger Out event。

ADC1选择通道1与TIM3触发源
确认CubeMX时钟求解提示
核对调整后的时钟树

展开 Rank,将通道 1 的 Sampling Time 设置为 7.5 Cycles。

ADC1通道1选择7.5个周期采样时间

配置DMA​

进入 DMA Settings,点击 Add 并选择 ADC1,添加 ADC 的 DMA 请求。

为ADC1添加DMA请求

配置TIM3触发​

打开 Timers → TIM3,启用 Internal Clock。在参数页中,将 Prescaler 设置为 72 - 1,Counter Period 设置为 200 - 1。

TIM3启用Internal Clock
TIM3设置预分频和自动重装载值

在 Trigger Output (TRGO) Parameters 中,将 Trigger Event Selection 设置为 Update Event,用于触发 ADC 采样。

TIM3选择Update Event触发输出

配置串口​

打开 Connectivity → USART1,将模式设置为 Asynchronous。

USART1选择异步通信模式

生成工程​

进入 Project Manager,将工程名设置为 IIR_TEST,填写保存位置,工具链选择 MDK-ARM。

设置IIR工程名称与MDK-ARM工具链

在 Code Generator 中,按图选择只复制需要的库文件,并勾选为每个外设生成独立的 .c/.h 文件。

设置库文件复制方式和外设文件生成方式

点击 GENERATE CODE,生成完成后点击 Open Project,进入 MDK。

生成代码并打开MDK工程

2 MDK配置​

下载并放入IIR驱动​

从本页的 IIR 驱动下载入口获取压缩包,解压后把 IIR 驱动文件夹放入工程目录,位置参考下图。

下载IIR驱动代码
将IIR驱动文件夹放入工程目录

添加头文件路径与工程文件​

打开 Options for Target → C/C++,在 Include Paths 中添加 IIR 驱动文件夹。

在Include Paths中添加IIR驱动目录

打开工程文件管理窗口,新建 IIR 分组,点击 Add Files 并进入驱动目录。将文件类型切换为 All files (*.*),选择 IIR.c 和 IIR.h 并添加到分组。

新建IIR分组并打开驱动目录
选择IIR驱动文件并加入工程

设置MicroLIB​

进入 Options for Target → Target,按视频工程配置勾选 Use MicroLIB,然后确认保存。

在Target选项中勾选Use MicroLIB

3 实验代码​

全局​

#include <stdio.h>
#include "IIR.h"
// ADC采样缓存
#define DATA_SIZE 256
uint16_t adc_dma_buf[DATA_SIZE];
//DMA传输完成中断
volatile uint8_t flag = 0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if (hadc->Instance == ADC1) flag = 1;
}
// printf输出重定向
int fputc(int ch, FILE *f)
{
uint8_t temp = ch;
HAL_UART_Transmit(&huart1, &temp, 1, HAL_MAX_DELAY);
return ch;
}

main()​

HAL_TIM_Base_Start(&htim3);
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)adc_dma_buf,DATA_SIZE);//在CubeMX中配置的单次传输

while(1)​

if (flag)
{
// 分帧采样有间隔,每帧复位;
iir_filter_reset();

for (uint16_t i = 0; i < DATA_SIZE; i++)
{
int16_t filtered = iir_filter_run(adc_dma_buf[i],b,a);

printf("%d\r\n", filtered);
}
printf("end\n");
flag = 0;
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_dma_buf,DATA_SIZE);//重新打开DMA
}

4 生成IIR滤波系数​

在SerialPie中设置滤波器​

打开 SerialPie 的“滤波”页面,选择右侧的 IIR,按图设置公共参数、原型阶数和滤波函数。

这是up在输入200Hz方波 幅值2.6V 占空比58%下的配置
采样率5000 Hz滤波类型带通
下限频率155.750 Hz上限频率256.250 Hz
原型阶数2滤波函数巴特沃斯 Butterworth
SerialPie设置IIR带通滤波器参数

复制系数到工程​

向下滚动到系数区域,系数类型选择 int16_t,点击 IIR 一侧的“复制”。回到 MDK,把生成的 b、a 两组系数完整粘贴到 main.c 的全局区域。

选择int16_t系数类型并复制IIR系数

3 ♒️ 实验效果​

完成上述配置与代码填写后,编译并下载工程。打开 SerialPie,连接开发板对应的串口,保持串口参数与工程配置一致,切换到“波形”页面查看输出。按图将显示模式设为“刷新模式”,批次识别选择 end\n 标记识别。下图为视频操作中的 IIR 输出波形。

SerialPie显示IIR实验输出波形