最近在做信号处理相关的功能,首先在matlab上做仿真,之后使用c/c++实现,然后尝试使用Matlab Coder做转换功能。
参考: 基于MATLAB Coder将matlab代码转换成C代码 官网视频讲解 matlab调用c/c++代码
特此感谢!
一、概念及开发流程
MATLAB Coder可以从MATLAB代码生成独立的、可读性强、可移植的C/C++代码。
通俗地说,就是将写好的matlab功能模块代码转换为c/c++代码,然后我们在此基础上进行改进。
本文开发环境:Win10 64、VS2015、Matlab R2016A。
开发流程:使用MATLAB Coder产生C代码的3个步骤:
- 开发实现特定算法功能的MATLAB代码及其测试文件
- 检查MATLAB代码的兼容性,确保MATLAB代码中的语句都能被转换成C代码(有些matlab代码语句并不能生成c/c++代码,例如matlab中的imread、imshow、plot等函数)
- 利用MATLAB Coder生成c/c++代码,并在VS2015中验证。
二、实践测试
参考的文章中给出了功能模块代码与测试代码分离的思想,因此本文借鉴这种思想,进行实践测试。
当然功能模块a.m文件可以作为b.m文件的调用,在编译时两个都要选中进行编译(可以理解为依赖),不过本文暂时不涉及该功能的实现。
2.1 Matlab功能模块代码及其测试代码
myfft.m
对输入的数据去除直流分量并进行FFT。其中,%#codegen用来防止出现警告错误
%#codegen
function B = myfft(v1,N)
v1=v1 - mean(v1);
B = fft(v1,N);
test_main.m
产生数据集并测试
f=100; %信号频率Hz
Fs=1000; %采样频率
N=256; %采样点数
t=(0:N-1)/Fs; %采样时间s
S=1000*sin(2*pi*f*t)+20*randn(size(t)); %信号采样值
%B = meanVal(S,N)
B = myfft(S,N);
f =((-N/2):(N/2-1))*Fs/N;
plot(abs(B))
title('Amplitude Spectrum of S')
xlabel('f (Hz)')
ylabel('|P1(f)|')
matlab输出:
f = (N-1)Fs/N = 261000/256=100Hz。
2.2 利用MATLAB Coder生成c/c++代码
-
在命令窗口,输入mex -setup ,选中一个存在的编译器,笔者这里自带了一个c编译器,读者也可以切换为c++编译器(输入mex -setup C++ )。
-
在命令窗口输入coder(图形界面),回车,弹出MATLAB Coder Project对话框(或在matlab软件的界面中点击MatLab Coder 图标)。
(1)在Select模块中选择我们想要编译的功能模块myfft.m
(2)点击Next
上图红色方框处也可以继续添加功能模块的.m文件。
(3)点击Next,进入Define Input Types界面。输入test_main.m测试文件,点击Autodefine Input Types按钮,从而使得matlab能自动检测出功能模块函数的接口变量的维度和类型。
(4)点击Next,点击check for issues按钮。
(5)点击Next,点击Generate按钮,生成了C/C++代码。
生成成功后如下图,可以在lib文件下查看到该文件。
2.3 VS2015验证
利用VS2015在lib同级目录下的文件夹libvs中建立工程myfftprj,将所有的.c .h导入工程。
由于物理路径的关系,修改当前工程头文件路径即可。
我们发现工程中输入实例输入为空,因此根据test_main.m文件需要进行修改。
static void argInit_1x256_real_T(double result[256])
{
int idx1;
const double pi = 3.141592653589793;
const double Fs = 1000;
for (idx1 = 0; idx1 < 256; idx1++) {
double t = idx1 / Fs;
result[idx1] = 100 * sin(2 * pi * 100 * t);;
}
}
同时输入参数N也要进行适当修正,添加<stdio.h> 和getchar()等辅助打印函数。
这里需要注意的是,生成的c++代码输出变量是根据实际输出决定的一个结构体类型变量,我们要在理解该结构体的基础上进行调试及打印。
比如当输出复数时,类型为emxArray_creal_T ,当输出实数时,类型为emxArray_real_T 。
代码:
#include "../rt_nonfinite.h"
#include "../myfft.h"
#include "main.h"
#include "../myfft_terminate.h"
#include "../myfft_emxAPI.h"
#include "../myfft_initialize.h"
#include <stdio.h>
void printArr(emxArray_creal_T *arr, int size)
{
for (int i = 0; i < size; i++)
{
printf("%4d %8.4f %8.4f \n", i, (arr->data[i]).re, (arr->data[i]).im);
}
}
static void argInit_1x256_real_T(double result[256]);
static double argInit_real_T(void);
static void main_myfft(void);
static void argInit_1x256_real_T(double result[256])
{
int idx1;
const double pi = 3.141592653589793;
const double Fs = 1000;
for (idx1 = 0; idx1 < 256; idx1++) {
double t = idx1 / Fs;
result[idx1] = 100 * sin(2 * pi * 100 * t);;
}
}
static double argInit_real_T(void)
{
return 0.0;
}
static void main_myfft(void)
{
emxArray_creal_T *B;
double dv0[256];
emxInitArray_creal_T(&B, 2);
argInit_1x256_real_T(dv0);
myfft(dv0,256 , B);
printArr(B, 256);
emxDestroyArray_creal_T(B);
}
int main(int argc, const char * const argv[])
{
(void)argc;
(void)argv;
myfft_initialize();
main_myfft();
myfft_terminate();
getchar();
return 0;
}
输出:
三、Matlab小技巧
format short g
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]){
mexPrintf("hello world\n");
}
mex hello.c
hello %脚本运行
|
请发表评论