DSP的C语言编程技术
第4章DSP软件开发与C语言编程
段名称 .text .cint
.pint .switch
.const
初始化段链接
描述 可执行代码和常量 已初始化的全局与静态变量的C初始 化记录 全局构造器(C++ constructor)表 实现switch语句表
限制 程序 64K数据
程序 程序/64K数据
已初始化的全局与静态const修饰变量, 64K数据 串常量
21
调试程序 • 连续运行与单步运行。 • 设置断点。 • 查看与修改存储单元。 • 查看与修改寄存器内容。 • 观察和编辑变量。 • 程序Animate运行和数据图形显示。
22
4.3 DSP 的C工程文件
C工程(Project)几种基本文件
• CCS 工 程 文 件 ( 扩 展 名 为 .pjt) 。 由 CCS 自 动 生 成 。 在 CC(Code Composer)软件环境中,扩展名为.mak。
29
段名称 .bss .stack .sysmem
未初始化段链接
内容 全局与静态变量 堆栈空间 malloc函数存储区
限制 64K数据 64K数据 64K数据
30
段(Section) .text .cint .pint .switch .const .bss .stack .sysmem
存储器映射表
• 源程序: 汇编语言文件(*.asm), C文件(*.c)。 • 头文件(*.h): 定义寄存器映射地址,用户自定义的常量
等。例如用于C程序的片内外设寄存器地址定义头文件 f2407_c.h,用于汇编语言程序的片内外设寄存器定义头 文件F2407REGS_A.h等。 • 链接命令文件(*.cmd)。 • 库文件(*.lib)。 C24x运行时支持库为rts2xx.lib。 • 目标文件(*.obj):COFF公共目标文件格式。 • 列表文件(*.lst):汇编生成的文件。 • 映射文件(*.map): 存储器分配。 • 可执行代码文件(*.out)。
7 基于C语言的DSP芯片开发
基于C语言的DSP芯片开发
2015年5月6日
DSP原理及应用
1
第7章基于C语言的DSP芯片开发
7.1 引言
DSP芯片开发常用的编程语言 1、汇编语言 2、高级语言(C语言) 3、两种语言的混合编程 通常用C语言或它与汇编语言的混合编程
2015年5月6日
DSP原理及应用
2
第7章基于C语言的DSP芯片开发
2015年5月6日 DSP原理及应用 12
第7章基于C语言的DSP芯片开发
7.2.2.3 中断函数
关键定interrupt,没有参数和返回值 Interrupt
void timer0() { } // cvectors.asm中BD _timer0 中断函数会自动保护所有寄存器,因 此效率不高
2015年5月6日 DSP原理及应用 7
第7章基于C语言的DSP芯片开发
7.2.1.3 其他数据类型
常数类型 int *const P = &x; const int *p = &x; 端口类型 ioprot type porthex_num ioprot unsigned port10 1、文件级声明,函数内不能出现该关键字 2、函数调用时,利用实值传递
call(port10); call(&port10);
2015年5月6日
DSP原理及应用
8
第7章基于C语言的DSP芯片开发
Volatile类型 存储区访问 volatile unsigned int *ctrl; while (*ctrl != 0xFF) ;
2015年5月6日
DSP原理及应用
函数调用
DSP课件第八章C语言编程基础
8.5 TMS320C24x C语言程序开发
TMS320C24x C语言具有特定的运行环境,为了确保C语言程序正 确运行,C语言程序开发必须维护这个环境。
8.5.1 存储器模式
TMS320C24x 的C编译器将存储器分为程序存储器和数据存储器。 程序存储器包含可执行代码,数据存储器包含外部变量、静态变量和系 统堆栈。
8.2.2 指定初始化类型
用C语言编程时,会根据需要定义全局变量和静态变量。有些全局变量 和静态变量具有初始值,有些全局变量和静态变量没有初始值。C编译器对 C程序编译后,为具有初始值的全局变量和静态变量建立了一个专门的数据 块.cinit。该块在程序运行后调入到RAM的.bss中。 .cinit调入到RAM中有 两种方法: (1)在运行时,自动初始化全局变量和静态变量; (2)在加载时,自动初始化全局变量和静态变量。
interrupt void nothing() {
return; }
//假中断子程序
8.3.5 _c_int0函数
在运行C程序之前,用户必须首先建立起C语言运行环境。
建立C语言运行环境的函数在库rts2xx.lib中。把_c_int0函数作为硬件 复位后的中断矢量入口来运行_c_int0函数。
/*CLKIN=10M,CLKOUT=40M*/
* SCSR1=0x0000;
}
8.3.4 创建假中断处理函数
(1)2407工作时,如果意外引发了内核级中断,但是却没有低层外设中断 向量装入外设中断寄存器中时,假中断向量0000h装入PIVR; (2)CPU执行一个软件中断指令INTR时,使用了参数1~6,企图用软件中 断去服务于外设中断INT1~INT6。这显然是一个错误,这时,假中断向量装 入PIVR ; (3)中断请求线发生故障,外设发出中断请求,而其INTn标志却在CPU应 答请求之前被软件清0,此时,外设中断的请求可能还没有被中断控制器确 认,中断控制器也不知道哪个外设中断向量应装PIVR,这时,假中断向量装 入PIVR .
轻松学会DSP——第5章-C程序编写和编译
C/C++系统堆栈.stack
.stack不同于DSP汇编指令定义的堆栈。DSP汇编程序 中要将堆栈指针SP指向一块RAM,用于保存中断、调 用时的返回地址,存放PUSH指令的压栈内容。
.stack定义的系统堆栈实现的功能是保护函数的返回 地址,分配局部变量,在调用函数时用于传递参数, 保护临时结果。
LNK500时使用的-c和-cr是对C语言中常量 (放在.cinit段中)的处理不同。-c(ROM 模式)表示在运行时处理,由boot.asm完成, 数据空间具有一个初始化表;而-cr则在装入 时处理,由load或者bootloader完成,数 据空间没有初始化表。如果是汇编文件进行 链接,这个参数不加。
6、汇编文件中使用C文件变量
C文件中该变量要在MAIN()函数外定义为 全局变量;
汇编中需要把该变量声明为全局标号; 汇编文件中使用绝对地址寻址方式
*(_var_name)方式访问,var_name为变 量名,同时要有“_”前缀。
三、运行环境及C编译工具
1、运行环境
C54x将存储器处理为程序存储器和数据存 储器两个线性块。程序存储器包含可执行 代码;数据存储器主要包含外部变量、静 态变量和系统堆栈。编译器的任务是产生 可重定位的代码,允许链接器将代码和数 据定位进合适的存储空间。C编译器对C语 言编译后除了生成3个基本段, 即.text、.data、.bss外,还生 成.cinit、.const、.stack、.sysmem段。
.stack定义的段大小(堆栈大小)可用链接器选项-
stack size设定,链接器还产生一个全局符号_
_STACK_SIZE,并赋给它等于堆栈长度的值,以字为 单位,缺省值为1K。
初始化过程
dsp实验二-编写一个以C语言为基础的DSP程序
实验二:编写一个以C语言为基础的DSP程序一、实验目的1.学习C语言编制程序:了解C语言程序设计方法和组成部分。
2.学习编制连接命令文件,用来控制代码的连接。
3.学会建立和改变map文件,以及利用它观察DSP内存使用情况。
4.进一步熟悉CCS调试程序。
二、实验设备1.PC机一台:操作系统为Windows2000或WindowsXP。
2.ICETEK-F2812-EDU实验箱一台。
三、实验原理1.C语言程序(1)CCS支持使用标准C语言应用程序。
当使用标准C 语言编制的程序时,其源程序文件名的后缀应为.c(如:volume.c)。
(2)CCS 在编译标准C 语言程序时,首先将其编译成相应汇编语言程序,再进一步编译成目标DSP 的可执行代码。
最后生成的是coff 格式的可下载到DSP 中运行的文件,其文件名后缀为.out。
2.命令文件的作用命令文件(文件名后缀为cmd)为链接程序提供程序和数据在具体DSP 硬件中的位置分配信息。
通过编制命令文件,我们可以将某些特定的数据或程序按照我们的意图放置在DSP 所管理的内存中。
命令文件也为链接程序提供了DSP 外扩存储器的描述。
在程序中使用CMD 文件描述硬件存储区,可以只说明使用部分,但只要是说明的,必须和硬件匹配,也就是只要说明的存储区必须是存在的和可用的。
3.内存映射(map)文件的作用一般地,开发的DSP 程序在调试好后,要固化到系统的ROM 中。
为了更精确地使用ROM空间,我们就需要知道程序的大小和位置,通过建立目标程序的map 文件可以了解DSP 代码的确切信息。
当需要更改程序和数据的大小和位置时,就要适当修改cmd 文件和源程序,再重新生成map 文件来观察结果。
另外,通过观察map 文件,可以掌握DSP 存储器的使用和利用情况,以便进行存储器方面的优化工作。
四、实验步骤1.实验准备:设置软件仿真模式。
2.建立工程文件:新建工程文件设置如图2.1。
DSP的FIR设计低通滤波C语言编写
DSP的FIR设计低通滤波C语言编写FIR(有限脉冲响应)滤波器是一种常用的数字滤波器,用于数字信号处理中的滤波操作。
FIR滤波器的设计通常包括两个主要步骤:滤波器的规格化和滤波器系数的计算。
滤波器的规格化是指确定滤波器的采样频率,截止频率以及陷波增益等参数。
在设计低通FIR滤波器时,我们需要确定滤波器的截止频率。
假设我们希望设计一个截止频率为Fs/4的低通FIR滤波器,其中Fs是采样频率。
根据滤波器设计的基本原理,我们可以得到滤波器的频率响应公式为:H(k) = (2 * Fs/4 * sin(2 * pi * Fs/4 * k))/(pi * k)其中,k是从0到N-1的整数序列,N是滤波器的长度。
经过频域设计,我们可以通过计算滤波器的频率响应公式来获得滤波器的系数。
接下来,我们将使用C语言编写一个低通FIR滤波器的代码示例。
在这个示例中,我们将实现一个截止频率为Fs/4的低通FIR滤波器,采样频率为Fs。
代码如下:```c#include <stdio.h>#include <stdlib.h>#include <math.h>//定义滤波器的长度#define N 51//定义采样频率//定义滤波器的截止频率#define Fc (Fs/4)//计算滤波器的系数void calculateCoefficients(float* coefficients)float sum = 0;for (int k = 0; k < N; k++)if (k == N/2)coefficients[k] = 2 * Fc/Fs;} elsecoefficients[k] = (sin(2.0 * M_PI * Fc * (k - N/2) / Fs)) / (M_PI * (k - N/2));}sum += coefficients[k];}//归一化滤波器的系数for (int k = 0; k < N; k++)coefficients[k] /= sum;}//应用滤波器void applyFilter(float* input, float* output, float* coefficients, int length)for (int n = 0; n < length; n++)output[n] = 0;for (int k = 0; k < N; k++)if (n - k >= 0)output[n] += input[n - k] * coefficients[k];}}}int mai//定义输入信号和输出信号的长度int length = 100;//为输入信号和输出信号分配内存空间float* input = (float*)malloc(length*sizeof(float));float* output = (float*)malloc(length*sizeof(float));//为滤波器的系数分配内存空间float* coefficients = (float*)malloc(N*sizeof(float));//生成输入信号for (int n = 0; n < length; n++)input[n] = sin(2.0 * M_PI * 1000 * n / Fs);}//计算滤波器的系数calculateCoefficients(coefficients);//应用滤波器applyFilter(input, output, coefficients, length); //打印输出信号for (int n = 0; n < length; n++)printf("%f\n", output[n]);}//释放内存空间free(input);free(output);free(coefficients);return 0;```在上面的代码示例中,我们首先定义了滤波器的长度、采样频率以及截止频率。
DSP应用程序中C代码和汇编代码的结合
DSP应用程序中C代码和汇编代码的结合◆ CEVA公司高级编译器项目经理Eran Balaish随着DSP处理器的功能日益强大,加上编译器的优化技术不断提高,以往只利用汇编语言编写DSP应用程序的普遍做法已逐渐被淘汰。
今天,几乎所有的DSP应用程序都是由C代码和汇编代码共同构成。
对于性能是核心的关键性功能,DSP工程师继续使用高度优化的汇编代码,而其它功能则采用C语言编写,以便于维护和移植。
C代码和汇编代码的结合需要DSP工程师在工具箱中备有专用工具和方法。
众所周知,汇编代码编程的性能更好,而C代码编程的优势在于编写更为方便、快捷。
为了解释清楚原因,让我们仔细对比一下汇编代码和C代码编程的优缺点。
汇编代码编程的优势● 汇编代码能够利用处理器独有的指令和各种专用硬件资源。
另一方面,C代码则是通用性的,必须支持不同的硬件平台,因此,对C代码来说,支持专用平台代码十分困难。
● 汇编代码的编程人员通常对应用非常熟悉,并可能做出编译器难以企及的设想。
● 汇编代码编程人员可以发挥人们的创造力;而编译器再先进也只是一个自动程序而已。
汇编代码编程的缺点:● 汇编代码编程人员不得不处理耗时的机器级问题,比如寄存器分配和指令调度。
而对C代码,这些问题都可交给编译器去做。
● 汇编代码编程需要拥有关于DSP架构及其指令集的专业知识,而C编码只需要掌握广为流行的C语言即可。
● 采用汇编代码,平台之间的应用移植极其困难和耗时。
而C应用程序的移植要简单得多。
图1显示了如何利用专用硬件机制来高度优化汇编代码。
左边的C代码实现方案利用模数运算创建了循环缓冲器。
右边的是高度优化的汇编代码,利用CEVA-TeakLite-III DSP核的模数机制来创建相同的缓冲器。
只要缓冲器指针(这里是r0)更新,该模数机制就自动执行模数算法。
这种运算和指针更新发生在同一个周期内,故汇编代码比C代码有效得多,其可为模数运算产生单独的指令。
在DSP应用中选择适当的C和汇编代码混合问题在于C 代码和汇编代码之间的界限究竟在哪里,答案由分析器提供的性能分析给出。
DSP的C语言编程
DSP的C语言开发一、流程步骤:main() {}下面是vectors.asm函数,该文件在每个DSP的project中(需手工加入),其中有对_c_int00的调用,而_c_int00在rts.lib中,在开发时要手工加入。
在reset 后,rom等外存中的程序已经转移到了L2 cache中,并且程序从0x0000 0000处开始执行,而0x0000 0000处的程序正是vectors.asm,以下就开始层层调用,进入main函数。
======== vectors.asm ========; Plug in the entry point at RESET in the interrupt vector table;;; ======== unused ========; plug inifinite loop -- with nested branches to; disable interrupts -- for all undefined vectors;unused .macro id.global unused:id:unused:id:b unused:id: ; nested branches to block interruptsnop 4b unused:id:nopnopnopnopnop.endm.sect ".vectors".ref _c_int00 ; C entry point.align 32*8*4 ; must be aligned on 256 word boundaryRESET: ; reset vectormvkl _c_int00,b0 ; load destination function address to b0mvkh _c_int00,b0b b0 ; start branch to destination functionmvc PCE1,b0 ; address of interrupt vectorsmvc b0,ISTP ; set table to point herenop 3 ; fill delay slotnopnop;; plug unused interrupts with infinite loops to; catch stray interrupts;unused 1unused 2unused 3unused 4unused 5unused 6unused 7unused 8unused 9unused 10unused 11unused 12unused 13unused 14unused 15Rts6000.lib来自于rts6000.src,该原文件是由多个.c和.cpp以及.asm组成的,其中关于int _args_main()的函数:这个函数就是void __interrupt c_int00()在初始化完成后调用的函数,int _args_main()函数中调用了main(argc, argv)从而正式转入main函数。
第三讲-DSP-C语言程序设计基础
先新建源程序窗口,如图所示。 输入源程序: int x,y,z; main() { x=1; y=2; while ( 1 ) { z=x+y; } }
main函数
main函数是一个比较特殊的函数。每个单片机、DSP C程序都必须 有一个名为main的函数,程序从这里开始执行。
main函数另一个独特的属性是,它有两种正式的原型且经常会使 用一些其它形式。两种标准型如下:
VA[i]= *pia/120; VB[i]= *pib/218; VC[i]= *pic/218;
在CCS中调试程序的一般步骤
打开文件夹内一个工程(系统自带的程序)。 点击编译工具栏的 rebuild all 按钮, 开始编译工程 下载编译结果到DSP开发板。 执行程序。
在CCS中调试程序的一般步骤
2)源文件.c 工程的主要文件,
软件开发时编写的代码 都是在源文件内。
3).lib文件
库文件
4).cmd 文件
用来分配存储空间的。
▪ 编写以C语言为基础
的简单DSP程序
▪数值运算
开设三个整 型量x,y,z
▪赋初值:
x=1,y=2
▪计算x+y
▪输出结果到z
▪循环
先新建源程序窗口,如图所示。 输入源程序: int x,y,z; main() { x=1; y=2; while ( 1 ) { z=x+y; } }
在CCS中调试程序的一般步骤
统计代码运行时间 点击菜单栏中的“Profile”“Clock””Enable”, 来
使能 Clock功能。接下来点击 “Profile”“Clock”“View”, 在 CCS 最下面会出现一 个类似于秒表的工具, 旁边显示数字“0”, 通过设置断点 观察始终数字的变化。
第7章 DSP的C语言编程
• DSP的C编译器还在不断优化; DSP的 编译器还在不断优化; • DSP的C编译器符合ANSI C标准; DSP的 编译器符合ANSI C标准 标准; • ANSI C标准会受处理器、运行环境或主机环境 C标准会受处理器、 标准会受处理器 的影响。 的影响。
14:42:22
6
CCS的C语言简介
• 由DSP厂商及第三方为DSP提供C编译器; DSP厂商及第三方为 厂商及第三方为DSP提供 编译器; 提供C • 使得采用高级语言开发DSP软件成为可能; 使得采用高级语言开发DSP软件成为可能 软件成为可能; • TI公司的CCS又提供了优化的C编译器; TI公司的 公司的CCS又提供了优化的 编译器; 又提供了优化的C
14:42:22
4
• Output Files
– Assembly source output
Generates assembly language source files that you can inspect easily, enabling you to see the code generated from the C/C++ source files.
14:42:22
11
• 访问数据空间 访问数据空间
– 通过指针来实现; 通过指针来实现; 指针来实现
*(unsigned int *) 0x1000=a; b=*(unsigned int *) 0x1001;
可以不事先进行定义; – 访问数据空间的地址可以不事先进行定义; 访问数据空间的地址可以不事先进行定义
※ const
dsp原理与开发编程
dsp原理与开发编程DSP(Digital Signal Processing)是数字信号处理的简称,它是利用数字技术对信号进行处理和分析的一种方法。
它主要应用于音频、图像、视频和通信等领域,能够对这些信号进行滤波、变换、编码、解码、压缩、增强、识别等操作。
DSP的基本原理是将模拟信号转换为数字信号,通过在数字域中进行计算和处理,再将数字信号转换为模拟信号。
这个过程主要包括信号采样、量化、编码、数字滤波、时域和频域分析等步骤。
在DSP的开发编程中,主要使用的编程语言是C/C++和MATLAB。
C/C++是一种通用的编程语言,适用于各种平台和嵌入式系统,它可以实现高效的算法和数据处理。
MATLAB 则是一种高级的数学软件,它提供了丰富的信号处理函数和工具箱,可以方便地进行信号处理和分析。
在DSP的开发编程中,常用的算法和技术包括滤波、快速傅里叶变换(FFT)、信号重构、自适应滤波、波束形成、多通道处理等。
开发人员可以根据具体的应用需求选择合适的算法和技术,并结合相应的编程语言进行实现和调试。
除了基本的信号处理算法和技术外,还可以使用硬件加速技术来提高DSP的性能。
常用的硬件加速技术包括使用FPGA (Field Programmable Gate Array)和ASIC(Application-Specific Integrated Circuit)等可编程逻辑器件,以及使用GPU (Graphics Processing Unit)等图形处理器。
总之,DSP原理与开发编程是一门涉及信号处理和算法实现的技术,可以应用于多个领域。
通过合理选择算法和技术,并结合相应的编程语言和硬件加速技术,可以实现高效、精确和可靠的数字信号处理。
轻松学会DSP——C程序编写和编译课件
根据个人习惯选择
开发者可以根据自己的习惯和喜好 选择适合自己的开发环境,比如习 惯使用CCS的开发者可以选择CCS 作为开发环境。
根据开发成本选择
开发者还需要考虑开发环境的成本 ,比如购买IDE的费用、学习成本等 。在选择开发环境时,需要根据实 际情况进行综合考虑。
05
DSP程序调试
BIG DATA EMPOWERS TO CREATE A NEW
FFT算法分类
FFT算法有多种实现方式,如基于 蝶形运算的Cooley-Tukey FFT算 法和基于分治思想的FFT算法等。 Cooley-Tukey算法是最常用的 FFT算法,其基本思想是将一个长 度为$N$的DFT分解为多个长度 为$N/2$的Hale Waihona Puke FT,递归计算直到 长度为2的DFT。
FFT算法实现过程
BIG DATA EMPOWERS TO CREATE A NEW ERA
轻松学会DSP——C程序编
写和编译课件
• DSP基础概念 • DSP编程语言 • DSP编译过程 • DSP开发环境 • DSP程序调试 • DSP应用实例
目录
CONTENTS
01
DSP基础概念
BIG DATA EMPOWERS TO CREATE A NEW
数字控制系统有多种类型,如开环控 制系统和闭环控制系统等。开环控制 系统结构简单,但控制精度和稳定性 较差;闭环控制系统具有反馈环节, 能够提高控制精度和稳定性。
数字控制系统的设计方法包括状态空 间法、根轨迹法和频域法等。状态空 间法能够得到系统的全部状态信息, 但计算量大;根轨迹法能够得到系统 的极点位置,但计算精度较低;频域 法能够得到系统的频率响应,但无法 得到系统的全部状态信息。
DSP中C语言编程总结
DSP中C语言编程在C和汇编混合编程的时候,存在C语言和汇编语言的变量以及函数的接口问题。
在C程序中定义的变量,编译为.asm文件后,都被放进了.bss区,而且变量名的前面都带了一个下划线。
在C程序中定义的函数,编译后在函数名前也带了一个下划线。
例如:extern int num就会变成 .bss _num, 1extern float nums[5]就会变成.bss _nums, 5extern void func ( )就会变成_func,一汇编和C的相互调用可以分以下几种情况:(1)汇编程序中访问c程序中的变量和函数。
在汇编程序中,用_XX就可以访问C中的变量XX了。
访问数组时,可以用_XX+偏移量来访问,如_XX+3访问了数组中的XX[3]。
在汇编程序调用C函数时,如果没有参数传递,直接用_funcname 就可以了。
如果有参数传递,则函数中最左边的一个参数由寄存器A给出,其他的参数按顺序由堆栈给出。
返回值是返回到A寄存器或者由A寄存器给出的地址。
同时注意,为了能够让汇编语言能访问到C语言中定义的变量和函数,他们必须声明为外部变量,即加extern 前缀。
(2)c程序中访问汇编程序中的变量如果需要在c程序中访问汇编程序中的变量,则汇编程序中的变量名必须以下划线为首字符,并用global使之成为全局变量。
如果需要在c程序中调用汇编程序中的过程,则过程名必须以下划线为首字符,并且,要根据c程序编译时使用的模式是stack-based model还是register argument model来正确地编写该过程,使之能正确地取得调用参数。
(3)在线汇编在C程序中直接插入asm(“\t*** ”),内嵌汇编语句,需要注意的是这种用法要慎用,在线汇编提供了能直接读写硬件的能力,如读写中断控制允许寄存器等,但编译器并不检查和分析在线汇编语言,插入在线汇编语言改变汇编环境或可能改变C变量的值可能导致严重的错误。
第四章 DSP的C语言程序设计
REG_READ(addr);//寄存器读
REG_WRITE(addr,val);//寄存器写
RESET_BIT(addr,bit); //bit位清零
GET_BIT(addr,bit); //取得bit位的值
SET-BIT(addr,bit); //bit位置1
#define DRR10_ADDR 0x21
#define DRR21_ADDR 0x40
#define DRR11_ADDR 0x41
分别将MCBSP0和MCBSP1的串口接收寄存器进行了定义。
统一定义法定义的寄存器用于对二者同时进行访问时比较方便,单独定义法定义的寄存器用于单独访问某个外设时比较方便。
在regs.h和reg54xx.h头文件中,定义了如下的宏函数,可以使用它们对寄存器或存储器进行访问。
REG_READ(addr);//寄存器读,addr为寄存器地址
# defineRSRFULL13//RSRFULL标志比特位于寄存器的bit13位置
#defineRSRFULL_SZ1 //此标志的长度为1个比特
我们只需要了解这些寄存器定义,在编程过程中直接使用而不需要自己来重新定义。
Reg54xx.h是对Regs.h的扩展和补充,并且Reg54xx.h头文件包含Regs.h。注意#define的语句中“\”是续行符。
函数类型 函数名(函数参数列表);
…
//中断服务程序(函数)的声明
interrupt void function_;
…
//主函数main()
void main(void)
{
//局部变量定义
DSP的C语言编程
DSP的C语言编程一、DSP的C语言简介:DSP生产厂商及第三方为DSP软件开发提供了C编译器,使得利用高级语言实现DSP程序的开发成为可能。
在TI公司的DSP软件开发平台CCS中,又提供了优化的C编译器,可以对C语言程序进行优化编译,提高程序效率,目前在某些应用中C语言优化编译的结果可以达到手工编写的汇编语言效率的90%以上。
DSP生产厂商和相关公司也在不断对C优化编译器进行改进设计,相信日后C语言程序优化编译的效果会有进一步的改善。
TMS320C2000系列提供有优化的C编译器,它支持ANSI(American National Standards Institute,美国国家标准委员会)开发的C语言标准,该C语言标准是使用最广泛的C语言标准,ANSI标准具有一些受目标处理器、运行期环境或主机环境影响的C语言特性,从有效性或实现上的考虑,这些特征在各种标准的C编译器之间可能有不同。
二、DSP的C语言特性2.1 TMS320C2000 C语言的特征(1)标识符和常数所有标识符的前100个字符有意义,区分大小写。
源(主机)和执行(目标)字符集为ASCII码,不存在多字节字符。
具有多个字符的字符常数按序列中最后一个字符来编码,例如:‘abc’= = ‘c’(2)数据转换浮点到整数的转换取整数部分。
指针和整数可以自由转换。
(3)表达式当两个有符号整数相除时,若其中一个为负,则其商为负,余数的符号与分子的符号相同。
斜杠(/)用来求商,百分号(%)用来求余数。
例如:10/-3 = -3,-10/3 = -3,10%-3 = 1,-10%3 = -1(4)声明寄存器变量对所有char,short,int和指针类型有效。
interrupt关键字仅可用于没有参量的void函数。
(5)预处理预处理器忽略任何不支持的#pragma伪指令。
预处理器支持的伪指令包括:·CODE_SECTOIN·DATA_SECTION·FUNC_EXT_CALLED2.2 TMS320C2000 C语言的数据类型注:在TMS320C2x/C2xx/C5xC语言中,字节长度为16位,sizeof操作符返回的对象长度是以16位为字节长度的字节数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
ANSIC 标准具有一些受目标处理器、运行期环境或主机环境影
响的C语言特性,这些特性在各种标准的C编译器之间可能有
不同。
3
15.2 DSP C语言特性 15.2.1 TMS320C2000 C语言的特征
(1)标识符和常数
所有标识符的前100个字符有意义,区分大小写。字符集为 ASCII码,不存在多字节字符。 具有多个字符的字符常数按序列中最后一个字符来编码,例如: ‘abc‟ = = „c‟
C程序开始运行时,必须首先初始化C运行环境,这是通过 c_int0函数完成的。
26
c_int0函数是复位中断的中断服务函数,此函数在运行支持库 (rts, runtime_support library)中提供。链接器会将这个
函数的入口地址放置在复位中断向量处,使其可以在初始化
时被调用。 c_int0函数进行以下工作来建立C运行环境: (1)为系统堆栈产生.stack段,并初始化堆栈指针。 (2)从.cinit段将初始化数据复制到.bss段中相应的变量。 (3)调用main函数,开始运行C程序。
near(近)
far(远)
volatile(可变的)
815.2.4Fra bibliotek寄存器变量
一个函数中最多可使用两个寄存器变量。
寄存器变量声明必须在变量列表或函数的起始处进行,在嵌套
块中声明的寄存器变量被处理为一般的变量。
编译器使用AR6和AR7作为寄存器变量:
AR6被赋给第一个寄存器变量 AR7被赋给第二个寄存器变量 寄存器变量的地址会被放入分配的寄存器中,这样变量的访问 速度会更快。
(2)数据转换
4
浮点到整数的转换,取整数部分。 指针和整数可以自由转换。
(3)表达式
当两个有符号整数相除时,若其中一个为负,则其商为负, 余数的符号与分子的符号相同。
斜杠(/)用来求商,例如: 10/-3 = -3, -10/3 = -3,
百分号(%)用来求余数,例如:
10%-3 = 1, -10%3 = -1
在进行函数调用的时候,可以做I/O端口变量的值传递,而
不是引用,例如:
call (port10); call (&port10); /*读端口10h,将其值传递给函数调用*/ /*引用传递无效!*/
18
15.2.8 访问数据空间 访问数据空间是利用指针来实现的:
*(unsigned int *)0x1000 = a; /* 将a的值写入数据空间
转指令和标记符可能会引起不可预料的操作结果。能够改变 段或其它影响C语言环境的指令也可能引起麻烦。
对包含asm语句的程序使用优化器时要特别小心。优化器可以重 新安排asm指令附近的代码顺序,这可能会引起不期望的结果。
15
15.2.7 访问I/O空间
读写I/O空间的功能是 C编译器对标准C的扩展,是利用关键字
C编译器可在编译器输出的汇编语言程序中直接输出汇编指令或
语句。利用asm语句嵌入汇编语言程序,可实现一些C语言
13
实现起来比较麻烦的硬件控制功能。 asm语句在语法上就象是调用一个函数名为asm的函数,函数参
数是一个字符串:
asm (“assembler text”);
编译器会直接将“参数字符串”复制到输出的汇编语言程序中,
16
所有I/O端口的定义必须在文件级完成,不支持在函数级声明
的I/O端口变量。 利用ioport关键字定义的I/O端口变量可以象一般变量一样进 行赋值操作: ioport unsinged port10; { ...... port10 = a; /*将a写到端口10h*/ ...... b = port10; /*从端口10h读入b*/
1. CODE_SECTION 该伪指令在名称为section name的命名段中为symbol分 配空间。语法为:
11
#pragma CODE_SECTION (symbol, “section name”);
2. DATA_SECTION
为名称为section name的命名段中为symbol分配空间。语
9
16位类型变量(char、short、int和指针)都可被定义为寄存 器变量。 但在运行时,设置一个寄存器变量大约需要4条指令,为了更 有效地使用这个功能,仅当变量被访问超过2次时,才使用 寄存器变量。 程序优化编译器也会定义寄存器变量,但方式不同。编译器会
自己决定哪些变量作为寄存器变量,程序中声明的寄存器变
5
(4)声明 寄存器变量对所有char,short,int和指针类型有效。
关键字interrupt仅可用于无参量的void函数。
(5)预处理
预处理器忽略任何不支持的#pragma伪指令。
预处理器支持的伪指令包括:
CODE_SECTOIN DATA_SECTION FUNC_EXT_CALLED
第15章
DSP的C语言编程
1
15.1 DSP C语言简介 软件开发平台为CCS。 CCS提供了优化的C编译器,优化编译结果达手工编写的90% 以上。
厂商和相关公司也在不断对C优化编译器进行改进.
相信C语言程序优化编译的效果会有进一步改善。
2
C编译器支持ANSI C语言标准。(ANSI--American National Standards Institute,美国国家标准委员会)
某些硬件控制功能不如汇编语言灵活,程序实时性不理想,很 多核心程序可能仍然需要利用汇编语言来实现。
利用两种语言进行混合编程主要有以下四种方式:
(1)C程序调用汇编函数;
(2)内嵌汇编语句;
(3)C程序访问汇编程序变量;
(4)修改C编译器输出。
29
15.3.1 程序运行环境 在C语言和汇编语言混合编程中,必须保证C程序运行环境不
27
用户程序可不用考虑上述问题,认为程序从main函数开始执行 就可以。
用户可对c_int0函数进行修改,但修改后的函数必须完成以上
任务。
15.3
DSP C语言与汇编语言混合编程
C语言编写DSP程序对底层的了解要求较低,流程控制灵活, 开发周期短。程序可读性、可移植性好,程序修改、升级方 便。
28
有被main函数调用的函数,这时就应该用FUNC_EXT_CALLED 来通知编译器保留此函数和被此函数调用到的函数,这些函 数将作为C程序的入口点。 这个伪指令必须出现在对要保留的函数的任何声明或引用之前, 其语法为: #pragma FUNC_EXT_CALLED (func);
15.2.6
asm语句
...... }
17
/*访问I/O空间10h的变量*/
端口变量的使用不仅限于赋值操作,用ioport关键字定义的 I/O端口变量可象其它变量一样用在表达式中,例如: a = port10 + b; /*读端口10h,加上b,结果赋给a*/ port10 += a;/*读端口10h,加上a,结果写回到端口10h*/
20
实时性不容易保证。
(2)回调法:当有中断发生时,会暂停当前正在执行的程序。 程序的实时性可得到保证,但如果中断处理函数使用不当易
造成中断丢失或中断嵌套问题。
21
采用回调法处理DSP中断需定义中断服务函数,有两种方法: (1)用关键字intterupt(中断)来实现。它的用法是:
interrupt void isr (void);
量会全部被忽略。 寄存器变量声明的格式为: register type reg;
10
15.2.5
伪指令pragma
伪指令pragma通知编译器的预处理器如何处理函数。
TMS320C2000 C编译器支持下列pragma:
CODE_SECTION DATA_SECTION FUNC_EXT_CALLED
会被汇编程序破坏,所有代码必须维护该环境,否则将难
以保证C程序的正常执行。 1. 存储器模型 C编译器将存储器作为程序存储器和数据存储器两个线性区来 处理: 程序存储器:包含可执行的代码和常量、变量初值。 数据存储器:包含外部变量、静态变量和系统堆栈。
法为: #pragma DATA_SECTION (symbol, “section name”); 3. FUNC_EXT_CALLED 当使用-pm选项时,编译器将使用程序级的优化。编译器将 删除所有未被main函数直接或间接调用的函数。
12
而用户程序里可能包含要被手工编写的汇编语言程序调用而没
ioport(I/O端口)来实现的。
ioport type porthexnum;
ioport指示这是定义一个端口变量的关键字。 type(类型)必须是char(字符)、short(短整型)、int (整型)或对应的无符号类型。 porthexnum为定义的端口变量,格式为“port”后面跟一个16 进制数。 例如“port000A”是定义访问I/O空间地址0Ah的变量。
因此必须保证参数双引号之间的字符串是一个有效的汇编语 言指令。 双引号之间的汇编指令必须以空格、制表符(TAB)、标记符 (LABEL)或注释开头,这和汇编语言编程的要求是一致的。
14
编译器不会检查此汇编语句是否合法,如果语句中有错误,在汇 编的过程中会被汇编器指出。
使用asm指令应小心不要破坏C语言的环境。如果C代码中插入跳
tmp = *(unsigned int *) (org + i);
*(unsigned int *) (org + offset +i) = tmp; }
15.2.9 中断服务函数
同单片机中断处理方式类似,DSP中断的处理也有两种方式:
(1)查询法:对中断的处理可完全按照程序预定的方式进行,