本笔记首先对DSP的特点及其选型进行了描述,然后重点记录DSP开发环境的搭建及基础工程示例,对为DSP开发新手有一定的指导作用。
初次选型建议:
最先考虑C2000系列,如果满足需求,选型型号: TMS320F28335(支持FPU,150MHz,100元左右);
其次考虑C674X系列,如TMS320C6747(375~456-MHz,3648 MIPS and 2736 MFLOPS,100元左右);
从初版学习开发考虑,建议选用TI的DSP,其资源和技术支持均非常成熟。
本章搭建示例基于c2000系列,主要为裸机开发,资源有限不建议运行OS,其他系列可参考搭建。
经实际测试ccs版本选择应注意以下事项:
ccs版本较多,win10系统不支持ccs6以下的版本;
ccs6以上的版本去掉了软件仿真功能;
ccs9版本只支持64位系统(该版本不能移植老版本的软件仿真功能);
本文选择安装 ccs6
最新ccs9版本推荐使用 c2000ware;
ccs9之前版本使用 controlSUITE;
新建一个基于TMS320F28335的工程,如下所示:
空工程组成介绍:
cmd文件
由于嵌入式DSP资源比较紧张,存在内部RAM、Flash 和外部RAM与Flash,需要人工干预来进行合理的资源分配;
链接配置文件,给出了程序空间和数据空间的设置,及编译后各程序段在程序或数据空间的具体位置。类似于IAR的 icf文件和 keil 的sct文件。
一般ccs工程有两个cmd文件,一个对寄存器进行存储映射,一个是对Flash, Ram进行存储分配。
上图中的 28335_RAM_lnk.cmd 定义了程序、数据等在Ram上的分配,即程序运行与ram,通常用于仿真调试,一般情况下直接用TI给的,不需要做修改即可满足调试用。
当程序需要下载固化时,选择 F28335.cmd。
DSP2833x_Headers_nonBIOS.cmd 这个文件就是寄存器的存储映射,当工程实际操作硬件时需要添加到工程中。
targetConfigs
仿真器的配置,直接双击文件选择使用的仿真器和对应芯片型号即可,后面讲述怎么添加软件仿真器功能。
已安装好 controlSUITE。
设备基础软件库:D:\ti\controlSUITE\device_support\f2833x\v142;
其他的应用库到时按需添加。
下面我们移植官方软件库实现简单的GPIO控制功能。
在工程目录下面 DSP2833x_Libraries 文件夹,用于存放从controlSUITE中拷贝出来的库文件。
将 DSP2833x_common 和 DSP2833x_headers 拷贝到 DSP2833x_Libraries目录中。
在工程中新建 APP(用户应用驱动),User(用于程序),Libraries(官方库),cmd等文件夹
最小工程所需文件按下图所示添加到工程中
工程头文件路径包含
GPIO反转程序编写
#include"DSP2833x_Device.h" //芯片型号、外设使能相关宏定义
#include"DSP2833x_Examples.h" //
/**
* @brief LED使用GPIO外设初始化
*/
void LED_Init(void)
{
EALLOW; //关闭写保护
SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1; // 开启GPIO时钟
//LED1端口配置
GpioCtrlRegs.GPCMUX1.bit.GPIO68=0; //设置为通用GPIO功能
GpioCtrlRegs.GPCDIR.bit.GPIO68=1; //设置GPIO方向为输出
GpioCtrlRegs.GPCPUD.bit.GPIO68=0; //使能GPIO上拉电阻
GpioDataRegs.GPCSET.bit.GPIO68=1; //设置GPIO输出高电平
EDIS; //开启写保护
}
/*
* @brief 主程序
*/
void main(void)
{
InitSysCtrl(); //系统时钟初始化,默认已开启F28335所有外设时钟
LED_Init();
while(1)
{
GpioDataRegs.GPCTOGGLE.bit.GPIO68=1;//设置GPIO输出翻转信号
DELAY_US(1000);
}
}
编译没有错误,基础工程搭建成功。
本方法适用于从 ccs6-ccs8.
1.下载仿真功能文件
链接: https://pan.baidu.com/s/1eZT7SGoGIRRsxPYCOLz3Xw 提取码: z94n
2.拷贝文件到ccs指定位置
找到CCS安装路径,将网盘中的simulator文件夹复制到CCS安装路径中的ccs_base文件夹内;
将网盘中的configurations文件夹复制到ccs_base\common\targetdb\文件夹下;
将网盘中的tisim_connection.xml复制到ccs_base\common\targetdb\connections\文件夹下;
将网盘中的devicer文件夹中的内容复制到安装路径ccs_base\common\targetdb\drivers\文件夹下;
重新打开ccs,即可为工程配置软件仿真如下:
接下来工程就支持软件仿真了,当然涉及到外设相关操作时会出错(比如ADC采集)。
测试代码如下
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
#include "math.h"
#define PI 3.1415926 //定义圆周率
#define Fs 1000 //定义采样频率 Hz
#define F1 100 //信号频率 Hz
#define F2 20
#define Sample_points 1024 //采样点数
float signal1[Sample_points];
float signal2[Sample_points];
int main(void)
{
int i;
float t;
for(i=0;i<Sample_points;i++)
{
t = i*1.0/Fs;
signal1[i] = sin(2*PI*F1*t);
signal2[i] = sin(2*PI*F2*t);
}
while(1);
}
很简单的一段代码,大致意思就是生成了两个不同频率的正弦信号,分别保存在了数组signal1和signal2中。
下面我们通过软件仿真功能将代码运行起来,同时同步graph工具图形化显示函数计算数据。
Graph设置如下:
运行程序,显示效果如下
接着我们看其傅里叶变换,Graph提供直接生成fft功能,点击菜单栏Tools->Graph->FFT Magnitude,如图所示:
正玄函数fft变换显示如下:
这一节将需要进行稍微复杂一点的操作,涉及到变量存储的分配及cmd文件修改,FFT计算原理,函数库及其运行支持库的设置,CFFT相关库函数等知识点。
利用CCS进行DSP编程时,如果不指定变量的存储位置,那么编译器会自动给变量分配存储位置。但是,有些时候,需要将某个变量存放到某个特定的位置,这个时候就可以利用#pragma DATA_SECTION指令了。
如进行CFFT和ICFFT都要求输入的数组格式对齐,即变量存储的起始地址为2xFFTsize*sizeof(float),例如256点的FFT变换,则变量的起始地址必须是1024的倍数,格式对齐的方式利用变量定义的方式进行。
如:
#pragma DATA_SECTION(RFFTin1Buff, "RFFTdata1");
float32 RFFTin1Buff[RFFT_SIZE];
定义 RFFTin1Buff 数组到 RFFTdata1的RAM段;
RFFTdata1再cmd文件中进行RAM分配,后面实例代码中进行说明。
利用#pragma CODE_SECTION指令可以将程序从Flash搬到RAM中运行,从而提高程序执行速率。
这个部分后面涉及程序优化时再进行详细描述。
1.拷贝dsp FPU运算库到工作区间,便于工程引用;
2.给工程添加dsp FPU运算库,从controlSUITE拷贝;
3.FPU库头文件路径引用及编译器相关设置
选择fpu运行库
FPU头文件路径添加
示例程序:
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
#include "math.h"
#include "float.h"
#include "FPU.h" //dsp 浮点运算库
#define RFFT_STAGES 8 //RFFT运算阶数
#define RFFT_SIZE (1 << RFFT_STAGES)
#pragma DATA_SECTION(RFFTin1Buff,"RFFTdata1"); //Buffer alignment for the input array,
float32 RFFTin1Buff[RFFT_SIZE]; //RFFT_f32u(optional), RFFT_f32(required)
//Output of FFT overwrites input if
//RFFT_STAGES is ODD
#pragma DATA_SECTION(RFFToutBuff,"RFFTdata2");
float32 RFFToutBuff[RFFT_SIZE]; //Output of FFT here if RFFT_STAGES is EVEN
#pragma DATA_SECTION(RFFTmagBuff,"RFFTdata3");
float32 RFFTmagBuff[RFFT_SIZE/2+1]; //Additional Buffer used in Magnitude calc
#pragma DATA_SECTION(RFFTF32Coef,"RFFTdata4");
float32 RFFTF32Coef[RFFT_SIZE]; //Twiddle buffer
float RadStep = 0.1963495408494f; // Step to generate test bench waveform
float Rad = 0.0f;
RFFT_F32_STRUCT rfft;
void main(void)
{
Uint16 i;
// InitSysCtrl(); //没有硬件支撑时,予以注销
DINT;
// InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
// InitPieVectTable();
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
// 清空输入缓存
for(i=0; i < RFFT_SIZE; i++)
{
RFFTin1Buff[i] = 0.0f;
}
// 测试样例波形
Rad = 0.0f;
for(i=0; i < RFFT_SIZE; i++)
{
RFFTin1Buff[i] = sin(Rad) + cos(Rad*2.3567); // 实部输入信号
Rad = Rad + RadStep;
}
rfft.FFTSize = RFFT_SIZE; // FFT变换的长度,FFTSize=2^stage
rfft.FFTStages = RFFT_STAGES; // 傅里叶变换的阶数
rfft.InBuf = &RFFTin1Buff[0]; // 输入数组
rfft.OutBuf = &RFFToutBuff[0]; // 输出数组
rfft.CosSinBuf = &RFFTF32Coef[0]; // 转化因子数组
rfft.MagBuf = &RFFTmagBuff[0]; //
RFFT_f32_sincostable(&rfft); // 计算傅里叶变换的转化因子 Calculate twiddle factor
for (i=0; i < RFFT_SIZE; i++)
{
RFFToutBuff[i] = 0; //Clean up output buffer
}
for (i=0; i < RFFT_SIZE/2; i++)
{
RFFTmagBuff[i] = 0; //Clean up magnitude buffer
}
RFFT_f32(&rfft); //实数傅里叶变换
RFFT_f32_mag(&rfft); //计算幅值 Calculate magnitude
for(;;);
} //End of main
上面示例程序中使用 #pragma DATA_SECTION 定义了一些数组到RAM段,这些RAM段须在cmd文件中定义分配。
设置仿真器为软件仿真器,编译程序没有错误,然后运行。
设置Graph及数据波形显示如下:
样例输入波形:
RFFT变换之后的波形:
待续…
本章开发基于TMS320C6748,运行TI-RTOS.
总体来说就是TI提供XDC标准的SDK(里面包含如函数库、BIOS、DSP库等),通过XDCtools进行编译,整体以包的形式操作,而无需添加c文件到工程中。
理解CCS的这个工程框架,有利于工程的搭建。
CCS8.3.0
ti-processor-sdk-rtos-omapl138-lcdk-05.03.00.07
这个组合经测试正常,因为使用TI的sdk需要考虑到 ccs、XDCtools、及sdk三者的版本匹配问题,否则程序无法正确编译。
很遗憾的是首先老版本软件仿真器不支持C6748芯片,CCS8.3更是运行软件仿真器出错,如需深入调试还是需要硬件支持来调试功能。
CCS添加sdk包
Window–>Preferences–>Code Composer Studio–>Products
点击Add,添加我们安装的sdk软件包
我们会看到下面会出现我们芯片所需要的软件包,点击Apply,然后ccs会提示安装sdk里面包含的包,安装完成后ccs重启。
新建SYS/BIOS工程
File–>New–>CCS Project
选择工程需要的组件
这样一个基础的RTOS工程就创建完成,程序编译正常。