aVF,带宽1-25Hz
好像FIR低通并没有起作用
IIR高通及50Hz陷波表现良好
测试中
液晶截图
AD采样用TIM1比较匹配中断1触发
采样率好像算错了,于是只好乱改一通,用频率计校正,现在是设定为400Hz
原来设置为定时器20分频,预置数2250,理论上是18M/20/2250=400Hz
结果采样率相差很远,大概是160Hz
定时器初始化代码,现在的:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
TIM_DeInit(TIM1);
//APB2=18MHz
TIM_TimeBaseStructure.TIM_Prescaler = 10;//原来是20
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 2043; //原来是2205
//刚好为400sps
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0;
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
//TIM1 CH1 in Toggle mode
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_Pulse = 1024;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OC1Init(TIM1,&TIM_OCInitStructure);
不知道为什么会有这个问题
“敏感部位”代码
#include "../platform.h"//变量类型定义
#include "iir_coefs.h"
#include "iir_filter.h"
static int32 y[IIR_NSEC][3];
static int32 x[IIR_NSEC+1][3];
//自带缓存,逐个输入数据即可,返回的是滤波后的结果
//伪代码例子:savetosdcard(iir_filter(adc_get()));
int16 iir_filter(int16 in)
{
uint16 i;
volatile int64 yout;
x[0][0] = in;
for(i=0;i<IIR_NSEC;i++)
{
x
[0] = x[0]*IIR_G/IIR_A[0];
y[0] =(x[0]*IIR_B[0]+x[1]*IIR_B[1]+x[2]*IIR_B[2]-y[1]*IIR_A[1]-y[2]*IIR_A[2])/IIR_A[0];
y[2]=y[1];y[1]=y[0];
x[2]=x[1];x[1]=x[0];
x[i+1][0] = y[0];
}
yout = x[IIR_NSEC][0]*IIR_G[IIR_NSEC]/IIR_A[IIR_NSEC-1][0];//×îºóÒ»Œ¶µÄÔöÒæ
if(yout>32767) yout=32767;
if(yout<-32768) yout=-32768;
return (int16)yout;
}
//复位滤波器
void iir_reset(void)
{
uint16 i,j;
for(i=0;i<IIR_NSEC+1;i++)
{
for(j=0;j<3;j++)
{
x[j]=0;
}
}
for(i=0;i<IIR_NSEC;i++)
{
for(j=0;j<3;j++)
{
y[j]=0;
}
}
}
系数使用说明
FIR就不提了,说下IIR
用fdatool设计好以后,要转换(convert structure)为Direct-form I而且要是由2阶部分(section)串联的(默认就是这样,不用特别设置)
然后把系数四舍五入(quantize),使系数变为整数,一般选择fixed point ,word length =16,
并且确定滤波器稳定,再导出(export ->export to workspace)
还要导出为C文件一次
%SOS Martix与系数的对应关系
%SOS(j,i)
%在第j个Section中:
%SOS(j,1:3) b0~b2 别名: NUM[j][0]~NUM[j][3] B[][]
%SOS(j,4) a0 别名: DEN[j][0] A[][0]
%SOS(j,5:6) a1~a2 别名:DEN[j][1]~DEN[j][2] A[][]
%G(i)是第i个Section的输入增益
%G的最后一个元素是输出增益
%Direct-Form I IIR Filter 的差分方程
% a0*y = b0*x + b1*x_1 + b2*x_2 - a1*y_1 -a2*y_2;
把C文件中的NUM,DEN数组的奇数项去掉,并改名为B,A数组,保存为iir_coefs.h给iir_filter.c使用
G矩阵要全部乘以A【任意项(每一项都是相同的)】【0】,以转化为整数,然后写入数组
宏IIR_NSEC是Section(部分)数,必须定义
例子:
//iir_coefs.h
#define IIR_NSEC 5
const int16 IIR_B[IIR_NSEC][3] = {
{
16384, -32768, 16384
},
{
16384, -32767, 16384
},
{
16384, -32766, 16384
},
{
16384, -32766, 16384
},
{
16384, -23170, 16384
}
};
const int16 IIR_A[IIR_NSEC][3] = {
{
16384, -31753, 15404
},
{
16384, -32596, 16221
},
{
16384, -32717, 16338
},
{
16384, -32753, 16373
},
{
16384, -21802, 14449
}
};
const int16 IIR_G[IIR_NSEC+1] = {
14158,16301,16360,16378,15417,16384
};
200字以内,仅用于支线交流,主线讨论请采用回复功能。