上一篇《(项目实战)基于QT嵌入式ARM数据采集上位机设计》
文章目录
一 、 引言
笔者在Linux环境下,将qt的软件部署到arm中,在使用fftw时出现找不到lib库的错误,折腾许久,终于得以解决,记录下来留给有需要的朋友。
开发环境说明:
- Linux环境下,将qt编写的软件部署到arm中
- 笔者使用的是Ubuntu16.04,编译器是 arm-linux-gnueabihf-gcc
二 、 FFTW 简介
1. FFTW是什么?
FFTW(The Fastest Fourier Transform in the West)是一个计算一维或者多维DFT(the discrete Fourier transform)的c程序子库,支持任意输入长度,可以是实数或者复数数据。
2. FFTW特点
- 比其他开源傅里叶变换速度快
- 支持一维和多维变换
- 支持任意输入长度变换
- 纯实数输入输出时能快速变换
- 支持实数奇偶输入数据变换
- 高效处理多个或者多步变换
- 并行变换,只对支持多线程的机器有效
- 对使用C编译器的平台都是可移植的
三 、 编译安装
1 编译安装
-
资源下载
ftp://ftp.fftw.org/pub/fftw/fftw-3.3.10.tar.gz
#解压并进入文件夹 tar zxvf fftw-3.3.10.tar.gz cd fftw-3.3.10
-
配置
在fftw-3.3.10文件夹打开终端./configure --prefix=/usr/local/fftw --host=arm-linux --disable-fortran --enable-shared=yes --with-slow-timer CC=arm-linux-gnueabihf-gcc
参数使用说明:
--prefix=/usr/local/fftw #配置安装目录
--host=arm-linux #宿主机类型
--enable-shared=yes #编译共享库
CC=arm-linux-gnueabihf-gcc #设置编译
#说明 :其他没有配置说明时选择默认配置,如果有需要,可使用 ./configure -help 查看配置选项,如配置浮点型精度以及双浮点型精度,具体请查看具体参数
sudo make
sudo make install
- 经过以上步骤,编译完成,在
/usr/local/fftw
中会找到编译的库文件,我在做项目时,习惯将库文件拷到工程文件中,即将/usr/local
中的fftw文件夹全部复制过去,然后再fftw文件夹下创建fftw.pri
,无论哪种方式按照你的习惯就好。
2. 测试是否安装成功
-
qt下的配置,在工程文件下的fftw文件夹下创建
fftw.pri
,fftw.pri代码如下#fftw.pri # FFTW 安装路径 FFTW_PATH = $$PWD # FFTW 插件相关库所在路径(例如:xx.lib) FFTW_LIB_PATH = $$FFTW_PATH/lib # FFTW 插件相关头文件所在路径(例如:xx.h) FFTW_INCLUDE_PATH = $$FFTW_PATH/include INCLUDEPATH += $$FFTW_INCLUDE_PATH LIBS += -L$$FFTW_LIB_PATH -lfftw3
注意:
LIBS += -L$$FFTW_LIB_PATH -lfftw3 这里一定是这种写法,而不是像windows下的写法,笔者这里折腾很久,还是一次偶然发现
#windows下的写法 LIBS += -L$$FFTW_LIB_PATH/ -llibfftw3/ -llibfftw3f #这种写法在Linux下找不到链接库
在
*.pro
中包含 fftw.pri,即include(fftw.pri)
-
如果不是创建
.pri
的这种方式,可以在.pro
文件加入如下内容INCLUDEPATH += /usr/local/fftw/include LIBS += -L"/usr/local/fftw/lib" -lfftw3
-
qt测试文件内容,只要编译器能够将以下代码编译通过,即fftw安装成功
#include "widget.h" //#include "stdio.h" #include "fftw3.h" Widget::Widget(QWidget *parent) : QWidget(parent) { int N = 150; fftw_complex *out_fft = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N); } Widget::~Widget() { }
3 如在arm开发板中进行使用,还需要如下配置:
-
将程序部署到arm中,还需将库文件放到arm的
/lib
下这里由于lib下.so文件多数是快捷方式,只需将那个不是快捷方式的.so文件复制到 arm下的
/lib
中,
例 : 笔者fftw文件夹下libfftw3.so.3.6.10
不是快捷方式,我将其复制到arm中的/lib
中,qt编写的软件部署到arm中,会提示:缺少libfftw3.so.3
,只需将libfftw3.so.3.6.10
改名为libfftw3.so.3
即可,再次部署即可。
四 、FFTW使用实例
以下是我在csdn更新的项目实例中代码,大家可以参考一下。具体细节可以查看我的上几篇博客内容,
sllfft.cpp文件
#include "sllfft.h"
#include <QDebug>
sllFFT::sllFFT(qint16 len)
{
nLen = len;
fftInit(nLen);
}
void sllFFT::pushdata(QVector<double> valueVector)
{
static QVector<double> fft_In;
for (int i=0; i<valueVector.size(); i++) {
fft_In.append(valueVector[i]);
if(fft_In.size() >= nLen){
fftunit(fft_In,nLen);
emit processCompleted(this->xAxis, this->outvalue);
// qDebug() << outvalue.size();
fft_In.resize(0);
// qDebug()<<""<<"t_vector"<<t_vector.size()<<time.elapsed()/1000.0<<"s";//测试时间ms级别
}
}
}
void sllFFT::fftInit(qint16 len)
{
out_fft = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * len);
xAxis.resize(len/2);
for (quint16 i=0;i<len/2;i++)
{
xAxis[i] = i * (DATA_SAMPLING_FREQ/nLen);
}
// xAxis.remove(0, 2);
}
void sllFFT::fftunit(QVector<double> Value,qint16 len)
{
QVector<double> psd_amp(len);
for (quint16 i = 0;i < len;i ++)
{
psd_amp[i] = 0.5*(1-qCos(2*M_PI*i/(len-1)))*qSqrt(1.633);
Value[i]=Value[i]*psd_amp[i];
}
plan_fft = fftw_plan_dft_r2c_1d(len, &Value[0], out_fft, FFTW_ESTIMATE);
fftw_execute(plan_fft);// 执行变换
QVector<double> psd_amptemp(len/2);
for (quint16 i = 0;i < len/2;i ++)
{
psd_amptemp[i] = qSqrt(((out_fft[i][0]*out_fft[i][0]+out_fft[i][1]*out_fft[i][1]))
/(len*DATA_SAMPLING_FREQ/4));
}
fftw_destroy_plan(plan_fft);
outvalue.resize(psd_amptemp.size());
// qDebug() << xAxis.size() << outvalue.size();
for (int i=0;i<outvalue.size();i++)
{
{
outvalue[i] = psd_amptemp[i];
}
}
}
sllfft.h文件
#ifndef SLLFFT_H
#define SLLFFT_H
#include <QObject>
#include "fftw3.h"
#include <QtMath>
#include <QVector>
class sllFFT : public QObject
{
#define DATA_SAMPLING_FREQ 1000
Q_OBJECT
public:
explicit sllFFT(qint16 len);
void pushdata(QVector<double> valueVector);
signals:
void processCompleted(QVector<double> t_vectorX, QVector<double> t_vectorY);
private:
qint16 nLen;
QVector<QVector<double>> outvaluetemp;
QVector<double> outvalue;
QVector<double> xAxis;
fftw_plan plan_fft;
fftw_complex *out_fft;
void fftInit(qint16 len);
void fftunit(QVector<double> Value,qint16 len);
char AddData(double value);
};
#endif // SLLFFT_H