CIC滤波器的matlab仿真与实现

2023-11-04 10:50

本文主要是介绍CIC滤波器的matlab仿真与实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

CIC滤波器的matlab仿真与实现

介绍

在数字信号处理中,由于后级硬件如FPGA的处理速度无法跟上前级ADC的采样速度,因此需要对ADC的采样数据进行降速处理,也就是对采样数据进行抽取,简单的抽取描述就是对其中连续几个点取一个点进行处理。
由抽取理论知识可以知道,抽取相当于对时域做压缩,相应的就会对频谱做扩展,同时由于采样信号都是离散的,因此反映在频谱上会有一连串的延拓频谱。这样抽取后可能会导致混叠现象的发生,使得信号失真,无法被完全还原出来。
因此一般需要在抽取前加一级低通抗混叠滤波器,以防止混叠现象的产生,一般实现框图如下图所示:
Alt
在FPGA设计实现中,滤波器的实现需要占用乘法器和加法器资源。实际设计抽取模块时,有一种更好的抽取设计方式,那就是通过CIC滤波器同时实现抽取+滤波两项功能。CIC滤波器只需要加法器、减法器和寄存器即可实现,可以节省FPGA的乘法资源。

CIC滤波器结构

CIC滤波器由两部分组成,前部分是积分器,后部分是梳状滤波器。如下图所示
Alt

依据Nobel恒等式,抽取与线性滤波的位置是可以交换的,只是需要注意滤波器的系数变化,上图等价于
Alt

积分器

积分器是单极点的IIR滤波器,其状态方程为:
y ( n ) = y ( n − 1 ) + x ( n ) y(n) = y(n-1) + x(n) y(n)=y(n1)+x(n)
其系统响应为:
H 1 ( z ) = 1 / ( 1 − z − 1 ) H1(z) = 1/(1 - z^{-1}) H1(z)=1/(1z1)

梳状滤波器

梳状滤波器为对称的FIR滤波器,其状态方程为:
y ( n ) = x ( n ) − x ( n − N ) y(n) = x(n) - x(n-N) y(n)=x(n)x(nN)
其系统响应为:
H 2 ( z ) = 1 − z − N H2(z) = 1-z^{-N} H2(z)=1zN

CIC滤波器

通过将积分器与梳状滤波器进行级联,可以得到CIC滤波器的系统函数响应:
H ( z ) = H 1 ( z ) ∗ H 2 ( z ) = 1 − z − N / ( 1 − z − 1 ) H(z) = H1(z)*H2(z) = 1-z^{-N}/(1 - z^{-1}) H(z)=H1(z)H2(z)=1zN/(1z1)
也可以化简为
H ( z ) = 1 + z − 1 ) + z − 2 + . . . + z − ( N − 1 ) H(z) = 1 + z^{-1)} + z^{-2} + ...+ z^{-(N-1)} H(z)=1+z1)+z2+...+z(N1)
其中N为抽取倍数
由于单级CIC的第一旁瓣阻带衰减是固定的13.46dB,无法很好的抑制旁瓣,因此可以通过级联的方式来提升抑制效果,一般五级级联的CIC滤波器对第一旁瓣的抑制可以达到60~65dB。

matlab仿真设计

方法一:

通过cic滤波器的系统函数响应,利用matlab构建五级级联、四倍抽取的CIC滤波器,完整仿真测试代码如下:

fs = 200;		%采样率
f1 = 10;		%信号频率1
f2 = 20;		%信号频率2
n = 4096;		%采样点数
t = 0:1/fs:(n-1)/fs;
x_in = cos(2*pi*f1*t) + 2*cos(2*pi*f2*t) + 1i*sin(2*pi*f1*t) + 1i*2*sin(2*pi*f2*t);    %复数信号,提供两个不同的频率10Hz与20Hza = [1,-1];     %梳状滤波器系数
b = [1,-1];		%积分器系数%五级级联积分器
c1 =  filter(1,b,x_in);	%x_in为输入信号
c2 =  filter(1,b,c1);
c3 =  filter(1,b,c2);
c4 =  filter(1,b,c3);
c5 =  filter(1,b,c4);d = downsample(c5,4);	%对信号进行四倍抽取%五级级联梳状滤波器
e1 = filter(a,1,d);
e2 = filter(a,1,e1);
e3 = filter(a,1,e2);
e4 = filter(a,1,e3);
y_out = filter(a,1,e4);	%y_out为CIC输出figure
subplot(211)
f = 0:200/4096:(4096-1)*200/4096;   %归一化处理
plot(f,20*log10(abs(fft(x_in))),'b');
title('抽取前fft变换');xlabel('f/Hz');
f_d = 0:12.5/1024:(1024-1)*12.5/1024;   %归一化处理
subplot(212)
plot(f_d,20*log10(abs(fft(y_out))),'r');
title('抽取后fft变换');xlabel('f/Hz');

仿真结果图:
Alt
信号频率不变,带宽变为原来的1/4。同时一般CIC滤波器的通带较窄,通带边沿容易衰减,可以在CIC滤波器后面加反sinc补偿滤波器进行通带补偿

方法二:

利用matlab官方提供的CIC函数进行设计,同样设计五级级联、四倍抽取的CIC滤波器,并设计补偿滤波器进行补偿,完整仿真代码如下:

fs = 200;
f1 = 10;
f2 = 20;
n = 4096;
t = 0:1/fs:(n-1)/fs;
x_in = cos(2*pi*f1*t) + 2*cos(2*pi*f2*t) + 1i*sin(2*pi*f1*t) + 1i*2*sin(2*pi*f2*t);    %复数信号,提供两个不同的频率cic_num = 4;          %抽取倍数
Hd = dsp.CICDecimator(cic_num,1,5);     %设计系数分别为抽取倍数、延时因子、级联系数
Fp = fs/cic_num*0.4;  %补偿滤波器通带
Fstp = fs/cic_num*0.45;    %补偿滤波器阻带
CICCompDecim = dsp.CICCompensationDecimator(Hd, ... 		'DecimationFactor',1,'PassbandFrequency',Fp, ...'StopbandFrequency',Fstp,'SampleRate',fs/cic_num);		%补偿滤波器设计,设计参数分别为抽取因子、通带、阻带、抽取后采样率
FC = dsp.FilterCascade(Hd,CICCompDecim);	%滤波器级联
f = fvtool(Hd, CICCompDecim, FC, ...'Fs', [fs fs/cic_num fs],'Arithmetic','fixed');
f.NormalizeMagnitudeto1 = 'on';
legend(f,'CIC Decimator','CIC Compensation Decimator', ...'Overall Response');x_in_t = zeros(4096,1);
for i = 1:4096x_in_t(i,1) = x_in(1,i);		%行矩阵替换为列矩阵,如果这里用x_in_t = x_in'频谱会显示错位
end
cicout = step(Hd,x_in_t);		%官方提供的cicout = Hd(x_in_t)会一直报错,这是推荐的另一种调用方法
y_out = step(CICCompDecim,cicout);figure
f = 0:200/4096:(4096-1)*200/4096;   %归一化处理
subplot(311)
plot(f,20*log10(abs(fft(x_in))),'b');
title('抽取前fft变换');xlabel('f/Hz');
f_d = 0:50/1024:(1024-1)*50/1024;   %归一化处理
subplot(312)
plot(f_d,20*log10(abs(fft(cicout))),'r');
title('抽取后fft变换');xlabel('f/Hz');
subplot(313)
plot(f_d,20*log10(abs(fft(y_out))),'g');
title('补偿后fft变换');xlabel('f/Hz');

CIC滤波器幅度响应以及补偿后幅度响应如下图
Alt
仿真结果如下图

在这里插入图片描述
通过官方cic函数实现效果和通过系统函数法设计的实现效果基本一致,有点问题是关于补偿后会出现很多类似滤波器频谱响应波形的频谱还不清楚什么原因,恳请各位指教!

这篇关于CIC滤波器的matlab仿真与实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/345268

相关文章

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并

mybatis执行insert返回id实现详解

《mybatis执行insert返回id实现详解》MyBatis插入操作默认返回受影响行数,需通过useGeneratedKeys+keyProperty或selectKey获取主键ID,确保主键为自... 目录 两种方式获取自增 ID:1. ​​useGeneratedKeys+keyProperty(推

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

Linux在线解压jar包的实现方式

《Linux在线解压jar包的实现方式》:本文主要介绍Linux在线解压jar包的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux在线解压jar包解压 jar包的步骤总结Linux在线解压jar包在 Centos 中解压 jar 包可以使用 u

c++ 类成员变量默认初始值的实现

《c++类成员变量默认初始值的实现》本文主要介绍了c++类成员变量默认初始值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录C++类成员变量初始化c++类的变量的初始化在C++中,如果使用类成员变量时未给定其初始值,那么它将被

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核