| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 人工智能 -> CCS中C语言应用开发实例 -> 正文阅读 |
|
[人工智能]CCS中C语言应用开发实例 |
山东大学信息学院DSP课程实验二 【实验目的】 ?? 1. 熟练掌握DSP开发流程 2. 掌握运用C语言基于CCS的项目设计思路及过程 【实验要求】 ? 1. 利用MATLAB的滤波器设计软件,生成低通滤波器、高通滤波器,分别给出滤波器系数。 2. 利用MATLAB产生由不同的正弦波合成的波形文件,送入CCS。 3. 编写C程序,分别实现低通、高通滤波,用CCS画出波形,给出结果分析 4. 利用编译器的op选项,对实验二的C语言程序按照级别进行优化,给出耗时的变化的分析。 5. 应用CCS的内联函数实现低通、高通滤波,与步骤1中的耗时进行比较 【实验具体内容】 1. 利用MATLAB的滤波器设计软件,生成低通滤波器、高通滤波器,分别给出滤波器系数。 采用开发环境为:Win 10 Matlab2020a版本
图1.1 ?打开FilterDesigner 或直接选择Matlab中APP选择中的:FilterDesigner 图1.2 ?FilterDesigner设计工具
选择FIR等波纹型、滤波器阶数200阶,采样频率4096、=200Hz/=300Hz 图1.3 ?FIR低通滤波器设计 设置好参数后点击“设计滤波器”,可通过观察“幅值响应”波形图直观的看出滤波效果。接下来需要将生成的滤波系数导出以便后续加载到CCS中。 图1.4 ?点击目标生成头文件 图1.5 生成C头文件界面 生成C头文件如下: 图1.6 ?生成低通滤波器系数头文件
选择FIR等波纹型、滤波器阶数200阶,采样频率4096、=800Hz/=100Hz 图1.7 ?高通滤波器设计 同上述步骤生成C头文件: 图1.8 ?生成高通滤波器系数头文件 2. 利用MATLAB产生由不同的正弦波合成的波形文件,送入CCS。 在进行DSP算法设计时,我们通常会在Matlab上验证一下算法是否正确,然后再把算法移植到DSP当中,然而在移植的过程中会不可避免的出现各种问题,这时就需要将DSP内存中的数据导出来传到Matlab中进行分析处理,同时我们也需要从Matlab传递一些数据到DSP当中,比如我们想生成某种比较复杂的数据(例如各种类型的噪声),如果用C语言来写的话将会非常的麻烦,而这些用matlab能够亲而易举的完成,这时我们只需要将matlab生成的数据导入到DSP中就可以了 首先需要利用Matlab生成若干个数据,然后存储为dat格式的文件,然后通过CCS将dat格式的文件导入到DSP中。 dat文件时CCS能够识别的文件之一、CCS支持的dat文件格式为: 文件头为: 定数 ??数据格式 起始地址 页类型 ??数据块大小 1651 ????????1 ???????80000000 ????????0 ??????????10 固定标识???数据格式?????基地址???????页类型 ??????长度 固定标识:它的值固定为1651 数据格式:1-十六进制 ?2-十进制 ?3-十进制长整型 ?4-十进制浮点型 基地址: ?就是要存入到DSP一段内存空间的首地址 页类型: ?0-数据 ??1-程序 ? 长度: ???装入数据的长度 1)首先给出Matlab源代码: f1=100; f2=1500; fs=4096; N=1024; T=1/fs; n=0:N; y1=1024*sin(2*pi*f1*n*T); y2=1024*sin(2*pi*f2*n*T); y=y1+y2; xto_ccs=round(y); fid=fopen('input1.dat','w');%将文件头写入文件,将生成的y信号写入到文件,格式四位小数 fprintf(fid,'%d\n',xto_ccs); fclose(fid); 采用=100Hz和两种频率(高频、低频)组成噪声信号波形 图2.1 ?源代码截图
图2.2 ?生成.dat文件 用记事本的方式打开此文件里面的内容如下: 图2.3 ?生成.dat文件中内容
源程序如下: #include "stdio.h" #include "LPF1.h" #include <math.h> #include <stdlib.h> #define Length 1024 #define pi 3.1415926 ?? long yn; //保存滤波后结果,32位长整型 long input[Length]; // long output[Length]; int i; void main() { int m,n; for(n=0;n<Length+BL;n++) //卷积计算 { yn=0; for(m=0;(m<BL)&&(m<n);m++) yn+=B[m]*input[n-m]; output[n]=yn; } while(1); }
图2.4 ?设置断点 接下来打开断点管理器Breakpoints,进行断点设置 图2.5 ?打开断点管理器 图2.6 ?断点管理器内容 图2.7 ?设置断点Action 进行如下选择: File:选择所产生的.dat文件作为数据导入 Wrap Around:True Start Address:input Page:DATA Length:1024 图2.8 ?Read Data from File 设置 点击OK后即可完成Matlab合成波形文件并送入CCS 3. 编写C程序,分别实现低通、高通滤波,用CCS画出波形,给出结果分析 建立工程添加文件。建立工程,工程结构如下图所示。将在matlab中生成的c语言头文件添加至CCS工程文件夹下面。在matlab生成的CCS头文件中,需要调用matlab的头文件。将头文件拷贝到工程路径下即可。 图3.1 ?工程结构框架 只拷贝生成的头文件后,运行可能会出错,提示缺失某个文件“tmwtypes.h”。该文件在matlab安装路径下。可以直接在安装路径下搜索该文件,直接拷贝到工程路径下即可。 输入信号生成,代码如下: ??????for(i=0;i<Length;i++) ???????????????????input[i]=1024*sin(w1*i)+1024*sin(w2*i);?? 因为计算时,其他数据类型都为整数,因此需要将-1~+1的小数格式转换为整数,不然在-1~+1的小数数据绝对值不超过1,那么在内存中都将被视作0,会导致波形严重失真。所以在此处需要将小数数据转换为整数型,又因为最后输出数据类型设置为long型,为了保证在计算过程中不溢出,Q值不能设置过大。 卷积计算公式为: 在计算机中要处理的信号和处理完成后的信号都可以用数组来保存,并且信号都为因果信号,即下表没有负数项,下标可以从0开始计算 已知h(n)的长度为BL,x(n)的长度为Length,利用外层循环控制n,内层循环控制m,将卷积计算的公式可表示为如下代码。 for(n=0;n<Length+BL;n++) ????????????? ????{undefined ????????yn=0; ????????for(m=0;(m<BL)&&(m<n);m++) ????????????yn+=B[m]*input[n-m]; ????????output[n]=yn; ????} CCS仿真测试情况??
#include "stdio.h" #include "LPF1.h" #include <math.h> #include <stdlib.h> #define Length 1024 #define pi 3.1415926 int fs=4096; //采样频率 int f1=100; //信号频率 int f2=1500; //噪声频率 #define w1 2*pi*f1/fs //信号角频率 #define w2 2*pi*f2/fs //噪声角频率 long yn; //保存滤波后结果,32位长整型 long input[Length]; long output[Length]; int i; void main() { int m,n; for(i=0;i<Length;i++) input[i]=1024*sin(w1*i)+1024*sin(w2*i); //待滤波信号,乘以1024转换为Q10格式(sin范围为-1~1,将其转换为整数格式) for(n=0;n<Length+BL;n++) //卷积计算 { yn=0; for(m=0;(m<BL)&&(m<n);m++) yn+=B[m]*input[n-m]; output[n]=yn; } while(1); }
图3.2 ?调试结果
图3.3 ?设置断点
图3.4 ?装载项目 选择volume2.out文件,并点击打开 图3.5 ?选择volume2.out文件
图3.6 ?点击Run to cursor执行程序
图3.7 ?创建Graph图标窗口
①时域显示参数设置,如下图,设置完成后点击OK即可显示曲线 图3.8 ?时域显示参数设置 参数说明: Acquisition Buffer Size:表示通过仿真器从DSP的内存中读取的数据的大小。由于程序里用于存储信号的数组大小是1024,这里我们设置成1024,也可以设置成比他更小的值,这样就只能看到信号的部分图像。 Dsp Data Type:数据类型设置,因为在程序中使用的是long型数据,在这里需要设置成32位整形数据。 Index Increment:索引增量,表示每个数据点序号的相差值,这里是逐点显示的,因此默认设置为1,如果想要每隔一个点显示一个那么就应该设置成2。 Q_Value:Q值,一般这不常用,默认。 Sampling Rate Hz:以Hz为单位的采样率,在这里我们的采样率是4096,因此设置成4096。 Start Address:开始地址,表示要显示的数组的首地址,假设我们现在想要看的是数组input因此,设置这里设置成input。 Auto Scale:自动调整显示比例使其适应整个显示窗口,默认即可。 Axis Display :显示坐标轴,默认即可。 Data Plot Style:数据绘制类型,有Line和Bar两种,这里选择Line。 Display Data Size:显示数据大小,表示要将多少个点的数据进行显示,注意这个值一定要小于等于Acquisition Buffer Size,这里设置成1024。 Grid Style:网格类型,有 NoGrid, Minor Grid, Major Grid三种选项,默认即可。 Magnitude Display Scale:幅值显示类型,有Linear(线性的)Logarithmic(对数的),默认即可。 Time Display Unit:显示时间的单位有sample,s, ms, us几种可选,其中sample表示显示的点的序号,默认即可。 Use Dc Value For Graph:是否使用Dc值,一般不常用,默认即可。 ②频谱显示参数设置,如下图 图3.9 ?FFT显示参数设置 参数说明:部分参数和时域显示时的参数相同,有部分不同如下: Signal Type :信号类型,有Real,Complex这两种,此处信号数据均为实数据,因此我们选择Real,如果数据类型是Complex,选择Complex。 Frequency Display Unit :频率显示单位,有Hz,KHz,MHz三种,这里选择Hz。 FFT Order :FFT的阶数,由它来决定FFT Frame Size,例如 FFT Order 设置为5 那么FFT Frame Size 就为32 = 2^5。这里我们设置成12,那么FFT Frame Size就是4096。 FFT Frame Size :FFT做变换的点数,FFT Order决定,此处选择4096点FFT。 FFT Window Function :FFT窗函数,选择做FFT变换时采用什么窗函数,有Rectangular(矩形窗),Bartlett,Blackman,Hamming,Hanning,选择什么窗函数根据实际的需求来决定到底采用哪一个窗函数,默认即可。
①按照上述操作实现的低通滤波 图3.10 ?低通显示图形 ②将头文件中的LPF1.h文件更换成为HPF.h后,重复上述操作实现高通滤波 图3.11 ?高通显示图形
每个文件都可以设置编译器优化,右键.c文件->File Specific options>optimization level 设置成空的,即可在debug的时候避免出现异常。开编译器优化可能导致跟踪函数的变量时值是错的。编译优化的好处是加快代码运行速度,但缺点就是只能把函数当做黑盒,函数内部的bebug结果是不可靠的。所以一般将算法和流程编到不同的文件中去,因为算法文件一般都是验证完了的,不怎么需要调试,所以算法文件开适当的优化,流程文件不开优化。这样既能提高运行效率又可以不影响流程的调试 图4.1 ?选择File Specific options 图4.2 ?Opt Level选择 进行代码优化,先要找出程序的瓶颈,即占用CPU时间较多的代码,然后对其进行有针对性的优化。使用CCS提供的代码剖析工具Profile可以统计显示出程序中各个重要段和函数的运行时间,找出运算量较大的程序段,优化这些程序段,对于提高算法的性能有巨大影响。 ②使用const、restrict 关键字修饰指针:const指示编译器其修饰的指针所指向的内容不能修改;restrict指示编译器其修饰的指针与其他指针指向的内容不会覆盖,这些信息使两个指针不会访问同一存储器地址,可以消除存储器之间的相关性,这样可以并行执行多个数据的读取和运算,使代码运行达到昀大效率。
图4.3 ?打开Clock视图
图4.4 ?优化级别为NONE 图4.5 ?优化级别为o0 图4.5 ?优化级别为o1 图4.5 ?优化级别为o2 图4.5 ?优化级别为o3
????在使用fir函数之前首先要把相关的头文件和一些库文件加入到工程中,在如图的安装路径下找到并打开此头文件和一个库文件,复制到工程所在文件夹中 图5.1 ?复制相关头文件库文件 接着在工程右键打开build option选项里把头文件的路径加进去即可,最后还要把54xdsp.lib这个库文件导入工程的library中,不然会有报错 ????????? 图5.2 ?添加头文件 接着编写C文件的程序和cmd文件,核心程序如下: #include <stdio.h> #include <math.h> #include "dsplib.h" #define pi 3.1415926 //采样频率,单位Hz int fs=4096; //产生正弦波频率,单位为Hz int f1=100,f2=1500; //定义信号角频率 #define w1 2*pi*f1/fs #define w2 2*pi*f2/fs //输入波形数组大小 DATA In[1024]; /*------------等波纹设计法(Equiripple),阶数64,通带幅值衰减 Wpass=1dB,阻带幅值衰减 Wstop1=80dB---------------*/ /*通带频率 Fpass=100Hz,截止频率 Fstop=150Hz,采样频率 Fs=4096Hz*/ #pragma DATA_SECTION(lowpass,".lowpass")//定义一个数据段,需要在cmd文件中有相应的段定义 DATA lowpass[64] = { ?????-129, ?????4, ????11, ????24, ????43, ????67, ????98, ???136, ???180, ??????232, ???291, ???357, ???430, ???510, ???596, ???686, ???782, ???880, ??????981, ??1083, ??1185, ??1285, ??1381, ??1474, ??1560, ??1638, ??1708, ?????1769, ??1818, ??1856, ??1882, ??1895, ??1895, ??1882, ??1856, ??1818, ?????1769, ??1708, ??1638, ??1560, ??1474, ??1381, ??1285, ??1185, ??1083, ??????981, ???880, ???782, ???686, ???596, ???510, ???430, ???357, ???291, ??????232, ???180, ???136, ????98, ????67, ????43, ????24, ????11, ?????4, ?????-129 }; /*------------------------------------------------------------------------------------------------------*/ /*低通滤波数据缓存*/ #pragma DATA_SECTION(buf1,".buffer1")//定义一个数据段,需要在cmd文件中有相应的段定义 DATA buf1[64] ; DATA ?*buf1ptr = &buf1[0]; DATA ff1[1024];//低通滤波输出数组 void main() { ??? int i; ? printf("HelloWorld!\n"); for(i=0;i<1024;i++) //产生波形 In[i]=1024*sin(w1*i)+1024*sin(w2*i) /*fir(DATA *x, DATA *h, DATA *r,DATA **d, ushort nh, ushort nx); ????*x:待滤波信号输入 ???????? ????*h:滤波系数,即一个数组 ????*r:滤波输出 ????*d:滤波输出缓存 ????*nh:滤波器的阶数 ????*nx:待滤波信号输入的大小,即数组的大小 */ fir(In, lowpass, ff1, &buf1ptr, 64, 1024); // ?调用函数,低通滤波 while(1); } MEMORY { ???PAGE 0: ??VECT: ????? origin = 0x80, ????????len = 0x80 ???PAGE 0: ??PROG: ????? origin = 0x100, ???????len = 0x3f00 ? ???PAGE 1: ??DATA: ????? origin = 0x4000, ??????len = 0x3c00 ?? ???PAGE 1: ??f1aDATA: ??? origin = 0x8000, ??????len = 0x80 ???PAGE 1: ??f1bDATA: ??? origin = 0x8080, ??????len = 0x80 } /* MEMORY */ SECTIONS { ???.text ???> PROG PAGE 0 ??????????????/* code ????????????????????*/ ???.switch ?> PROG PAGE 0 ??????????????/* switch table info ???????*/ ???.cinit ??> PROG PAGE 0 ???.vectors > VECT PAGE 0 ???????????????/* interrupt vectors ????????*/ ??? ???.cio ????> DATA PAGE 1 ??????????????/* C I/O ????????????????????*/ ? ???.data ???> DATA PAGE 1 ??????/* initialized data ?????????*/ ???.bss ????> DATA PAGE 1 ??????/* global & static variables */ ???.const ??> DATA PAGE 1 ??????????????/* constant data ????????????*/ ???.sysmem ?> DATA PAGE 1 ??????????????/* heap ?????????????????????*/ ???.stack ??> DATA PAGE 1 ??????????????/* stack ????????????????????*/ ???.buffer1: ?{} align =64, ?load = f1aDATA PAGE 1 ?? ???.lowpass: ?{} align =64, ?load = f1bDATA PAGE 1 ????? } ??/*SECTIONS */ 由于在程序中定义了数据段,所以要在cmd文件中定义使用的数据段大小 图5.3 ?定义cmd文字内容 再次编译一下,如果没有问题的话应该是没有错误和警告的,然后就可以查看频谱了,操作跟上面看输入信号频谱一样,需要修改的是开始的地址,改为滤波输出的数组的名称即可 图5.4 ?修改滤波输出数组名 图 5.5 ?运用内联函数实现低通滤波 图5.6 ?运用内联函数实现高通滤波 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/27 4:37:25- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |