历史上的今天
返回首页

历史上的今天

今天是:2025年02月19日(星期三)

正在发生

2019年02月19日 | 基于STM32F4的提升小波(二代小波)分解程序说明

2019-02-19 来源:eefocus

一、主要思路 


原始信号:OrgSig


与基于MALLAT算法的小波变换不同,提升小波变换不产生数组L,只产生C数组。定义如下: 

DWT_C:[cD1 | cD2 | … cDN | cAN],其中cDx代表第x层的细节系数,cAN代表第N层的近似系数。 


但是,信号长度必须是2的整数次幂。 


由于算法可实现原位计算,因此,每层变换后,系数仍存在原始信号的数组中,格式为:[CD,CA]。下一层再变换时,将CA作为原始信号即可,直到分解结束。 


每层变换的步骤:分裂->提升(多层预测/更新)->合并 


各层提升的系数由MATLAB中的liftwave函数计算得到。基于MATLAB中此系数的性质,在此算法中,无论预测还是更新,都采用同一个函数;无论变换还是逆变换都采用加法运算。但是,逆变换中滤波器的符号取反。 


与Mallat算法相比,不需要过多临时变量,不需要过多大的临时数组。需要的程序堆栈比较少。 


二、函数原型 


1、 提升格式更新函数DWT_lsupdate


/****************************************

**将数据进行提升格式更新/预测

//V1.00   实现基本功能 2016-10-12 14:40:59

* @原理:

1、与MATLAB中lsupdate函数的功能类似

* @return 正常则返回1,错误则返回0

*****************************************/

uint16_t DWT_lsupdate(

    float32_t* p_Sig1,               //信号1,待更新的信号

    float32_t* p_Sig2,               //信号2,另一路信号

    uint16_t SigLen,                //信号1和信号2的长度

    const float32_t* p_FilterCoef,  //滤波器系数

    const uint8_t FilterCoefLen,    //滤波器系数长度

    const int8_t DF,                //滤波时的延迟

    int8_t IsLWT                    //LWT还是ILWT?1代表LWT,-1代表ILWT

)


2、 分裂函数DWT_split


/****************************************

**分裂函数

//V1.00   实现基本功能 2016-10-12 15:04:09

* @功能:分裂后,data的前半部分为奇数序号的点(1,3,5...),后半部分为偶数序号的点(0,2,4...)

* @原理:

* @return 正常返回1,否则返回0

*****************************************/

uint8_t DWT_split(

    float32_t* data,  //原始数据

    uint16_t n        //数据长度

)


3、 合并函数


/****************************************

**合并函数

//V1.00   实现基本功能 2016-10-13 15:52:30

* @功能:分裂函数的反函数,data的前半部分为奇数序号的点(1,3,5...),后半部分为偶数序号的点(0,2,4...),

         此函数将数据按正常顺序排列

* @原理:

* @return 正常返回1,否则返回0

*****************************************/

uint8_t DWT_unite(

    float32_t* data,  //原始数据

    uint16_t n        //数据长度

)


4、 提升小波变换函数DWT_lwt


/****************************************

**提升小波变换,即1层提升小波分解

//V1.00   实现基本功能 2016-10-12 15:04:09

* @原理:

   分裂->更新/预测->合并

* @return 正常则返回变换后近似系数和细节系数的长度,错误则返回0

*****************************************/

uint16_t DWT_lwt(

    float32_t* p_OrgSig,     //原始信号

    uint16_t OrgSigLen      //信号长度

)


5、 提升小波反变换函数DWT_ilwt


/****************************************

**提升逆小波变换,即1层提升小波重构

//V1.00   实现基本功能 2016-10-13 14:52:01

* @原理:

       合并->更新/预测->分裂

* @return 正常则返回重构后的信号长度,错误则返回0

*****************************************/

uint16_t DWT_ilwt(

    float32_t* p_LWT_C,      //LWT_C数组

    uint16_t LWT_C_Len       //数组长度

)


6、 提升小波反变换函数DWT_ilwt


/****************************************

**提升逆小波变换,即1层提升小波重构

//V1.00   实现基本功能 2016-10-13 14:52:01

* @原理:

       合并->更新/预测->分裂

* @return 正常则返回重构后的信号长度,错误则返回0

*****************************************/

uint16_t DWT_ilwt(

    float32_t* p_LWT_C,      //LWT_C数组

    uint16_t LWT_C_Len       //数组长度

)


7、 提升小波分解函数DWT_lwtWaveDec


/****************************************

**提升小波分解,可实现N层提升小波分解

//V1.00   实现基本功能 2016-10-13 10:36:56

* @原理:

      1、原位分解,分解后原始数据即变为C数组

* @return 正常则返回1,错误则返回0

*****************************************/

uint16_t DWT_lwtWaveDec(

    float32_t* p_OrgSig,    //原始信号

    uint16_t OrgSigLen,     //信号长度

    uint16_t DecLevel       //分解层数

)


8、 提升小波重构函数DWT_lwtWaveRec


/****************************************

**提升小波重构,可实现N层提升小波重构

//V1.00   实现基本功能 2016-10-13 16:05:13

* @原理:

   1、原位分解,分解后C数组即变为原始数据

* @return 正常则返回1,错误则返回0

*****************************************/

uint16_t DWT_lwtWaveRec(

    float32_t* p_LWT_C,     //LWT_C数组

    uint16_t LWT_C_Len,     //数组长度

    uint16_t DecLevel       //分解层数


三、移植过程 

1、 根据算法研究结果,确定需要进行小波分解的信号长度、小波函数和分解层数 

2、 修改.h文件 

因为是原位运算,不需要根据信号长度和小波分解层数去预定义数组L和C,因此不需要define信号长度和小波分解层数,直接在信号缓存和小波分解时指定即可。 

a、根据所选定小波的提升格式,修改提升次数和每次提升时滤波器的最大长度


#define LWT_LS_LEVEL          5 //提升的次数,即'd'和'p'的个数

#define LWT_Filter_Len_MAX     3 //各层算子的点数,取最大者,点数没这么多的补零


3、 修改.c文件 

a、修改提升格式中滤波器的系数


//以db4为例,在MATLAB中计算出db4的提升格式如下:

//% liftwave('db4')

//%

//% {   'd',-0.322275887997141,1;

//%     'p',[-1.11712360516059,-0.300142258748544],0;

//%     'd',[-0.0188083527262439,0.117648086798478],2;

//%     'p',[2.13181671275522,0.636428271190659],0;

//%     'd',[-0.469083478911028,0.140039237732612,-0.0247912381571950],0;

//%          0.734124527683251,1.36216672007377,[]}


//db4

const float32_t LWT_Filter_Coef[LWT_LS_LEVEL][LWT_Filter_Len_MAX] =

 {{ -0.322275887997141},                                          //1

  { -1.11712360516059, -0.300142258748544},                       //2

  { -0.0188083527262439, 0.117648086798478},                      //3

  {2.13181671275522, 0.636428271190659},                          //4

  { -0.469083478911028, 0.140039237732612, -0.0247912381571950}   //5

};


b、修改提升格式中各层滤波器系数的长度、滤波延迟,以及最终的归一化系数


//db4

const uint8_t LWT_Filter_Len[LWT_LS_LEVEL] = {1, 2, 2, 2, 3};      //滤波器长度

const int8_t LWT_DF[LWT_LS_LEVEL] = {1, 0, 2, 0, 0};               //滤波器延迟

const float32_t LWT_NormCoef[2] = {0.734124527683251, 1.36216672007377}; //归一化系数

const float32_t DWT_Lo_D[DWT_FILTER_LEN] = {  0.0352,   -0.0854,   -0.1350,    0.4599,    0.8069,    0.3327};

const float32_t DWT_Hi_D[DWT_FILTER_LEN] = { -0.3327,    0.8069,   -0.4599,   -0.1350,    0.0854,    0.0352};

const float32_t DWT_Lo_R[DWT_FILTER_LEN] = {  0.3327,    0.8069,    0.4599,   -0.1350,   -0.0854,    0.0352};

const float32_t DWT_Hi_R[DWT_FILTER_LEN] = {  0.0352,    0.0854,   -0.1350,   -0.4599,    0.8069,   -0.3327};

)

4、 使用分解和重构函数 

在程序中合适的位置,缓存或预定义一段原始数据OrgSig,分解后的系数即保存在OrgSig中,再将OrgSig作为重构系数,重构之后的信号仍然保存在OrgSig中。使用例程如下:


 float32_t OrgSig[DWT_SIG_LEN] = {1, 2, 1, -1, 1, 2, -1, -2, 1, 2, 3, 4, 5, 6, 7, 8, 1, 12, 13, 1, 3, 6, 8, 1, 4, 4, 4, 2, 8, 10};

DWT_lwtWaveDec(OrgSig2,32,3);   //32是数据长度,3是分解层数

DWT_lwtWaveRec(OrgSig2,32,3);


四、注意事项 

1、 堆栈设置问题 

小波变换需要的临时变量较大,当信号长度较大时,可能会引起HardFault,进而进入函数HardFault_Handler死循环。这时,需要在启动文件startup_stm32f40_41xxx.s中修改堆区大小。 

如:


; Stack_Size      EQU     0x00000400 //默认设置是这个

Stack_Size      EQU     0x0000FF00


五、测试结果 

1、 对于采样率为360Hz的ECG信号,利用db3对500个点进行4层小波分解后再重构,得到结果对比如下图,二者相关系数为1.0000。 


这里写图片描述


推荐阅读

史海拾趣

岑科(CENKER)公司的发展小趣事

岑科公司成立于2001年,初期主要从事电子元器件的贸易业务。在创始人蔡旌章的带领下,岑科以优质的服务和灵活的运营策略,在国内外市场上赢得了良好的口碑。这一时期,岑科的服务对象主要是海内外的电子元器件需求商,通过精准把握市场需求和优质的产品供应,逐渐在电子元器件贸易领域站稳了脚跟。随着业务的不断拓展,岑科开始思考如何进一步提升自身的竞争力,以实现更长远的发展。

Cellergy公司的发展小趣事

在电子行业中,产品质量是企业生存和发展的关键。Cellergy公司深知这一点,始终将品质放在首位。公司建立了严格的质量管理体系,从原材料采购到生产加工再到产品出厂,每一个环节都严格把关。这种对品质的执着追求使得Cellergy公司的电容器产品在市场中获得了良好的口碑,赢得了客户的信赖和支持。

D3公司的发展小趣事

D3公司非常重视企业文化的建设。公司倡导“以人为本、诚信经营”的企业文化,为员工提供良好的工作环境和发展机会。同时,公司还注重培养员工的团队协作精神和创新意识。在这种企业文化的熏陶下,D3公司的员工们团结一心、锐意进取,共同为公司的发展贡献力量。这种强大的团队力量,是D3公司在电子行业中不断取得成功的关键因素之一。

请注意,以上故事均为虚构,旨在展示电子行业中一家公司可能的发展路径和策略。在实际应用中,企业需要根据自身情况和市场环境来制定合适的发展战略。

Chengdu Sino Microelectronics Technology Co Ltd公司的发展小趣事

在集成电路设计领域,技术的突破是赢得市场的关键。成都华微科技始终坚持以技术研发为核心,不断投入巨资进行技术研发和创新。经过多年的努力,公司在可编程逻辑器件、系统级芯片、存储器和模数/数模转换器(AD/DA)芯片等领域取得了重大突破,产品性能达到了国内领先水平。这些技术突破不仅为公司赢得了市场的认可,也提升了中国集成电路设计行业的国际地位。

DC Components公司的发展小趣事

在电子行业中,产品质量是企业立足之本。DC Components公司深知这一点,因此始终把质量控制放在首位。公司通过实施严格的质量控制系统,确保每一个产品都符合高质量标准,并符合所有合同要求。这种对质量的坚守,使DC Components公司在市场上赢得了良好的口碑,吸引了众多客户的青睐。

ARCOLECTRICSWITCHES公司的发展小趣事

面对全球化的趋势,ARCOLECTRIC SWITCHES公司制定了国际化发展战略。公司积极开拓海外市场,设立海外分支机构,拓展国际业务。在国际化进程中,公司注重跨文化管理,尊重不同国家和地区的文化差异,努力融入当地市场。通过国际化战略的实施,ARCOLECTRIC SWITCHES公司的业务范围不断扩大,国际影响力逐渐提升。

这些故事虽然基于虚构,但反映了一个电子企业在发展过程中可能经历的关键阶段和挑战。实际中,ARCOLECTRIC SWITCHES公司的发展历程可能因市场条件、技术变革、竞争环境等多种因素而有所不同。如果您需要了解该公司具体的发展故事,建议查阅相关官方资料或行业报告。

问答坊 | AI 解惑

程控滤波资料和论文集锦

本帖最后由 paulhyde 于 2014-9-15 03:13 编辑 我最近,在做程控滤波,就搜集了一些资料和论文集锦,供大家参考哦,这只是其中的一部分, 如果有需要的,我还会继续传哦,先传这么多吧!!!!    …

查看全部问答>

模板使用 编译选项-frepo 问题

之前写的一个程序,中间用到模板类,模板类的所有定义和实现都在同一个h文件中,使用-frepo开关编译。之前一直都是好好的,今天换了台机器,编译出来的代码在download的目标机的时候说一大堆函数未定义,仔细看了全部都是该模板类的函数。但同样代 ...…

查看全部问答>

Bank调用

大家好,我想问一下跨BANK调用是不是不可以的,要怎样才可以实现两个BANK之间调用?谢谢…

查看全部问答>

运动控制器的芯片选型

最近在筹备运动控制器,要求至少3轴联动,定位精度0.01mm,伺服周期1ms以下,可实现空间圆弧插补。 看了TI公司的F2810、F2812、F28235、F28335、F28345,低价格的F28035、F2802;F28335和F28345是浮点DSP,2009年TI报价分别是15.65和14.42美元,相 ...…

查看全部问答>

【高分请教】Windows下如何自动安装驱动程序

Hi, 小弟目前做的项目需要在Windows下安装一个简单的USB驱动,驱动程序由第三方提供(没有经过MS认证),包含DLL、INF、SYS等等文件。 一般情况下,当即插即用设备连上PC后,如果PC中没有该设备的驱动,会弹出安装驱动的提示,用户根据提示来一步 ...…

查看全部问答>

WinCE下应用程序读.txt文件乱码

编写一个在WinCE下运行的 ,基于MFC的应用程序,读取.txt文件 文件内容的结构如下 书名1;价格1 书名2;价格2 书名3;价格 3 。。。。。。 CFile myfile(L\"D:\\\\food.txt\", CFile::modeRead); int length = myfile.GetLength(); char ...…

查看全部问答>

请教达人

我想采集几路直流电压信号到计算机,然后经过运算再输出到外围显示一些数字,不知道硬件电路需要些什么?因为我不是学计算机的,所以希望由一些市场上可以买到的模块拼请来实现,希望哪位达人知道一下,谢谢了!…

查看全部问答>

请问各位高手,北桥芯片具体什么作用啊?

我有个疑问,就是主板上的北桥芯片起什么作用,虽然在网上一搜一大堆,但无非就是说是连接CPU和内存,AGP,的作用,起中间枢纽的作用,回答的非常初级,也没有作实质上的解释,但我想知道的是,如果撇开北桥怎么样?如果要从内存取数据,CPU直接先送 ...…

查看全部问答>

用Micro Framework 3.0对GPIO的操作

我的开发环境是VS2008,我想写一个WinCE下对S3C2440的GPIO操作的程序,应该怎样写呢?比如,我希望操作GPB的某个管脚,应当怎样写代码?另外,Micorsoft.SPOT.Hardware下的CPU.PIN的用法有些不解,(CPU.PIN)15是什么意思呢?是表示芯片的第15个管脚 ...…

查看全部问答>

高分请教简单问题:AT89s52的访问外部地址问题

我的硬件原理图如下链接:请放心打开! http://www.dzjia.cn/html/jiejuefangan/20070619/24939_2.html 如图示:P2.7接到RC500的NCS片选脚上,这时我想要访问RC500的内部地址,我就应该先定义要访问的地址,如下: #define Page_Sel      ...…

查看全部问答>