×

C语言开发DSP嵌入式系统解析

消耗积分:1 | 格式:rar | 大小:0.6 MB | 2017-11-03

分享资料个

大家在开发嵌入式产品时首先会想到用控制器的汇编语言编写监控程序,主要原因是:①汇编语言生成的程序对应的二进制代码少,程序执行要比高级语言生成的程序快;②控制器刚问世时,没有相应的高级语言可供使用;③存储器的价格问题和寻址空间的限制。
  以上所述问题目前已基本解决,在这就不阐述了。实际情况是:在单片机的应用领域,开发者已开始使用C语言进行开发。大家发现用高级语言开发嵌入式产品是如此轻松,并且C语言程序编译后的二进制代码也非常短小精练。
  目前使用最多的数字信号处理器(DSP)是美国TI公司的TMS320家族,而工业控制上用得最多的又是TMS320F2XX系列。TI公司为每一个DSP芯片提供了汇编语言和C语言供开发者选用。本人一直使用C语言进行产品开发,而目前很少见到这方面的介绍、所以特撰此文,以TMS320F240为例,向各位同行推荐用C语言开发DSP嵌入式系统。
  1 DSP的C语言的特殊性
  大家在使用51系列C语言时已经注意到,控制器的C语言和PC机上使用的C有一个显著的特点:经常要对硬件操作,程序中有大量针对控制器内部资源进行操作的语句。所以,开发者要明白怎样用C语言来操纵控制器的内部资源,即怎样用C语句操作寄存器和内部存储器等。
  举个例子:在51汇编中我们写 MOV A,#20H;汇编程序能够识别A是指累加器;而在51的C程序中我们写ACC=32;,编译器能够识别ACC是指累加器而不是一般的变量。即每一个寄存器都有一个专有名字供开发者使用,它们定义在一个头文件reg51.h中,程序员只需在程序的开始部分用#include“reg51.h”语句将该文件包含进来即可。注意:这些寄存器的名字不能用作变量名。
  同样,在TMS320F240的C语言中也有一个头文件C240.H定义各个寄存器的名称,这里摘录几条语句进行介绍。
  比如:#define IMR((PORT)0x0004)
  #define XINTI_CR((PORT) 0x07070)
  IMR、XINT1_CR就对应两个寄存器,实际是寄存器的地址,用高级语言的说法是指针。我们也在程序的开始部分用#include“c240.h”语句将该文件包含进来。这样,在DSP的C语言中使用它们只需在前面加一个星号(*),例如,
  *IMR=0X1010;/*将十六进制数1010H赋给IMR寄存器*/
  *XINT1_CR=0X0A0B0;/*将十六进制数A0B0H赋给XINT1_CR寄存器*/
  开发者最好将c240.h这个文件打印出来,弄清楚各个寄存器的定义名称。至于不涉及硬件的语法和ANSI语法一样。需要注意的是,有些ANSI标准中的函数在DSP的编译器中不提供,读者可以参考DSP编译器的C语言手册。搞清楚了这些特殊性,由汇编语言转到C语言开发是很容易的事。当然,没有汇编语言编程基础的人同样可以用C语言开发DSP应用系统。
  有关嵌入式系统的C语言编程可参考《单片机与嵌入式系统应用》2001年1~6期《嵌入式C编程技术》,本文不作讨论。下面只针对以TMS320F240芯片为处理器的嵌入式C语言编程进行阐述,希望能够指导读者进行具体操作。
  2 TMS320F240芯片的C语言开发过程
  简单地说,整个过程包括以下5个步骤:
  ①编辑C语言源程序;
  ②编译源程序(注意编译参数);
  ③链接目标文件(注意用CMD文件);
  ④在线仿真;
  ⑤固化程序。
  2.1源程序的编辑
  可以用任何一个编辑器书写源程序,如EDIT。NOTEPAD等,最后以.C为后缀存盘。源代码可以写在一个C文件中,也可写在多个C文件中;有些预定义变量和函数原型声明可以集中放在一个头文件中。
  注意事项:不要忘记在C程序的前面用 #in-clude “c240.h”将寄存器定义文件包括进来。
  2.2源程序的编译
  源程序编辑好后可以用DSPCL编译程序进行编译,生成OBJ文件。
  使用格式:DSPCL源文件名 参数
  例如: DSPCL EX1.C-V2XX-GK-MN
  常用参数的意义:
  V2XX——表示C编译器选择处理器2XX系列;
  GK——保留编译生成的汇编文件(.ASM文件);
  MN——进行正常优化。
  其它参数请参考DSP编译器的手册。如果有多个源文件分别编译,每一个源文件经编译后产生一个OBJ文件和ASM文件。
  2.3 目标文件的链接
  2.3.1 TI公司的COFF文件格式
  TI公司新的汇编器和编译器创建的目标文件采用COFF(Common Object File Format)的目标文件格式。采用COFF格式有利于模块化编程,为管理代码段和目标系统存储器提供更加有力和灵活的方法。基于COFF格式编写汇编程序或C语言程序时,不必为程序代码和变量指定目标地址;为程序编写和程序移植提供了极大的方便。
  COFF格式的基本思想是:鼓励程序员在用汇编语言或C语言编程时运用代码块和数据块的概念。这种块称为SECTION,是目标文件中的最小单位。
  所有的块分为两大类:已初始化块和未初始化块。已初始化块包含程序代码和数据,未初始化块是为未初始化的数据在存储器中的保留块。C编译器对C程序编译后产生已初始化块和未初始化块,已初始化块如.text块、.const块、.cinit块;未初始化块如.bss块。
  举个例子,当程序员用C语句float data[100];定义一个数组时,不需要指定这100个数组元素的具体位置,编译器会在数据区预留所需空间。到链接时链接器会具体定位。
  2.3.2 链接器对块的处理
  链接器对块的处理有两个功能:其一,将COFF目标文件中的块用来建立程序块和数据块,并将这些块组合成可以被DSP芯片执行的COFF输出模块;其二,链接器为输出块指定存储位置。
  链接器提供两个命令实现上述功能:MEMORY和SECTIONS。MEMORY命令定义目标系统的存储器,程序员可以定义每一块存储器并指定起始地址和长度;SECTIONS命令用来定义输入块的组合和输出块在存储器中的存放位置。若不用MEMORY和SECTIONS命令,链接器采用缺省的分配算法。推荐使用这两个命令,但要注意这两个命令在CMD文件(链接器命令文件)中使用。
  下面分析一个TMS320F240芯片的典型CMD文件。(假设文件名 EX1.CMD。)
  (1)CMD文件的构成及其详细解释
  BOOT.OBJ /*F240的中断矢量表,参见后面的说明*/
  EX1.OBJ /*源程序编译后对应的目标文件*/
  /*若程序有多个目标文件,一块写在这里*/
  -STACK 0X400 /*设定系统堆栈*/
  -C /*ROM初始化*/
  -O EX1.OUT /*输出的文件名*/
  -M EX1.MAP /*输出映像文件名*/
  -L RTS2XX.LIB /*涟接RTS2XX.LIB库*/
  MEMORY /*MEMORY命令规定系统的存储器配置*/
  {
  PAGEO:ROM0:origin=0000h,length=003fh
  /*FLASH ROM*/
  PAGE0:ROM1:origin=0040h,length=0200h
  /*FLASH ROM*/
  PAGEO:ROM2:origin=0240h,length=3000h
  /*FLASH ROM*/
  PAGE1:RAM_B2:origin=0060h,length=0020h
  /*内部RAMB2*/
  PAGE1:RAM_B1:origin=0300h,length=0100h
  /*内部RAM B1*/
  PAGE1:RAM_B0:origin=0100h,length=0100h
  /*内部RAM B0*/
  PAGE1:RAM_EX:origin=0d000h,length=2800h
  /*外部扩展RAM*/
  }
  SECTIONS /*SECTIONS命令规定了程序中块的具体分配方法*/
  {
  .vectors:load=ROM0 /*规定矢量表的存放位置*/
  .cinit:load=rom1 /*C初始化表的存放位置*/
  .text: load=ROM2 /*系统程序的存放位置*/
  .bSS load=RAM_B0 /*未初始化数据的存放位置*/
  .const load=RAM_B1 *已初始化数据的存放位置*/
  }
  (2)TMS320F240链接时所需的中断矢量表文件
  TMS320F240的目标文件在链接时要用到中断矢量表。中断矢量表用汇编语言编写,和具体的DSP芯片有关。假设TMS320F240的中断矢量表对应的汇编程序为BOOT.ASM,汇编后的文件名为BOOT.OBJ。
  下面是一个典型的矢量表文件。(假设程序名为BOOT.ASM。)
  .port /*定义中断函数的名字*/
  .globl_c_int0 /*中断0对应的函数名*/
  .globl_c_int1 /*中断1对应的函数名,以下语句的意义相同*/
  .globl_c_int2 /*可以将中断函数名看作中断入口地址*/
  .globl_c_int3 /*矢量表的存放不需程序员干预*/
  .globl_c_int4
  .globl_c_int5
  .globl_c_int6
  .globl_c_int7
  .globl_c_int8
  ·sect“.vectors”/*用.sect命令自定义一个块,用于存放中断矢量表*/
  RSVE CT B _c_int0 /*中断0发生后,程序的跳转目的地址*/
  INT1 B _c_int1 /*中断1发生后,则跳到c_int1()函数处*/
  INT2 B _c_int2 /*意义同上,下同*/
  INT3 B _c_int3
  INT4 B _c_int4
  INT5 B _c_int5
  INT6 B _c_int6
  用汇编器汇编该程序,命令形式:DSPABOOT.ASM-V2XX生成BOOT.OBJ文件供链接器使用。这样,就可以按如下形式在C源程序中编写中断函数:
  voidc_inx() /*x为1~8中之一*/
  {
  中断程序的C语句系列;
  }
  注意事项:c_int0()是系统入口函数,用户不能编写。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.lene-v.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'C语言开发DSP嵌入式系统解析',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.lene-v.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);