17、MATLAB代码生成与基础功能详解

MATLAB代码生成与基础功能详解

1. MATLAB代码生成概述

在MATLAB环境中,滤波器的设计和执行都能顺利完成,甚至数学推导过程也可借助MATLAB符号数学实现。不过,设计好的滤波器需要在各种测试平台和目标设备上部署。传统的部署方式是手动将MATLAB程序重写为适用于不同硬件平台的C和C++代码,这个过程既繁琐又耗时,还需要多次验证准确性。其整体流程如下:

graph LR
    A[MATLAB代码开发] --> B[代码转换为C和C++]
    B --> C[目标部署]
    C --> D[测试与验证]
    D --> E{是否通过}
    E -- 否 --> B
    E -- 是 --> F[完成]

MATLAB提供了MATLAB Coder来从MATLAB程序生成C和C++代码。生成的代码可以以可读和可移植的格式作为源代码或库集成到现有项目中。对于数学复杂的算法,可先在MATLAB环境中开发,接口程序则用C和C++编写,MATLAB Coder会生成相应的C和C++代码。此外,还能将生成的代码编译为MEX函数,在MATLAB环境中进行验证和加速。MEX即“MATLAB可执行文件”,MEX子例程可以像MATLAB函数一样通过命令行调用。

2. 代码生成准备

2.1 检查编译器

代码生成仅支持MATLAB函数,而非一般脚本,因此需将算法拆分为单个函数。在进行代码生成前,要检查编译器,可使用以下命令:

>> mex -setup 

若没有支持的编译器或SDK,会出现如下错误信息:

Error using mex 
No supported compiler or SDK was found. You can install the freely available 
MinGW-w64 C/C++ 
compiler; see Install MinGW-w64 Compiler. For more options, visit 
http://www.mathworks.com/support/compilers. 

此时,需要安装开源编译器MinGW64,安装步骤如下:
1. 点击HOME功能区标签。
2. 选择Add-Ons。
3. 点击Get Add-Ons。
4. 搜索‘gcc’。
5. 选择并安装‘MATLAB Support for MinGW-w64 C/C++ Compiler’。

2.2 示例滤波器函数

以下是一个用于MEX函数的示例滤波器函数:

function [y] = myfilter1(x) 
%#codegen 
% For code generation, you should put the codegen hashtag in above
persistent d1 % Static variable for function
if isempty(d1) % If it is not defined, the function compute filter coefficient
    d1 = dsp.FIRFilter('Numerator',fir1(50,0.1)); % Actual filter
end 
y = d1(x); % Filter execution
end 

在该滤波器函数中,由于使用了静态变量和条件语句,滤波器系数只需计算一次。但并非所有MATLAB内置函数都与代码生成兼容,可访问相关网站查看兼容性。适合代码生成的滤波器选择有:dsp.FIRFilter、dsp.IIRFilter、dsp.HighpassFilter、dsp.LowpassFilter。可在命令窗口输入以下指令检查适用性:

coder.screener('myfilter1')

2.3 生成和编译C代码

若检查无误,可生成并编译 myfilter1.m 函数的C代码:

codegen myfilter1 -args {randn(4001,1)}

最后一个参数指定了滤波器函数的输入参数,需注意参数大小要与调用参数大小对应,这里的4001是MATLAB声音的大小。

2.4 测试代码与执行时间对比

以下是MATLAB函数的测试代码:

data = load('mtlb.mat'); % Load sound
x = data.mtlb; 
Fs = data.Fs; 
tic 
y = myfilter1(x); % Filter algorithm (Change this for compiled version)
toc 
figure, 
subplot(211), spectrogram(x,128,120,128,Fs) 
title('Input') 
subplot(212), spectrogram(y,128,120,128,Fs) 
title('Output') 

执行上述代码后,可得到输入和输出信号的频谱图。使用 tic toc 函数可测量执行时间,示例执行时间如下:

Elapsed time is 0.265705 seconds.

将滤波器函数替换为MEX函数后的代码如下:

tic 
y = myfilter1_mex(x); % Filter algorithm (Change this for compiled version)
toc 

MEX函数的执行时间如下:

Elapsed time is 0.001380 seconds.

代码生成和编译带来的加速比可通过以下公式计算:
[
Speedup = \frac{Execution\ time\ with\ MATLAB\ code}{Execution\ time\ with\ MEX\ code}
]
根据上述执行时间,MEX的加速比为192.54,这表明MEX代码比MATLAB内置代码快192.54倍。对于1024样本大小的帧,需要重新生成MEX函数:

codegen myfilter1 -args {randn(1024,1)}

3. MATLAB基础功能

3.1 MATLAB界面与命令执行

打开MATLAB后,会看到四个窗口空间:
- 当前文件夹:显示工作目录和文件。
- 命令窗口:用于输入命令并立即执行。
- 工作区:展示变量和数据。
- 编辑器 - 无标题:点击新建按钮后,可在编辑器窗口编写脚本进行编程。

执行MATLAB命令的方式有:
- 在命令窗口输入命令并按回车键。
- 在编辑器窗口编写程序,然后按 Ctrl + Enter 键。
也可通过点击运行按钮执行脚本程序。MATLAB编程的一大优势是无需担心变量问题,可直接创建和使用变量。例如,在命令窗口创建变量 a b 并初始化:

>> a = 1 
a = 
     1 
>> b = 2 
b = 
     2 
>> a+b 
ans = 
     3 
>> 

若要清除命令窗口,可输入 clc

3.2 矩阵和数组操作

MATLAB对基于矩阵和数组的线性代数运算有强大支持,可创建矩阵和数组,示例如下:

>> a = [1 2 3] 
a = 
     1     2     3 
>> b = [4, 5, 6] 
b = 
     4     5     6 
>> c = [7; 8; 9] 
c = 
     7 
     8 
     9 
>> d = [1 2 3; 4 5 6; 7 8 9] 
d = 
     1     2     3 
     4     5     6 
     7     8     9 
>> e = d*a 
Error using  *  
Incorrect dimensions for matrix multiplication. Check that the number of 
columns in the first matrix matches the number of rows 
in the second matrix. To perform elementwise multiplication, use '.*'. 
 >> e = a*d 
e = 
    30    36    42 
>> 

MATLAB中的大多数算术运算符执行线性代数运算,要求矩阵之间的维度匹配。以下是算术运算符列表:
| 符号 | 作用 |
| ---- | ---- |
| + | 加法 |
| - | 减法 |
| * | 矩阵乘法 |
| / | 矩阵右除法 |
| \ | 矩阵左除法 |
| ^ | 矩阵幂 |
| ’ | 复共轭转置 |
| .* | 元素级乘法 |
| ./ | 元素级右除法 |
| .\ | 元素级左除法 |
| .^ | 元素级幂 |
| .’ | 转置 |

逻辑和关系运算符列表如下:
| 符号 | 作用 |
| ---- | ---- |
| == | 等于 |
| ~= | 不等于 |
| > | 大于 |
| >= | 大于或等于 |
| < | 小于 |
| <= | 小于或等于 |
| & | 逻辑与 |
| | | 逻辑或 |
| && | 逻辑与(短路) |
| || | 逻辑或(短路) |
| ~ | 逻辑非 |

3.3 矩阵生成与操作

可使用MATLAB函数生成矩阵,部分函数如下表所示:
| 函数 | 作用 |
| ---- | ---- |
| zeros | 创建全零数组 |
| ones | 创建全一数组 |
| rand | 生成均匀分布的随机数 |
| eye | 创建单位矩阵 |

示例代码如下:

>> rng('default') 
>> aa = rand(3,3) 
aa = 
    0.8147    0.9134    0.2785 
    0.9058    0.6324    0.5469 
    0.1270    0.0975    0.9575 
>> bb = ones(3,2) 
bb = 
     1     1 
     1     1 
     1     1 
>> 

还可通过连接数组来生成更大的矩阵,示例如下:

>> rng('default') 
>> bb = randi(10,2,3) 
bb = 
     9     2     7 
    10    10     1 
>> cc = [bb bb] 
cc = 
     9     2     7     9     2     7 
    10    10     1    10    10     1 
>> dd = [bb, bb] 
dd = 
     9     2     7     9     2     7 
    10    10     1    10    10     1 
>> ee = [bb; bb] 
ee = 
     9     2     7 
    10    10     1 
     9     2     7 
    10    10     1 
>> 

使用索引可访问或修改数组中的元素,示例如下:

>> bb = randi(100,4,4) 
bb = 
    23    54    11    82 
    92   100    97    87 
    16     8     1     9 
    83    45    78    40 
>> bb(2,4) 
ans = 
    87 
>> bb(14) 
ans = 
    87 
>> bb(2,4)=0 
bb = 
    23    54    11    82 
    92   100    97     0 
    16     8     1     9 
    83    45    78    40 
>> bb(2,1:3) 
ans = 
    92   100    97 
>> bb(:,2) 
ans = 
    54 
   100 
     8 
    45 
>> bb(end,:) 
ans = 
    83    45    78    40 
>> cc = 0:5:30 
cc = 
     0     5    10    15    20    25    30 
>> dd = 1:10 
dd = 
     1     2     3     4     5     6     7     8     9    10 
>> 

3.4 函数使用与帮助

可使用 help doc 函数查看函数的输入和输出参数格式,例如:

>> help max 
 max    Largest component. 
    ... 
    [Y,I] = max(X) returns the indices of the maximum values in vector I. 
    If the values along the first non-singleton dimension contain more 
    than one maximal element, the index of the first one is returned. 
    ... 
    Example:  
        X = [2 8 4; 7 3 9] 
        max(X,[],1) 
        max(X,[],2) 
        max(X,5) 
    ... 
>> 

3.5 数值计算与绘图

以下是一个数值求解方程的示例:

x,可执行以下代码:
```matlab
x = -10:0.1:10;          
% Input values
y = x.^2-1;             
% Output equation
[k1,I1] = min(y)         
% Find the min value at k1 and location I1
[k2] = find(y<0)         
% Find the locations for negative output
y(k2)                 
% Corresponding negative values
[k3] = find(y==0)        
% Find the zero locations
y(k3)                  
% Verify the zero outputs 

MATLAB拥有强大的可视化工具,可进行2-D和3-D绘图。以下是2-D绘图示例:

x = 0:pi/100:2*pi;       
% Input
y1 = sin(x);             
% sine function
y2 = cos(x);             
% cosine function
figure, 
plot(x,y1,x,y2), grid    
% Line plot for sine and cosine
title('Example 1') 
legend('sin(\omega)','cos(\omega)');  % Legend with special char
xticks([0 pi/2 pi 3*pi/2 2*pi])        % Tick position
xticklabels({'0','\pi/2','\pi','3\pi/2','2\pi'})    
% Tick label
xlim([0 2*pi])                   
% x display range
ylim([-1.5 1.5])                 
% y display range
xlabel('\omega')                 
% x label
ylabel('Magnitude')              
% y label
figure, 
subplot(211), stem(x,y1), grid   
% Subplot with stem 
title('Example 2') 
ylabel('sin(\omega)') 
xticks([0 pi/2 pi 3*pi/2 2*pi]) 
xticklabels({'0','\pi/2','\pi','3\pi/2','2\pi'}) 
xlim([0 2*pi]) 
subplot(212), stem(x,y2), grid 
ylabel('cos(\omega)') 
xticks([0 pi/2 pi 3*pi/2 2*pi]) 
xticklabels({'0','\pi/2','\pi','3\pi/2','2\pi'}) 
xlim([0 2*pi]) 
xlabel('\omega') 

3-D绘图示例如下:

[X,Y] = meshgrid(-2:0.1:2); 
% Cartesian grid
Z = exp(-(X.^2+Y.^2));        
% 2-D Gaussian function Z = f(X,Y)
figure, 
surf(X,Y,Z)                      
% 3D surface plot 
title('3-D Normal Distribution')      
% Title
xticks([-2 -1 0 1 2])               
% Tick position
xticklabels({'-2','-1','x_0','1','2'})       % Tick label
xlabel('x')                        % x axis label
yticks([-2 -1 0 1 2])                % Tick position
yticklabels({'-2','-1','y_0','1','2'})       % Tick label 
ylabel('y')                       
% y axis label
zlabel('e^{-((x-x_0)^2+(y-y_0)^2)}')   
% z axis label
colormap('gray')              
% Color bar color configuration
colorbar                      
% Color bar

3.6 MATLAB函数创建与执行

可创建新的脚本作为函数,函数格式如下:

function [outputArg1,outputArg2] = untitled2(inputArg1,inputArg2)
%UNTITLED2 Summary of this function goes here 
%   Detailed explanation goes here 
outputArg1 = inputArg1; 
outputArg2 = inputArg2; 
end 

以简单的求和函数为例:

function [z] = Mysum(x,y) 
% Compute the sum of two variables or arrays 
% z = x+y 
% Example 
% x = [1 2 3]; 
% y = [3 5 7]; 
% z = Mysum(x,y) 
% Created by Keonwook Kim 
% Jan. 23rd 2019 
z = x+y; 
end 

保存函数为 Mysum.m 后,可使用 help 函数查看注释并执行示例:

>> help Mysum 
  Compute the sum of two variables or arrays 
  z = x+y 
  Example 
  x = [1 2 3]; 
  y = [3 5 7]; 
  z = Mysum(x,y) 
  Created by Keonwook Kim 
  Jan. 23rd 2019 
>>   x = [1 2 3]; 
  y = [3 5 7]; 
  z = Mysum(x,y) 
z = 
     4     7    10 
>> 

3.7 代码调试与常用命令

可使用双百分号(%%)将MATLAB程序划分为多个部分,移动光标选中部分后,按 Ctrl + Enter 键可执行所选部分。在命令窗口,可通过点击向上箭头键召回命令历史,输入字符可缩小历史范围。常用命令如下:
- clear all:清除所有变量
- clc:清除命令窗口
- clf:清除当前图形
- close all:关闭所有图形窗口
- lookfor ‘keyword’:搜索所有MATLAB文件中的关键字

4. 代码生成的进一步应用与优化

4.1 系统对象与帧处理

在处理音频数据时,可采用系统对象和帧处理的方式。以下是一个示例代码,展示了如何使用系统对象进行帧处理:

FrameSize = 1024;  
% Frame size
reader = dsp.AudioFileReader('handel.ogg','SamplesPerFrame',FrameSize); 
% Audio file reader object 
P = audioDeviceWriter(reader.SampleRate);  % Audio device writer object
time = 0;  
% Execution time initialization
while ~isDone(reader) 
    x = reader(); 
    tic; 
    y = myfilter1(x); % Filter algorithm (Change this for compiled version) 
    time = time + toc; 
    P(y); 
end 
time 

在上述代码中,音频文件被分割成多个帧进行处理,每次处理一帧数据。执行时间会累积多个帧的处理时间。

4.2 MEX函数在系统对象中的应用

将上述代码中的滤波器函数替换为MEX函数,可进一步提高处理速度:

... 
while ~isDone(reader) 
    ... 
    y = myfilter1_mex(x); % Filter algorithm (Change this for compiled version)
    time = time + toc; 
    ... 
end 
time 

通过这种方式,MEX函数在系统对象中的执行时间会显著减少。根据示例,MEX函数的执行时间为0.0203秒,而原MATLAB函数的执行时间为0.2069秒,加速比为10.2。不过,由于分段执行需要初始化和结束执行的开销,性能提升会有所降低,但总体来说,MEX函数仍能提供显著的加速效果。

4.3 代码生成的注意事项

  • 函数兼容性 :并非所有MATLAB函数都支持代码生成,在进行代码生成前,需要检查函数的兼容性。可访问相关网站查看支持C/C++代码生成的函数和对象列表。
  • 参数匹配 :在生成代码时,输入参数的大小必须与调用时的参数大小对应,否则可能会导致错误。例如,在生成 myfilter1 函数的MEX函数时,需要根据实际输入数据的大小指定参数。
  • 编译器安装 :确保安装了支持的编译器,如MinGW64。若没有可用的编译器,可按照以下步骤安装:
    1. 点击HOME功能区标签。
    2. 选择Add-Ons。
    3. 点击Get Add-Ons。
    4. 搜索‘gcc’。
    5. 选择并安装‘MATLAB Support for MinGW-w64 C/C++ Compiler’。

5. MATLAB基础功能的高级应用

5.1 特殊字符与TeX标记

在绘图时,可使用TeX标记添加特殊字符和希腊字母。以下是一些常用的TeX标记及其对应的符号:
| 字符序列 | 符号 | 字符序列 | 符号 |
| ---- | ---- | ---- | ---- |
| ^{ } | 上标 | \delta | δ |
| _{ } | 下标 | \epsilon | ϵ |
| \bf | 粗体字体 | \theta | θ |
| \it | 斜体字体 | \pi | π |
| \alpha | α | \omega | ω |
| \beta | β | \Omega | Ω |
| \gamma | γ | \rightarrow | → |

例如,在绘图的标题、标签和图例中使用这些特殊字符,可使图形更加专业和清晰。以下是一个使用特殊字符的绘图示例:

x = 0:pi/100:2*pi;       
% Input
y1 = sin(x);             
% sine function
y2 = cos(x);             
% cosine function
figure, 
plot(x,y1,x,y2), grid    
% Line plot for sine and cosine
title('Example with Special Characters') 
legend('sin(\omega)','cos(\omega)');  % Legend with special char
xticks([0 pi/2 pi 3*pi/2 2*pi])        % Tick position
xticklabels({'0','\pi/2','\pi','3\pi/2','2\pi'})    
% Tick label
xlim([0 2*pi])                   
% x display range
ylim([-1.5 1.5])                 
% y display range
xlabel('\omega')                 
% x label
ylabel('Magnitude')              
% y label

5.2 函数的高级应用

MATLAB函数可用于解决各种复杂的问题。例如,可使用 min find 函数求解方程的最小值、负数和零的位置。以下是一个示例:

x = -10:0.1:10;          
% Input values
y = x.^2-1;             
% Output equation
[k1,I1] = min(y)         
% Find the min value at k1 and location I1
[k2] = find(y<0)         
% Find the locations for negative output
y(k2)                 
% Corresponding negative values
[k3] = find(y==0)        
% Find the zero locations
y(k3)                  
% Verify the zero outputs 

通过这些函数,可对给定的函数进行数值计算和分析。

5.3 代码优化与调试技巧

  • 代码分段执行 :使用双百分号(%%)将代码划分为多个部分,便于调试和逐步执行。在调试时,可只执行部分代码,检查中间结果。
  • 命令历史的利用 :在命令窗口,可通过点击向上箭头键召回命令历史,输入字符可缩小历史范围。这有助于快速重复执行之前的命令,提高效率。
  • 常用命令的使用 :熟练掌握常用命令,如 clear all clc clf close all lookfor ‘keyword’ ,可提高代码的开发和调试效率。

6. 总结

MATLAB是一个强大的工具,具有丰富的功能和广泛的应用场景。通过MATLAB代码生成,可将MATLAB程序转换为C和C++代码,提高代码的执行效率和可移植性。在进行代码生成时,需要注意函数的兼容性、参数匹配和编译器的安装。

MATLAB的基础功能,如矩阵和数组操作、函数使用、绘图和代码调试等,为用户提供了便捷的编程环境。通过合理运用这些功能,可解决各种复杂的问题。同时,MATLAB的可视化工具可帮助用户直观地展示数据和结果。

在实际应用中,可根据具体需求选择合适的方法和工具,充分发挥MATLAB的优势。无论是滤波器设计、音频处理还是数值计算,MATLAB都能提供有效的解决方案。

6.1 关键知识点回顾

  • 代码生成 :使用MATLAB Coder生成C和C++代码,编译为MEX函数可提高执行速度。
  • 基础功能 :矩阵和数组操作、函数使用、绘图和代码调试是MATLAB的核心基础功能。
  • 注意事项 :代码生成时要注意函数兼容性、参数匹配和编译器安装。

6.2 未来展望

随着技术的不断发展,MATLAB的功能将不断完善和扩展。未来,MATLAB可能会在人工智能、机器学习等领域发挥更大的作用。同时,代码生成技术也将不断优化,提高生成代码的质量和性能。

对于开发者来说,不断学习和掌握MATLAB的新功能和技巧,将有助于提高开发效率和解决问题的能力。希望本文能为读者提供有价值的参考,帮助大家更好地使用MATLAB。

6.3 操作流程总结

以下是MATLAB代码生成和基础功能使用的操作流程总结:

graph LR
    A[MATLAB代码开发] --> B[检查编译器]
    B -- 无编译器 --> C[安装MinGW64编译器]
    B -- 有编译器 --> D[创建滤波器函数]
    C --> D
    D --> E[检查函数适用性]
    E -- 适用 --> F[生成和编译C代码]
    F --> G[测试代码]
    G --> H[对比执行时间]
    I[MATLAB基础功能学习] --> J[矩阵和数组操作]
    I --> K[函数使用与帮助]
    I --> L[绘图与可视化]
    I --> M[代码调试与常用命令]

通过以上流程,可逐步掌握MATLAB代码生成和基础功能的使用方法。在实际应用中,可根据具体需求选择合适的步骤进行操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值