C FIR带通滤波器
我试图在STM32F407微控制器上实现一个60kHz的带通滤波器,我遇到了一些问题。我在MATLABs fdatool的帮助下生成了滤波器,然后在MATLAB中对其进行了仿真。下面的MATLAB脚本模拟了它C FIR带通滤波器,c,matlab,filter,arm,signal-processing,C,Matlab,Filter,Arm,Signal Processing,我试图在STM32F407微控制器上实现一个60kHz的带通滤波器,我遇到了一些问题。我在MATLABs fdatool的帮助下生成了滤波器,然后在MATLAB中对其进行了仿真。下面的MATLAB脚本模拟了它 % FIR Window Bandpass filter designed using the FIR1 function. % All frequency values are in Hz. Fs = 5250000; % Sampling Frequency N = 18
% FIR Window Bandpass filter designed using the FIR1 function.
% All frequency values are in Hz.
Fs = 5250000; % Sampling Frequency
N = 1800; % Order
Fc1 = 59950; % First Cutoff Frequency
Fc2 = 60050; % Second Cutoff Frequency
flag = 'scale'; % Sampling Flag
% Create the window vector for the design algorithm.
win = hamming(N+1);
% Calculate the coefficients using the FIR1 function.
b = fir1(N, [Fc1 Fc2]/(Fs/2), 'bandpass', win, flag);
Hd = dfilt.dffir(b);
%----------------------------------------------------------
%----------------------------------------------------------
T = 1 / Fs; % sample time
L = 4500; % Length of signal
t = (0:L-1)*T; % Time vector
% Animate the passband frequency span
for f=55500:50:63500
signal = sin(2*pi*f*t);
plot(filter(Hd, signal));
axis([0 L -1 1]);
str=sprintf('Signal frequency (Hz) %d', f);
title(str);
drawnow;
end
pause;
close all;
signal = sin(2*pi*50000*t) + sin(2*pi*60000*t) + sin(2*pi*78000*t);
signal = signal / 3;
signal = signal(1:1:4500);
filterInput = signal;
filterOutput = filter(Hd,signal);
subplot(2,1,1);
plot(filterInput);
axis([0 4500 -1 1]);
subplot(2,1,2);
plot(filterOutput)
axis([0 4500 -1 1]);
pause;
close all;
从fdatool中,我将滤波器系数提取为q15格式的16位无符号整数,这是因为我使用的是12位ADC。由MATLAB生成的过滤器系数标题为,系数的结果图如下图所示
下面是过滤器实现的代码,它显然不起作用,我也不知道我能做些什么,我在网上看了一些例子,然后
#包括“fdacoefs.h”
#定义过滤器样本4500
#定义块大小为900
静态uint16输入[过滤样本];
静态uint16输出[过滤样本];
静态uint16第一个[NUM_TAPS+块大小-1];
uint16_t util_calculate_filter(uint16_t*缓冲区,uint32_t len)
{
uint16_t i;
uint16_t最大值;
uint16_t min;
uint32_t指数;
//创建过滤器实例
arm_fir_实例_q15实例;
//确保缓冲区长度不超过样本大小
如果(镜头>过滤样本)
len=过滤样本;
对于(i=0;i
ADC以5.25毫秒每秒的速度采样,它对一个60kHz的信号采样4500次,在这里你可以看到滤波器的频率,然后是滤波器的频率,这很奇怪
有什么明显的我错过的吗?因为我完全迷路了,任何指点和提示都是有用的 正如Lundin指出的,我将其改为使用32位整数,这实际上解决了我的问题。当然,我用MATLABS fdatool生成了新的过滤器系数,作为有符号32位整数
static signed int firInput[FILTER_SAMPLES];
static signed int firOutput[FILTER_SAMPLES];
static signed int firState[NUM_TAPS + BLOCK_SIZE -1];
uint16_t util_calculate_filter(uint16_t *buffer, uint32_t len)
{
uint16_t i;
int power;
uint32_t index;
// Create filter instance
arm_fir_instance_q31 instance;
// Ensure that the buffer length isn't longer than the sample size
if (len > FILTER_SAMPLES)
len = FILTER_SAMPLES;
for (i = 0; i < len ; i++)
{
firInput[i] = (int)buffer[i];
}
// Call Initialization function for the filter
arm_fir_init_q31(&instance, NUM_TAPS, &firCoeffs, &firState, BLOCK_SIZE);
// Call the FIR process function, num of blocks to process = (FILTER_SAMPLES / BLOCK_SIZE)
for (i = 0; i < (FILTER_SAMPLES / BLOCK_SIZE); i++) //
{
// BLOCK_SIZE = samples to process per call
//arm_fir_q31(&instance, &firInput[i * BLOCK_SIZE], &firOutput[i * BLOCK_SIZE], BLOCK_SIZE);
arm_fir_q31(&instance, &firInput[i * BLOCK_SIZE], &firOutput[i * BLOCK_SIZE], BLOCK_SIZE);
}
arm_power_q31(&firOutput, len, &power);
// Convert output back to uint16 for plotting
for (i = 0; i < (len); i++)
{
buffer[i] = (uint16_t)(firOutput[i] - 63500);
}
return (uint16_t)((power/10));
}
静态有符号整数输入[FILTER_SAMPLES];
静态有符号整数输出[FILTER_SAMPLES];
静态有符号整数第一次[NUM_TAPS+BLOCK_SIZE-1];
uint16_t util_calculate_filter(uint16_t*缓冲区,uint32_t len)
{
uint16_t i;
整数幂;
uint32_t指数;
//创建过滤器实例
arm\U fir\U实例\U q31实例;
//确保缓冲区长度不超过样本大小
如果(镜头>过滤样本)
len=过滤样本;
对于(i=0;i
在32位MCU上进行如此多的uint16\t
计算,我会立即怀疑各种溢出和隐式升级错误。有几个地方代码依赖于隐式整数提升。这通常是一个程序员不考虑/不了解隐式升级的标志,而隐式升级又会产生非常微妙的bug。为什么我在32位MCU上使用uint16_t计算会很重要?有处理半字的指令,q15值也表示为16位无符号值,ADC将12位样本存储在无符号16位缓冲区中,因此类型转换在哪里进行?32位MCU表示您的int
类型为32位,这反过来意味着您使用的所有小整数类型都将被隐式提升为32位有符号类型。这是由C强制执行的,与特定的处理器或编译器无关。您需要了解整数提升规则和平衡(“通常的算术转换”)是如何工作的。我知道,但我不明白这是怎么回事?变量在计算前改变符号。提供意外结果的变量比较。看似有效但隐藏的潜在值溢出的计算,在代码发生轻微更改时会突然暴露出来。位运算产生非常奇怪的结果。等等很多潜在的微妙的错误。
static signed int firInput[FILTER_SAMPLES];
static signed int firOutput[FILTER_SAMPLES];
static signed int firState[NUM_TAPS + BLOCK_SIZE -1];
uint16_t util_calculate_filter(uint16_t *buffer, uint32_t len)
{
uint16_t i;
int power;
uint32_t index;
// Create filter instance
arm_fir_instance_q31 instance;
// Ensure that the buffer length isn't longer than the sample size
if (len > FILTER_SAMPLES)
len = FILTER_SAMPLES;
for (i = 0; i < len ; i++)
{
firInput[i] = (int)buffer[i];
}
// Call Initialization function for the filter
arm_fir_init_q31(&instance, NUM_TAPS, &firCoeffs, &firState, BLOCK_SIZE);
// Call the FIR process function, num of blocks to process = (FILTER_SAMPLES / BLOCK_SIZE)
for (i = 0; i < (FILTER_SAMPLES / BLOCK_SIZE); i++) //
{
// BLOCK_SIZE = samples to process per call
//arm_fir_q31(&instance, &firInput[i * BLOCK_SIZE], &firOutput[i * BLOCK_SIZE], BLOCK_SIZE);
arm_fir_q31(&instance, &firInput[i * BLOCK_SIZE], &firOutput[i * BLOCK_SIZE], BLOCK_SIZE);
}
arm_power_q31(&firOutput, len, &power);
// Convert output back to uint16 for plotting
for (i = 0; i < (len); i++)
{
buffer[i] = (uint16_t)(firOutput[i] - 63500);
}
return (uint16_t)((power/10));
}