• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

基于Matlab Coder将matlab代码转换成c代码

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

最近在做信号处理相关的功能,首先在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个步骤:

  1. 开发实现特定算法功能的MATLAB代码及其测试文件
  2. 检查MATLAB代码的兼容性,确保MATLAB代码中的语句都能被转换成C代码(有些matlab代码语句并不能生成c/c++代码,例如matlab中的imread、imshow、plot等函数)
  3. 利用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++代码
  1. 在命令窗口,输入mex -setup,选中一个存在的编译器,笔者这里自带了一个c编译器,读者也可以切换为c++编译器(输入mex -setup C++)。

  2. 在命令窗口输入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文件需要进行修改。

/*
 * Arguments    : double result[256]
 * Return Type  : void
 */
static void argInit_1x256_real_T(double result[256])
{
	int idx1;
	const double pi = 3.141592653589793;
	const double Fs = 1000; //采样频率
							/* Loop over the array to initialize each element. */
	for (idx1 = 0; idx1 < 256; idx1++) {
		/* Set the value of the array element.
		Change this value to the value that the application requires. */
		double t = idx1 / Fs;
		result[idx1] = 100 * sin(2 * pi * 100 * t);;//argInit_real_T()
	}
}

同时输入参数N也要进行适当修正,添加<stdio.h>和getchar()等辅助打印函数。
这里需要注意的是,生成的c++代码输出变量是根据实际输出决定的一个结构体类型变量,我们要在理解该结构体的基础上进行调试及打印。
比如当输出复数时,类型为emxArray_creal_T,当输出实数时,类型为emxArray_real_T
代码:

/* Include Files */
#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>

/* Function Definitions */
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);
		//printf("%4d    %8.4f \n", i, arr->data[i]);
	}
}
/* Function Declarations */
static void argInit_1x256_real_T(double result[256]);
static double argInit_real_T(void);
static void main_myfft(void);

/* Function Definitions */

/*
 * Arguments    : double result[256]
 * Return Type  : void
 */
static void argInit_1x256_real_T(double result[256])
{
	int idx1;
	const double pi = 3.141592653589793;
	const double Fs = 1000; //采样频率
							/* Loop over the array to initialize each element. */
	for (idx1 = 0; idx1 < 256; idx1++) {
		/* Set the value of the array element.
		Change this value to the value that the application requires. */
		double t = idx1 / Fs;
		result[idx1] = 100 * sin(2 * pi * 100 * t);;//argInit_real_T()
	}
}

/*
 * Arguments    : void
 * Return Type  : double
 */
static double argInit_real_T(void)
{
  return 0.0;
}

/*
 * Arguments    : void
 * Return Type  : void
 */
static void main_myfft(void)
{
  emxArray_creal_T *B;
  double dv0[256];
  emxInitArray_creal_T(&B, 2);

  /* Initialize function 'myfft' input arguments. */
  /* Initialize function input argument 'v1'. */
  /* Call the entry-point 'myfft'. */
  argInit_1x256_real_T(dv0);
  myfft(dv0,256 , B);  //argInit_real_T()
  printArr(B, 256);
  emxDestroyArray_creal_T(B);
}

/*
 * Arguments    : int argc
 *                const char * const argv[]
 * Return Type  : int
 */
int main(int argc, const char * const argv[])
{
  (void)argc;
  (void)argv;

  /* Initialize the application.
     You do not need to do this more than one time. */
  myfft_initialize();

  /* Invoke the entry-point functions.
     You can call entry-point functions multiple times. */
  main_myfft();

  /* Terminate the application.
     You do not need to do this more than one time. */
  myfft_terminate();

  getchar();
  return 0;
}

输出:

三、Matlab小技巧

  • 不以科学计数法显示(参考文章
format short g
#include "mex.h"
//使用MEX必须包含的头文件
void mexFunction(int nlhs, mxArray *plhs[], 
                 int nrhs, const mxArray *prhs[]){
    mexPrintf("hello world\n");
}
mex hello.c
hello  %脚本运行

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Delphi Treeview中显示Mainmenu菜单发布时间:2022-07-18
下一篇:
Delphi之TComponent类发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap