This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

【活动结束】别等了! 快来参与!!! 免费工具等你拿!

Other Parts Discussed in Thread: TMS320F2812, TMS320F28335, ADS805, CONTROLSUITE, SPRC087, CCSTUDIO, ULN2003A, TMS320F2808, LAUNCHXL-F28027, TMS320F28035, TPS3307, LM258, TMS320F28027, TMDSHVBLPFCKIT, TLV320AIC1106, ADS8482, TMS320LF2407A, LM393

为配合C2000 DAY的强势推出,2012 10 8  11 9 ,我们诚邀您来分享您在学习或工作中关于应用 TI C2000 产品的设计心得

我们相信业内同仁的分享和交流为彼此提供宝贵的经验借鉴,同时真诚希望 TI 官方社区成为大家共同学习和探讨技术的一个网上家园!

发贴要求(不符合下面要求将不具备获奖资格)

- 每篇有关C2000的主题不少于 300

- 内容要求必须清晰详细写出设计心得的具体过程(例如设计中使用哪款产品碰到的问题及其解决的方法和步骤。)

- 发表以跟贴形式,需为原创贴 (最好同时配上合适的图片或视频)

奖项设置
征文奖交由 TI 技术专家团队评选,TI拥有最终解释权!
优秀分享奖(封顶50名): LAUNCHXL-F28027  和 TMDX28069USB  各一个
阳光普照奖 (封顶100):LAUNCHXL-F28027 一个
每个ID只有一次获奖机会
每周做一次审核。先到先得!
  • 期待,谢谢TI给这么好的平台,搞这么好的活动!!!

  • 基于TMS320F28335的数字SPWM采样算法

    之前做过C2000方面的设计,共享下~

    基于TMS320F28335的数字SPWM采样算法.doc
  • 上传个LAUNCHXL-F28027的驱动,方便大家得到板子安装


    XDS100 Driver驱动.rar
  • 急盼结果,幸运了可以拿板子继续学习!

  • DSP-F2812C语言心得记录6-SCI通信发送模块中FIFO增强特性的使用方法

    SCI通信发送的过程中,有两种发送的方式供选择,一种是利用SCI模块的普通功能(即查询等待标志位的方式进行),另一种是利用F2812的增强特性FIFO功能进行数据的传送。比较这两种数据发送的方式发现,前一种查询等待的方式在发送一个字节的过程中会占用一个周期中的1ms时间(这是波特率为9600bps时候的情况),而后一种方式则基本不占用系统的周期等待时间,直接往Buf里面写数据就会自动的往外发送。

    以下是FIFO功能的增前特性描述:

     

    我在编程序的时候只用到增强特性中FIFO的发送功能,通过将SCIFFTX寄存器中的SCIFFEN位置1,使能FIFO模式。在任何操作状态下SCIRST都可以复位FIFO模式。

    本人对寄存器的设置是

    ScibRegs.SCIFFTX.all=0xE040; //1(1表示SCI FIFO可以恢复发送或接收)/1(使能SCI FIFO增强功能)/1(重新使能发送FIFO操作)/00000(发送FIFO是空的)/0(没有TXFIFO中断)/1(清除TXFFINT标志位)/0(中断被禁止)/00000(中断级别为0)

    ScibRegs.SCIFFCT.all=0x00; //禁止串口自动检测波特率

    for(temp=1;temp<TXindex1;temp++)

       {

        ScibRegs.SCITXBUF=DateReceiveBuf[temp];

        }

    //然后FIFO就会把所要发送的数据都会自动的发送出去

    ScibRegs.SCIFFTX.bit.SCIFFENA=0; //禁止FIFO功能,以确保利用回SCI的通信接收中断功能

    上述的FIFO功能设置并不占用其它定时器中断的时间,这样可以有效的提高周期的资源利用率。提高了通信的效率。

    对于第一种查询等待的方式,其中的设置是要等待一个字节完全的发送出去才能够进行其它模块的工作,这样的话是非常耗用时间和DSP的资源利用率的,而且其它模块的时间根本得不到保证,以下是我在调试时的一些相关设置:

    ScibRegs.SCITXBUF=DateReceiveBuf[temp];

    while(!((1<<6) & ScibRegs.SCICTL2.all)); //等待这个字节的数据完全的发送出去,该指令按照波特率为9600bps来算的话,发送一个字节的时间将耗时1ms,这样是很浪费资源的,其它模块的功能根本执行不了。

    根据上述的比较会发现,利用FIFO的功能进行通信是非常合理的,而且资源利用效率高。

  •   DSP之路

    DSP之前,一直用的是51,51DSP 可以说是一个相当大的跨度,整个架构的理念都不一样。

    公司要开发新的项目(电力系统的电网质量监测),这就涉及到AD的告诉采样,谐波分析,做FFT。这里面涉及到的各种复杂的运算,51根本就承受不了,51 做完一个FFT下来都要几秒钟了,这样子CPU 啥都干不成了。没办法,换CPU 是必须的了。直接就上了TMS32F2407,利用2407内部的高速AD 进行采样。

    下图是部分AD 转换电路,利用传感变压器将电网的高压隔离变成低压,使适合CPU进行采集:

    2407AD的部分接口如下图:

     

       一切都按计划进行着,但是没想到就出问题了,AD出来的数据不够稳定。一开始以为是因为采集速度太快了造成的,然后就放慢一点采样速度,结果还是不理想。对着2407的参数表,感觉没道理的 ,怎么会差这么远呢?然后就开始翻用户手册,查资料,上论坛找看有没有跟我一样情况的兄弟。搞了几天啊 ,就为了一个这问题,因为给51的思想固化了,一个CPU 就一个电源,没想到电源对AD采集影响这么大,2407AD要一个单独比较干净的电源。然后就是辛苦的割线啊,飞线弄多个电源进来,出来的结果超过了预期的目标。一个字,爽!

       小插曲,后来转2802的时候,也中了电源的招,我这次当然不会中单电源的招了,但是没有注意到,这家伙上电有次序的,1.8V先上电,3.3V后上电,搞得我焦头烂额了一个礼拜,后来在网上碰到一仁兄说2802的注意事项的时候,说到了上电次序的问题,才幡然大悟啊 。当然接下来又是苦逼的割线跟飞线了。

    一字记之曰:源。

    速度太快,也有出事的时候,使用2407 调试SPI接口的器件(ZLG7289)的时候就出事了。用的模拟SPI,直接就把51的模拟SPI程序移植过来用了。奇怪的现象就出现了,读、写数据都是错误的。我就开始单步调试跟踪啊,咦,单步来走,就能读能写了。一全速执行 就是不对(刚开始还怀疑到仿真器的头上了,第一次用没经验嘛,什么都怀疑)。后来用示波器分析波形才发现时序不对了,时钟跑快了。把读,写数据操作的延时加大就成功了。

    使用DSP ,其强大的定时器功能,EPWM51 先进多了,当然,其配置也稍微有点复杂,不过,对着手册来搞还是能胜任的。好了 就啰嗦这么多了,更多的发现,期待大家去挖掘。(晶振最好用有源的,这样稳定,性能也有很大的提升)

    下面上几张我DSP的处女作品

    手机照的,不是很清楚,呵呵。 继续上张全身相:

    这张可是改了3次板后的 最终图了。

    还有一张 比较乱 做的  也拿出来给大家瞄瞄吧

    希望大家学习愉快!!!!!

  • 周四了 貌似这个周的结果还没有公布呀。。。

  • 不好意思,让大家久等了,根据工程师的评估,获奖朋友的名单如下:

    优秀分享奖: jun zou,changtong wei,Surface,shenxue,xianfeng li,bo zhang

    阳光普照奖:licheng cao, kk zhao,Wanxiang Zhang,Dachuan Zhang, fan,dejian fu ,sai zhu,longfei feng,qimin ren ,xie yuanfu

  • 终于等过来了!非常感谢deyisupport和TI的各位朋友!

  • 唉 没得到优秀分享呀

  • 有板子用了哦  谢谢

  • 终于盼来了,感谢“deyisupport”

     支持TI,祝发展越来越好!

  • 谢谢,礼物很精美,支持TI尽自己最大力

  • 分享C2000的学习笔记,包括详细的开发步骤,希望能得个开发板,O(∩_∩)O谢谢

    F2812学习笔记.pdf
  • 异步电动机矢量控制系统

        由于DSP能对输入数据进行高速处理,克服了一般单片机处理能力有限的问题,而且电路设计较为简单,能获得较强的抗干扰能力,另外DSP具有专业化的指令集,提高了数字滤波器的运算速度,使得DSP在控制器的规则实施、矢量控制和矩阵变换等方面具有独特的优势。在电机控制系统中多用DSP作为核心控制器,以满足对实时性、稳定性及可靠性的要求。控制器选用TMS320F2812,具有丰富的电机控制外设电路,16个12位A/D转换通道,12个PWM输出通道,能控制两台三相电机,体积小、价格低、可靠性高,能在高度集成的环境中实现高性能电机控制。基本结构如下:

     

        用F2812设计的异步电动机矢量控制系统的基本结构如下所示。用可编程I/O口捕捉转子的速度反馈信号,电机的相电流反馈信号通过霍尔电流转换器采集到ADC通道进行转换。光电编码器将电机的转速编码,DSP据此计算电机的转速。通过霍尔电流传感器采集电机相电流的瞬时值,估计电机的实时运行状态,如转矩的大小和方向、电机的转速和滑差。按照某种调控规律产生PWM信号,控制逆变器的开关动作,对电机运行状态进行调控。

     

    主要硬件设计介绍如下:

    1.传感器

    本设计中设计的传感器包括霍尔位置传感器、霍尔电流传感器及速度传感器。

    霍尔位置传感器是一种检测物体位置的磁场传感器,以霍尔效应原理为其工作基础。霍尔线性型传感器输出模拟量,因此需要A/D转换通道进行采集。F2812通过芯片内部自带的ADC转换模块中的3个A/D转换通道捕捉霍尔位置传感器的3个相位置信号,接到ADCINA3、ADCINA4、ADCINA5引脚上,可以检测转子的转动位置。

    F2812同时需要3个A/D转换通道对霍尔电流传感器电流进行采集,以获得3个相电流信号。霍尔电流传感器采集电机相电流的瞬时值,估计电机的实时运行状态,如转矩的大小和方向、电机的转速和滑差。

    测量电机转速常用的方法有增量编码器和测速发电机。本设计采用光电编码器,F2812包含一个正交编码单元,电机的码盘信号通过CAP1和CAP2端口进行捕捉。捕捉到的数据存放在寄存器中,通过比较捕捉到的两相脉冲值可以确定当前电机转子的速度和方向,完成这些仅需两个数字量输入和一个内部寄存器。为防止电流过高对DSP造成损坏,信号经过一个光耦合器件连接到DSP引脚。

    2.A/D转换模块

    F2812内部集成了16路12位A/D转换模块,模拟量的输入范围是0-3.3V,通道分为两组,0-7为一组,8-15为一组,每组具有一个专门的输入端。事件转换器可将ADC配置成两个独立的8通道模块,也可串接成一个16通道模块。8通道模块将8路输入信号自动排序,并按序选择一路信号进行转换,完成后的结果保存在对应的结果寄存器中。串接模式下,成为16通道的A/D转换器模块允许对同一个通道信号进行多次转换,主要用于过采样的算法中。

    3.电机驱动器

    F2812有16路PWM输出口供电机使用,通过控制PWM波的占空比来改变加在电机两端的电压,从而改变电机的转速。由于DSP发出的PWM波功率不足以驱动大功率电机,需要经过IGBT进行功率转换。设计中采用功率芯片如PM100DSA120等,这类芯片利用TTL电平即可实现功率驱动,而且具有完整的隔离及保护功能,如过流、过压保护等。

     

    主要软件设计如下:

    1.初始化程序;

          CLRC CNF

          SETC OVM

          SPM 0

          SETC SXM

          LAR AR0,#DEC_MS

          LAR AR1,#(24-1)

          LACC #ANGLES_

          LARP AR0

    INIT_TBL

          TBLR *+,AR1

          ADD #1

          BANZ INIT_TBL,AR0

          LAR AR4,#79H

          LDP #0E0H

          SPLK #68H,WDCR

          SPLK #0284H,SCSR1

          LDP #0E1H

          SPLK #900H,ADCTRL1

          SPLK #0001H,MAXCONV

          SPLK #0010H,CHSELSEQ1

          LACC MCRA

          OR #0FD8H

          SACL MCRA

     

    2.电流采样和A/D转换子程序

          LDP #0E1H

          SPLK #2000H,ADCTRL2

          BIT ADCTRI2,3

          BCND CONVERSION,TC

          LACC RESULT0,10

          LDP #0

          SACH IA

          LDP #0E1H

          LACC RESULT1,10

          LDP #0

          SACH IB

     

  • 双降压全桥并网逆变器的控制方法

    1.双降压全桥并网逆变器的控制原理简介:

    双降压全桥并网逆变器的控制原理图解如下:

        双降压全桥并网逆变器的控制方法,属逆变器控制方法。采用电流传感器采样并网逆变器进网电流,采用电压传感器采样电网电压通过锁相环输出与电网电压同频同相的进网电流给定。进网电流环接收所述进网电流给定和进网电流反馈信号,输出电压给定1。 PWM产生电路接受所述电压给定1,输出逻辑控制信号PWM1PWM2。功率开关管驱动逻辑电路接收所述逻辑控制信号PWM1PWM2以及电网电压反馈信号,输出各个功率开关管的高低电平驱动信号。采实现了单极性倍频控制,减小了滤波器的体积和重量,不存在传统单极性调制进网电流过零点畸变问题;每半个工频周期只有2个功率开关管高频开关,提高了变换效率。

        1. 双降压全桥并网逆变器的控制方法,所述双降压全桥并网逆变器包括电网(Ugrid)、电源(Uin)、第一滤波电感(L1)、第一功率开关管(S1)、第一续流二极管(D1)、第二滤波电感(L2)、第二功率开关管(S2)、第二续流二极管(D2)、第三滤波电感(L3)、第三功率开关管(S3)、第三续流二极管(D3)、第四滤波电感(L4)、第四功率开关管(S4)和第四续流二极管(D4),其中电源(Uin)的正极分别与第一功率开关管(S1)的漏极、第二续流二极管(D2)的阴极、第三功率开关管(S3)的漏极和第四续流二极管(D4)的阴极连接,第一功率开关管((S1)的源极分别与第一续流二极管(D1)的阴极和第一滤波电感(L1)的输入端连接,第一滤波电感(L1)的输出端分别与电网(Ugrid)的正极和第二滤波电感(L2)的输出端连接,第二滤波电感(L2)的输入端分别与第二续流二极管(D2)的阳极和第二功率开关管(S2)的漏极连接,第二功率开关管(S2)的源极分别与电源(Uin)的负极、第四功率开关管(S4)的源极、第一续流二极管(D1)的阳极和第三续流二极管(D3)的阳极连接,第三续流二极管(D3)的阴极分别与第三滤波电感(L3)的输入端和第三功率开关管(S3)的源极连接,第四功率开关管(S4)的漏极分别与第四滤波电感(L4)的输入端和第四续流二极管(D4)的阳极连接,第三滤波电感(L3)的输出端分别与电网(Ugrid)的负极和第四滤波电感(L4)的输出端连接接地;

    其特征在于:采用电流传感器采样进网电流(ig)输出进网电流反馈信号(igf);采用电压采样电路采样电网电压(Ugrid)输出电网电压反馈信号(Ugridf);将所述电网电压反馈信号(Ugridf)通过锁相环(PLL)输出与电网电压(Ugrid)同频同相的进网电流给定(iref);将所述电网电压反馈信号(Ugridf)通过第一比较器输出工频开关逻辑信号;将所述工频开关逻辑信号通过第一非门输出工频开关逻辑的非信号;将所述进网电流给定(iref)与进网电流反馈信号(igf)相减后通过进网电流调节器输出电压给定1(Uref1);将所述电压给定1(Uref1)与三角载波信号(Uc)通过第二比较器输出逻辑控制信号PWM1;将所述电压给定1(Uref1)通过反相器输出电压给定2 (Uref2)后与三角载波信号(Uc)通过第三比较器输出逻辑控制信号PWM2;将所述逻辑控制信号PWM1与工频开关逻辑信号通过第一与门输出第一功率开关管(S1)的开关逻辑信号,所述第一功率开关管(S1)的开关逻辑信号通过第一驱动电路驱动第一功率开关管(S1);将所述逻辑控制信号PWM1通过第二非门后与工频开关逻辑的非信号通过第二与门输出第二功率开关管(S2)的开关逻辑信号,所述第二功率开关管(S2)的开关逻辑信号通过第二驱动电路驱动第二功率开关管(S2);将所述逻辑控制信号PWM2与工频开关逻辑的非信号通过第三与门输出第三功率开关管(S3)的开关逻辑信号,所述第三功率开关管(S3)的开关逻辑信号通过第三驱动电路驱动第三功率开关管(S3);将所述逻辑控制信号PWM2通过第三非门后与工频开关逻辑信号通过第四与门输出第四功率开关管(S4)的开关逻辑信号,所述第四功率开关管(S4)的开关逻辑信号通过第四驱动电路驱动第四功率开关管(S4)

    1) 关键算法介绍:

    1) 

    //增量式 PID 控制设计

    float IncPIDCalc(float NextPoint)

    {

      register float iError, iIncpid;

       //当前误差

      iError = sptr->SetPoint - NextPoint;

       //增量计算

      iIncpid = sptr->Proportion * iError               //E[k]项

                - sptr->Integral   * sptr->LastError     //E[k-1]项

                + sptr->Derivative * sptr->PrevError;   //E[k-2]项

       //存储误差,用于下次计算

      sptr->PrevError = sptr->LastError;

      sptr->LastError = iError;

       //返回增量值

     return(iIncpid);

    }

    2) 数字锁相算法:

    inline void SPLL_1ph_run(SPLL_1ph *spll_obj)

    {

    //-------------------//

    // Phase Detect   //

    //-------------------//

    spll_obj->Upd[0]=SPLL_Qmpy(spll_obj->AC_input,spll_obj->cos[1]);

    //-------------------//

    //Notch filter structure//

    //-------------------//

    spll_obj->ynotch[0]=-SPLL_Qmpy(spll_obj->notch_coeff.A1_notch,spll_obj->ynotch[1])-SPLL_Qmpy(spll_obj->notch_coeff.A2_notch,spll_obj->ynotch[2])+SPLL_Qmpy(spll_obj->notch_coeff.B0_notch,spll_obj->Upd[0])+SPLL_Qmpy(spll_obj->notch_coeff.B1_notch,spll_obj->Upd[1])+SPLL_Qmpy(spll_obj->notch_coeff.B2_notch,spll_obj->Upd[2]);

    // update the Upd array for future

    spll_obj->Upd[2]=spll_obj->Upd[1];

    spll_obj->Upd[1]=spll_obj->Upd[0];

    //---------------------------//

    // PI loop filter   //

    //---------------------------//

    spll_obj->ylf[0]=-SPLL_Qmpy(spll_obj->lpf_coeff.A1_lf,spll_obj->ylf[1])+SPLL_Qmpy(spll_obj->lpf_coeff.B0_lf,spll_obj->ynotch[0])+SPLL_Qmpy(spll_obj->lpf_coeff.B1_lf,spll_obj->ynotch[1]);

    //update array for future use

    spll_obj->ynotch[2]=spll_obj->ynotch[1];

    spll_obj->ynotch[1]=spll_obj->ynotch[0];

    spll_obj->ylf[1]=spll_obj->ylf[0];

    //------------------//

    // VCO              //

    //------------------//

    spll_obj->wo=spll_obj->wn+spll_obj->ylf[0];

    //integration process

    spll_obj->sin[0]=spll_obj->sin[1]+SPLL_Qmpy((SPLL_Qmpy(spll_obj->delta_t,spll_obj->wo)),spll_obj->cos[1]);

    spll_obj->cos[0]=spll_obj->cos[1]-SPLL_Qmpy((SPLL_Qmpy(spll_obj->delta_t,spll_obj->wo)),spll_obj->sin[1]);

    if(spll_obj->sin[0]>SPLL_Q(0.99))

    spll_obj->sin[0]=SPLL_Q(0.99);

    else if(spll_obj->sin[0]<SPLL_Q(-0.99))

    spll_obj->sin[0]=SPLL_Q(-0.99);

    if(spll_obj->cos[0]>SPLL_Q(0.99))

    spll_obj->cos[0]=SPLL_Q(0.99);

    else if(spll_obj->cos[0]<SPLL_Q(-0.99))

    spll_obj->cos[0]=SPLL_Q(-0.99);

    spll_obj->theta[0]=spll_obj->theta[1]+SPLL_Qmpy(spll_obj->wn,SPLL_Q(0.00001591549));

    if(spll_obj->sin[0]>SPLL_Q(0.0) && spll_obj->sin[1]<=SPLL_Q(0.0))

    {

    spll_obj->theta[0]=SPLL_Q(0.0);

    spll_obj->theta[1]=spll_obj->theta[0];

    spll_obj->sin[1]=spll_obj->sin[0];

    spll_obj->cos[1]=spll_obj->cos[0];

    }

    3) GRANDO PID算法:

     PID_GR_MACRO(v)

    /* proportional term */ 

    v.data.up = _IQmpy(v.param.Kr, v.term.Ref) - v.term.Fbk;

    /* integral term */ 

    v.data.ui = _IQmpy(v.param.Ki, _IQmpy(v.data.w1, (v.term.Ref - v.term.Fbk))) + v.data.i1;

    v.data.i1 = v.data.ui;

    /* derivative term */ 

    v.data.d2 = _IQmpy(v.param.Kd, _IQmpy(v.term.c1, (_IQmpy(v.term.Ref, v.param.Km) - v.term.Fbk))) - v.data.d2;

    v.data.ud = v.data.d2 + v.data.d1;

    v.data.d1 = _IQmpy(v.data.ud, v.term.c2);

    /* control output */ 

    v.data.v1 = _IQmpy(v.param.Kp, (v.data.up + v.data.ui + v.data.ud));

    v.term.Out= _IQsat(v.data.v1, v.param.Umax, v.param.Umin);

    v.data.w1 = (v.term.Out == v.data.v1) ? _IQ(1.0) : _IQ(0.0);

    2.附图:

    C2000分享.doc
  • F28035用于一种新型的双降压全桥并网逆变器

    1.F28035(PNT)的外设使用分配:

    1) ADC用来采样电网电压,并网电流,PV电压、PV电流、BUS母线电压、并测量板子的温度。

    2) PWM1A /PWM1B/PWM2A/ PWM2B驱动四个桥臂。PWM3A驱动单路BOOST

    3) CAP用来捕获过零点。

    4) 强大的C28XDSC内核用来进行大量的运算,如有值效,有功无功,FFT,数字锁相,正弦波采用线性插值进行高精度获得等。

    2.F28035及其外设电路:

    1) F28035

    2) 时钟与存储器

    3) 电压电流采样

    4) 通讯接口

    5) IO隔离

    6) IO口驱动加强与电平转换

    3.双降压全桥并网逆变器的控制原理简介:

    双降压全桥并网逆变器的控制原理图解如下:

        双降压全桥并网逆变器的控制方法,属逆变器控制方法。采用电流传感器采样并网逆变器进网电流,采用电压传感器采样电网电压通过锁相环输出与电网电压同频同相的进网电流给定。进网电流环接收所述进网电流给定和进网电流反馈信号,输出电压给定1。 PWM产生电路接受所述电压给定1,输出逻辑控制信号PWM1PWM2。功率开关管驱动逻辑电路接收所述逻辑控制信号PWM1PWM2以及电网电压反馈信号,输出各个功率开关管的高低电平驱动信号。采实现了单极性倍频控制,减小了滤波器的体积和重量,不存在传统单极性调制进网电流过零点畸变问题;每半个工频周期只有2个功率开关管高频开关,提高了变换效率。

        1. 双降压全桥并网逆变器的控制方法,所述双降压全桥并网逆变器包括电网(Ugrid)、电源(Uin)、第一滤波电感(L1)、第一功率开关管(S1)、第一续流二极管(D1)、第二滤波电感(L2)、第二功率开关管(S2)、第二续流二极管(D2)、第三滤波电感(L3)、第三功率开关管(S3)、第三续流二极管(D3)、第四滤波电感(L4)、第四功率开关管(S4)和第四续流二极管(D4),其中电源(Uin)的正极分别与第一功率开关管(S1)的漏极、第二续流二极管(D2)的阴极、第三功率开关管(S3)的漏极和第四续流二极管(D4)的阴极连接,第一功率开关管((S1)的源极分别与第一续流二极管(D1)的阴极和第一滤波电感(L1)的输入端连接,第一滤波电感(L1)的输出端分别与电网(Ugrid)的正极和第二滤波电感(L2)的输出端连接,第二滤波电感(L2)的输入端分别与第二续流二极管(D2)的阳极和第二功率开关管(S2)的漏极连接,第二功率开关管(S2)的源极分别与电源(Uin)的负极、第四功率开关管(S4)的源极、第一续流二极管(D1)的阳极和第三续流二极管(D3)的阳极连接,第三续流二极管(D3)的阴极分别与第三滤波电感(L3)的输入端和第三功率开关管(S3)的源极连接,第四功率开关管(S4)的漏极分别与第四滤波电感(L4)的输入端和第四续流二极管(D4)的阳极连接,第三滤波电感(L3)的输出端分别与电网(Ugrid)的负极和第四滤波电感(L4)的输出端连接接地;

    其特征在于:采用电流传感器采样进网电流(ig)输出进网电流反馈信号(igf);采用电压采样电路采样电网电压(Ugrid)输出电网电压反馈信号(Ugridf);将所述电网电压反馈信号(Ugridf)通过锁相环(PLL)输出与电网电压(Ugrid)同频同相的进网电流给定(iref);将所述电网电压反馈信号(Ugridf)通过第一比较器输出工频开关逻辑信号;将所述工频开关逻辑信号通过第一非门输出工频开关逻辑的非信号;将所述进网电流给定(iref)与进网电流反馈信号(igf)相减后通过进网电流调节器输出电压给定1(Uref1);将所述电压给定1(Uref1)与三角载波信号(Uc)通过第二比较器输出逻辑控制信号PWM1;将所述电压给定1(Uref1)通过反相器输出电压给定2 (Uref2)后与三角载波信号(Uc)通过第三比较器输出逻辑控制信号PWM2;将所述逻辑控制信号PWM1与工频开关逻辑信号通过第一与门输出第一功率开关管(S1)的开关逻辑信号,所述第一功率开关管(S1)的开关逻辑信号通过第一驱动电路驱动第一功率开关管(S1);将所述逻辑控制信号PWM1通过第二非门后与工频开关逻辑的非信号通过第二与门输出第二功率开关管(S2)的开关逻辑信号,所述第二功率开关管(S2)的开关逻辑信号通过第二驱动电路驱动第二功率开关管(S2);将所述逻辑控制信号PWM2与工频开关逻辑的非信号通过第三与门输出第三功率开关管(S3)的开关逻辑信号,所述第三功率开关管(S3)的开关逻辑信号通过第三驱动电路驱动第三功率开关管(S3);将所述逻辑控制信号PWM2通过第三非门后与工频开关逻辑信号通过第四与门输出第四功率开关管(S4)的开关逻辑信号,所述第四功率开关管(S4)的开关逻辑信号通过第四驱动电路驱动第四功率开关管(S4)

    4.F28035DSC处理器使用的一些关键算法介绍:

    1) 

    //增量式 PID 控制设计

    float IncPIDCalc(float NextPoint)

    {

      register float iError, iIncpid;

       //当前误差

      iError = sptr->SetPoint - NextPoint;

       //增量计算

      iIncpid = sptr->Proportion * iError               //E[k]项

                - sptr->Integral   * sptr->LastError     //E[k-1]项

                + sptr->Derivative * sptr->PrevError;   //E[k-2]项

       //存储误差,用于下次计算

      sptr->PrevError = sptr->LastError;

      sptr->LastError = iError;

       //返回增量值

     return(iIncpid);

    }

    2) 数字锁相算法:

    inline void SPLL_1ph_run(SPLL_1ph *spll_obj)

    {

    //-------------------//

    // Phase Detect   //

    //-------------------//

    spll_obj->Upd[0]=SPLL_Qmpy(spll_obj->AC_input,spll_obj->cos[1]);

    //-------------------//

    //Notch filter structure//

    //-------------------//

    spll_obj->ynotch[0]=-SPLL_Qmpy(spll_obj->notch_coeff.A1_notch,spll_obj->ynotch[1])-SPLL_Qmpy(spll_obj->notch_coeff.A2_notch,spll_obj->ynotch[2])+SPLL_Qmpy(spll_obj->notch_coeff.B0_notch,spll_obj->Upd[0])+SPLL_Qmpy(spll_obj->notch_coeff.B1_notch,spll_obj->Upd[1])+SPLL_Qmpy(spll_obj->notch_coeff.B2_notch,spll_obj->Upd[2]);

    // update the Upd array for future

    spll_obj->Upd[2]=spll_obj->Upd[1];

    spll_obj->Upd[1]=spll_obj->Upd[0];

    //---------------------------//

    // PI loop filter   //

    //---------------------------//

    spll_obj->ylf[0]=-SPLL_Qmpy(spll_obj->lpf_coeff.A1_lf,spll_obj->ylf[1])+SPLL_Qmpy(spll_obj->lpf_coeff.B0_lf,spll_obj->ynotch[0])+SPLL_Qmpy(spll_obj->lpf_coeff.B1_lf,spll_obj->ynotch[1]);

    //update array for future use

    spll_obj->ynotch[2]=spll_obj->ynotch[1];

    spll_obj->ynotch[1]=spll_obj->ynotch[0];

    spll_obj->ylf[1]=spll_obj->ylf[0];

    //------------------//

    // VCO              //

    //------------------//

    spll_obj->wo=spll_obj->wn+spll_obj->ylf[0];

    //integration process

    spll_obj->sin[0]=spll_obj->sin[1]+SPLL_Qmpy((SPLL_Qmpy(spll_obj->delta_t,spll_obj->wo)),spll_obj->cos[1]);

    spll_obj->cos[0]=spll_obj->cos[1]-SPLL_Qmpy((SPLL_Qmpy(spll_obj->delta_t,spll_obj->wo)),spll_obj->sin[1]);

    if(spll_obj->sin[0]>SPLL_Q(0.99))

    spll_obj->sin[0]=SPLL_Q(0.99);

    else if(spll_obj->sin[0]<SPLL_Q(-0.99))

    spll_obj->sin[0]=SPLL_Q(-0.99);

    if(spll_obj->cos[0]>SPLL_Q(0.99))

    spll_obj->cos[0]=SPLL_Q(0.99);

    else if(spll_obj->cos[0]<SPLL_Q(-0.99))

    spll_obj->cos[0]=SPLL_Q(-0.99);

    spll_obj->theta[0]=spll_obj->theta[1]+SPLL_Qmpy(spll_obj->wn,SPLL_Q(0.00001591549));

    if(spll_obj->sin[0]>SPLL_Q(0.0) && spll_obj->sin[1]<=SPLL_Q(0.0))

    {

    spll_obj->theta[0]=SPLL_Q(0.0);

    spll_obj->theta[1]=spll_obj->theta[0];

    spll_obj->sin[1]=spll_obj->sin[0];

    spll_obj->cos[1]=spll_obj->cos[0];

    }

    3) GRANDO PID算法:

     PID_GR_MACRO(v)

    /* proportional term */ 

    v.data.up = _IQmpy(v.param.Kr, v.term.Ref) - v.term.Fbk;

    /* integral term */ 

    v.data.ui = _IQmpy(v.param.Ki, _IQmpy(v.data.w1, (v.term.Ref - v.term.Fbk))) + v.data.i1;

    v.data.i1 = v.data.ui;

    /* derivative term */ 

    v.data.d2 = _IQmpy(v.param.Kd, _IQmpy(v.term.c1, (_IQmpy(v.term.Ref, v.param.Km) - v.term.Fbk))) - v.data.d2;

    v.data.ud = v.data.d2 + v.data.d1;

    v.data.d1 = _IQmpy(v.data.ud, v.term.c2);

    /* control output */ 

    v.data.v1 = _IQmpy(v.param.Kp, (v.data.up + v.data.ui + v.data.ud));

    v.term.Out= _IQsat(v.data.v1, v.param.Umax, v.param.Umin);

    v.data.w1 = (v.term.Out == v.data.v1) ? _IQ(1.0) : _IQ(0.0);

    5.附图:

    F28035来做一种新型逆变器分享.doc
  • F28035用于一种新型的双降压全桥并网逆变器

    1.F28035(PNT)的外设使用分配:

    1) ADC用来采样电网电压,并网电流,PV电压、PV电流、BUS母线电压、并测量板子的温度。

    2) PWM1A /PWM1B/PWM2A/ PWM2B驱动四个桥臂。PWM3A驱动单路BOOST

    3) CAP用来捕获过零点。

    4) 强大的C28XDSC内核用来进行大量的运算,如有值效,有功无功,FFT,数字锁相,正弦波采用线性插值进行高精度获得等。

    2.F28035及其外设电路:

    1) F28035

    2) 时钟与存储器

    3) 电压电流采样

    4) 通讯接口

    5) IO隔离

    6) IO口驱动加强与电平转换

    3.双降压全桥并网逆变器的控制原理简介:

    双降压全桥并网逆变器的控制原理图解如下:

        双降压全桥并网逆变器的控制方法,属逆变器控制方法。采用电流传感器采样并网逆变器进网电流,采用电压传感器采样电网电压通过锁相环输出与电网电压同频同相的进网电流给定。进网电流环接收所述进网电流给定和进网电流反馈信号,输出电压给定1。 PWM产生电路接受所述电压给定1,输出逻辑控制信号PWM1PWM2。功率开关管驱动逻辑电路接收所述逻辑控制信号PWM1PWM2以及电网电压反馈信号,输出各个功率开关管的高低电平驱动信号。采实现了单极性倍频控制,减小了滤波器的体积和重量,不存在传统单极性调制进网电流过零点畸变问题;每半个工频周期只有2个功率开关管高频开关,提高了变换效率。

        1. 双降压全桥并网逆变器的控制方法,所述双降压全桥并网逆变器包括电网(Ugrid)、电源(Uin)、第一滤波电感(L1)、第一功率开关管(S1)、第一续流二极管(D1)、第二滤波电感(L2)、第二功率开关管(S2)、第二续流二极管(D2)、第三滤波电感(L3)、第三功率开关管(S3)、第三续流二极管(D3)、第四滤波电感(L4)、第四功率开关管(S4)和第四续流二极管(D4),其中电源(Uin)的正极分别与第一功率开关管(S1)的漏极、第二续流二极管(D2)的阴极、第三功率开关管(S3)的漏极和第四续流二极管(D4)的阴极连接,第一功率开关管((S1)的源极分别与第一续流二极管(D1)的阴极和第一滤波电感(L1)的输入端连接,第一滤波电感(L1)的输出端分别与电网(Ugrid)的正极和第二滤波电感(L2)的输出端连接,第二滤波电感(L2)的输入端分别与第二续流二极管(D2)的阳极和第二功率开关管(S2)的漏极连接,第二功率开关管(S2)的源极分别与电源(Uin)的负极、第四功率开关管(S4)的源极、第一续流二极管(D1)的阳极和第三续流二极管(D3)的阳极连接,第三续流二极管(D3)的阴极分别与第三滤波电感(L3)的输入端和第三功率开关管(S3)的源极连接,第四功率开关管(S4)的漏极分别与第四滤波电感(L4)的输入端和第四续流二极管(D4)的阳极连接,第三滤波电感(L3)的输出端分别与电网(Ugrid)的负极和第四滤波电感(L4)的输出端连接接地;

    其特征在于:采用电流传感器采样进网电流(ig)输出进网电流反馈信号(igf);采用电压采样电路采样电网电压(Ugrid)输出电网电压反馈信号(Ugridf);将所述电网电压反馈信号(Ugridf)通过锁相环(PLL)输出与电网电压(Ugrid)同频同相的进网电流给定(iref);将所述电网电压反馈信号(Ugridf)通过第一比较器输出工频开关逻辑信号;将所述工频开关逻辑信号通过第一非门输出工频开关逻辑的非信号;将所述进网电流给定(iref)与进网电流反馈信号(igf)相减后通过进网电流调节器输出电压给定1(Uref1);将所述电压给定1(Uref1)与三角载波信号(Uc)通过第二比较器输出逻辑控制信号PWM1;将所述电压给定1(Uref1)通过反相器输出电压给定2 (Uref2)后与三角载波信号(Uc)通过第三比较器输出逻辑控制信号PWM2;将所述逻辑控制信号PWM1与工频开关逻辑信号通过第一与门输出第一功率开关管(S1)的开关逻辑信号,所述第一功率开关管(S1)的开关逻辑信号通过第一驱动电路驱动第一功率开关管(S1);将所述逻辑控制信号PWM1通过第二非门后与工频开关逻辑的非信号通过第二与门输出第二功率开关管(S2)的开关逻辑信号,所述第二功率开关管(S2)的开关逻辑信号通过第二驱动电路驱动第二功率开关管(S2);将所述逻辑控制信号PWM2与工频开关逻辑的非信号通过第三与门输出第三功率开关管(S3)的开关逻辑信号,所述第三功率开关管(S3)的开关逻辑信号通过第三驱动电路驱动第三功率开关管(S3);将所述逻辑控制信号PWM2通过第三非门后与工频开关逻辑信号通过第四与门输出第四功率开关管(S4)的开关逻辑信号,所述第四功率开关管(S4)的开关逻辑信号通过第四驱动电路驱动第四功率开关管(S4)

    4.F28035DSC处理器使用的一些关键算法介绍:

    1) 

    //增量式 PID 控制设计

    float IncPIDCalc(float NextPoint)

    {

      register float iError, iIncpid;

       //当前误差

      iError = sptr->SetPoint - NextPoint;

       //增量计算

      iIncpid = sptr->Proportion * iError               //E[k]项

                - sptr->Integral   * sptr->LastError     //E[k-1]项

                + sptr->Derivative * sptr->PrevError;   //E[k-2]项

       //存储误差,用于下次计算

      sptr->PrevError = sptr->LastError;

      sptr->LastError = iError;

       //返回增量值

     return(iIncpid);

    }

    2) 数字锁相算法:

    inline void SPLL_1ph_run(SPLL_1ph *spll_obj)

    {

    //-------------------//

    // Phase Detect   //

    //-------------------//

    spll_obj->Upd[0]=SPLL_Qmpy(spll_obj->AC_input,spll_obj->cos[1]);

    //-------------------//

    //Notch filter structure//

    //-------------------//

    spll_obj->ynotch[0]=-SPLL_Qmpy(spll_obj->notch_coeff.A1_notch,spll_obj->ynotch[1])-SPLL_Qmpy(spll_obj->notch_coeff.A2_notch,spll_obj->ynotch[2])+SPLL_Qmpy(spll_obj->notch_coeff.B0_notch,spll_obj->Upd[0])+SPLL_Qmpy(spll_obj->notch_coeff.B1_notch,spll_obj->Upd[1])+SPLL_Qmpy(spll_obj->notch_coeff.B2_notch,spll_obj->Upd[2]);

    // update the Upd array for future

    spll_obj->Upd[2]=spll_obj->Upd[1];

    spll_obj->Upd[1]=spll_obj->Upd[0];

    //---------------------------//

    // PI loop filter   //

    //---------------------------//

    spll_obj->ylf[0]=-SPLL_Qmpy(spll_obj->lpf_coeff.A1_lf,spll_obj->ylf[1])+SPLL_Qmpy(spll_obj->lpf_coeff.B0_lf,spll_obj->ynotch[0])+SPLL_Qmpy(spll_obj->lpf_coeff.B1_lf,spll_obj->ynotch[1]);

    //update array for future use

    spll_obj->ynotch[2]=spll_obj->ynotch[1];

    spll_obj->ynotch[1]=spll_obj->ynotch[0];

    spll_obj->ylf[1]=spll_obj->ylf[0];

    //------------------//

    // VCO              //

    //------------------//

    spll_obj->wo=spll_obj->wn+spll_obj->ylf[0];

    //integration process

    spll_obj->sin[0]=spll_obj->sin[1]+SPLL_Qmpy((SPLL_Qmpy(spll_obj->delta_t,spll_obj->wo)),spll_obj->cos[1]);

    spll_obj->cos[0]=spll_obj->cos[1]-SPLL_Qmpy((SPLL_Qmpy(spll_obj->delta_t,spll_obj->wo)),spll_obj->sin[1]);

    if(spll_obj->sin[0]>SPLL_Q(0.99))

    spll_obj->sin[0]=SPLL_Q(0.99);

    else if(spll_obj->sin[0]<SPLL_Q(-0.99))

    spll_obj->sin[0]=SPLL_Q(-0.99);

    if(spll_obj->cos[0]>SPLL_Q(0.99))

    spll_obj->cos[0]=SPLL_Q(0.99);

    else if(spll_obj->cos[0]<SPLL_Q(-0.99))

    spll_obj->cos[0]=SPLL_Q(-0.99);

    spll_obj->theta[0]=spll_obj->theta[1]+SPLL_Qmpy(spll_obj->wn,SPLL_Q(0.00001591549));

    if(spll_obj->sin[0]>SPLL_Q(0.0) && spll_obj->sin[1]<=SPLL_Q(0.0))

    {

    spll_obj->theta[0]=SPLL_Q(0.0);

    spll_obj->theta[1]=spll_obj->theta[0];

    spll_obj->sin[1]=spll_obj->sin[0];

    spll_obj->cos[1]=spll_obj->cos[0];

    }

    3) GRANDO PID算法:

     PID_GR_MACRO(v)

    /* proportional term */ 

    v.data.up = _IQmpy(v.param.Kr, v.term.Ref) - v.term.Fbk;

    /* integral term */ 

    v.data.ui = _IQmpy(v.param.Ki, _IQmpy(v.data.w1, (v.term.Ref - v.term.Fbk))) + v.data.i1;

    v.data.i1 = v.data.ui;

    /* derivative term */ 

    v.data.d2 = _IQmpy(v.param.Kd, _IQmpy(v.term.c1, (_IQmpy(v.term.Ref, v.param.Km) - v.term.Fbk))) - v.data.d2;

    v.data.ud = v.data.d2 + v.data.d1;

    v.data.d1 = _IQmpy(v.data.ud, v.term.c2);

    /* control output */ 

    v.data.v1 = _IQmpy(v.param.Kp, (v.data.up + v.data.ui + v.data.ud));

    v.term.Out= _IQsat(v.data.v1, v.param.Umax, v.param.Umin);

    v.data.w1 = (v.term.Out == v.data.v1) ? _IQ(1.0) : _IQ(0.0);

    5.附图:

    F28035来做一种新型逆变器分享.doc
  •  使用TMS320LF2407做的太阳能逆变,分享下。

    SPWM 算法原理[3]

      PWM 技术利用全控型器件的导通和关断把电压变成一定形状的电压脉冲序列,实现变压、变频控制并且消除谐波,而SPWM 算法是以获得正弦电压输出为目标的一种脉宽调制技术。 为了得到正弦波,需要输出一组连续的幅值相等而宽度不相等的矩形波,实现过程为:正弦调制波与三角载波相交,交点产生控制功率开关器件的信号,经相应驱动电路来控制功率开关器件的通断,从而得到一系列等幅而且脉冲宽度正比于对应区间正弦波曲线函数值的矩形脉冲,即SPWM 波形。

      用软件方式实现SPWM 的算法包括:自然采样法,规则采样法(对称规则采样法,不对称规则采样法)。自然采样法在计算SPWM 波的脉宽时要解超越方程,不适合用于实时控制。在实际控制应用中,为减少谐波分量,多采用不对称规则采样法(如图1 所示)。实践证明,不对称规则采样法所形成的阶梯波比对称规则采样法更接近于正弦波,特别是当载波比N=3或3 的倍数时,前者的输出电压中不存在偶次谐波分量,其它高次谐振波分量的幅值也较小,并且当逐渐增大调制率,使脉宽调制向输出方波过渡时,采用不对称规则采样,不会像自然采样那样产生基波幅值跳跃的现象。所谓不对称规则采样法,是指既在三角波的顶点位置又在底点位置对正弦波进行采样,此阶梯波与三角波的交点所确定的脉宽,在一个三角波的周期内的位置是不对称的,如图1 所示。在这里,采样周期Ts 是三角波周期Tt 的1/2,即Ts=Tt/2。

                           

      k1 为偶数时是顶点采样,k2 为奇数时是底点采样。而非对称规则采样法在一个载波周期里采样两次正弦波数值,该采样值更真实地反映了实际的正弦波数值。这是单相SPWM 波形生成的数学模型,三相正弦电压彼此相位差2π / 3 ,要用三条相位相差2π / 3的正弦调制波与同一三角形载波来生成三相SPWM 波形,可以推得以下公式:

      对于触发时间的求解公式,根据输入调制频率可计算载波比N。为了增强系统的运行速度,当选定载波比N 后,正弦函数sin(kπ / N)在三角载波各顶点和底点时刻的采样值可先计算制成表格,放入ROM 中,供程序在线运算时调用。可以根据负载压频U/f 曲线实时计算调制比M值。由于三相交流输入相位相差2π / 3,从正弦函数表中查询某一时刻k 值的函数值sin(kπ / N) ,赋给U 相后,查表指针向前移动2π / 3 ,查得sink(1π /N+2π /3),得到V相,指针再向前移动2π / 3 ,查得sin(k1π / N + 4π / 3) ,得到W 相。

      3.DSP 实现不对称规则采样算法的原理

      在本文中我们通过TI 公司32 bit 控制器TMS320LF2407来实现SPWM 算法。TMS320LF2407的波形发生器属于DSP 芯片的外部事件管理模块,占用CPU 的时间很少,可以方便地生成6路带编程死区和输出极性的PWM 波[2]。通过对比较单元的寄存器进行适当的设置可以方便地生成所需的SPWM 波。

      TMS320LF2407 有两个事件管理器模块(EVA 或EVB),每个EV 都内含2 个通用定时器,三个全比较单元,死区单元及输出逻辑,事实上一个事件管理器模块就可以生成三相六路SPWM 脉冲波形。为了产生PWM 输出,通过设定通用定时器T1(我们使用EVA 中的T1)的周期寄存器T1PR,并选择通用定时器T1 处于连续增/减计数模式,以产生SPWM 算法中的对称三角波载波信号。定时器计数器T1CNT 从0 递增到T1PR,然后再从T1PR 递减到0,循环计数,同时比较寄存器(CMPRx ,x=1、2、3)的值不断地与定时器计数器的值进行比较,当两个值发生匹配后,比较单元的输出信号送入PWM 电路中的对称/非对称波行形发生器,由它产生一路PWM 脉冲信号,再经过死区单元以及输出逻辑后,产生一对具有可编程死区的可以驱动同一桥臂IGBT 的互补信号PWMy,y+1。当两个功率器件串连放在主电路中组成一个桥臂时,上下两个器件绝对不能同时导通,否则会发生短路。因此导通上一桥臂的PWM 须互不重叠,这就要求一个器件导通前,另一个器件要完全关闭,所以需要一个延迟的死区时间。如图2 示,比较单元1、2、3 的对称/非对称波形发生器提供的输入信号PHn(n=1,2,3)作为死区单元的输入,对于每一个输入信号PHn ,死区单元产生两路输出: PHx 和PHx_。如果死区单元未被使能,那这两路输出的信号是完全相同的;当死区单元使能时,两路输出信号的跳变沿被一段死区时间间隔开。

     

      4.DSP 软件设计

      整个程序分为主程序和中断子程序两大部分。主程序任务是:初始化启动系统后,扫描键盘输入,更新调制波频率fm,根据调制波频率fm计算载波比N 和定时器T1 周期寄存器的值,由负载压频U/f 曲线计算调制比M,并将N 值,M 值等信息显示液晶显示屏上;除主程序外一共开放了三个中断,分别是:

      ①定时器T1 中断子程序:完成三个比较寄存器(CMPRx ,x=1、2、3)的计算、赋值,用于更新PWM1~PWM6 的占空比。②定时器T2 周期中断,用于扫描按键,更新调制波频率fm。

      ③PDPA 中断,用于保护功率模块,一旦PDPA 脚为低便封锁PWM1~PWM6。主程序流程图与中断子程序流程是程序的主要组成部分,详细见图(3)、图(4)。

     

      5.实验波形及结论

      通过键盘设定调制波频率,我们设定为25Hz,用数字示波器测量PWM1/CMP1 引脚,所得实验波形如图5 所示。从图中可知,PWM 波形的占空比是按正弦规律实时变化的,所得正弦调制波频率也期望值一致,系统同时实现了死区功能。实践证明,以TMS320LF2407为核心基于不对称规则采样算法的SPWM 波的设计是成功的。该系统具有很好的控制精度和较强的实时响应,实时控制能力。

     

    软件设计

    利用TMS320LF240x实现SVPWM算法的程序

       
    下面给出了利用TMS320LF2407实现SVPWM算法的一个应用程序。在该程序中,我们假设有200个电压矢量Uout 平均分布在电角度为2π的范围内,通过改变SVPWM的调制周期T可以改变输出的3相正弦波的频率。

    源程序代码:

    (1)       所需的复位和中断矢量定义文件“vectors.asm”请读者参考本书相关章节。

    (2)       主程序

    // 该程序用于简单的SVPWM演示,产生3相互差120度电角度的正弦交流电压,此程序实

    // 时计算cmp1和cmp2的值

    #include              "register.h" 

    #include              "float.h"

    #include              "math.h"

    float                     ualfa[200],ubeta[200]; // 存储电压矢量Uout的(α,β)轴分量ualfa、ubeta的数组

    int                        sector[200];                 // 定义存储扇区数的数组

    #define              PI2             2*3.1415926   // 定义2π的值  

    #define              DETA        PI2/200       // 定义相临两个Uout之间的电角度的差值

    #define              INIA          3.1415926/180  // 定义Uout的初始电角度 

    #define              TP       1200          // t1的周期寄存器的值,其值等于SVPWM调制周期T的一半,

                                                           // 因为在该程序中2π电角度内Uout的点数一定,故改变此值

                                              // 可以改变输出的3相正弦交流电压的频率

    #define              KP      0.7           // 定义Uout的标幺值,KP的值在0和1之间,改变此值可以

                                                          // 改变逆变桥输出电压的幅值

    //  屏蔽中断子程序        

    void inline disable()

    {

             asm(" setc INTM");

    }

    // 系统初始化子程序

    viod  initial()

    {

             *IFR=0xFFFF;                                          //  清除所有的中断标志        

             *IMR=0X0;                                    // 屏蔽所有中断

             *SCSR1=0x81FE;                                        // CLKIN=6M,CLKOUT=24M

        *WDCR=0xE8;                                         // 不使能看门狗

             *T3PER=TP;                                         // 通用定时器1的周期=PWM的周期/指令周期/2

             *T3CON=0X0802;                               // 设置通用定时器1为连续增减模式,以产生对称的PWM,

                                                                    // 且为了便于调试,使仿真一挂起时时钟就停止运行

             *ACTRB=0X666;                                 // PWM7、9、11高有效,PWM8、10、12低有效

             *COMCONB=0X9200;                       // 使能PWM输出和比较动作

         *EVBIMRA=0X00;                             // 禁止EVB和时钟及比较有关的中断

             *T3CNT=0X00;                                    // T1的计数器清0 

             *EVBIFRA=0x0FFFF;                        // 清除EVB相应的中断标志 

             *MCRC=*MCRC|0X7E;                      // PWM7-PWM12输出使能,使能IOPE1-IOPE6第二功能        

            WSGR=0x0000;                                   // 不使能所有的等待状态

    }

    // 根据Uout的标幺值KP计算ualfa,ubeta子程序

    void  calu()

    {

             int     i;

             for(i=0;i<200;i++)

             {

                       ualfa[i]=KP*cos(INIA+i*DETA);

                       ubeta[i]=KP*sin(INIA+i*DETA);

             }

    }

    // 各点的扇区确定子程序

    void  SECTOR()

    {

             int     i,a,b,c;

             float  vref1,vref2,vref3;

             for(i=0;i<200;i++)

             {

                       vref1=ubeta[i];

                       vref2=(-ubeta[i]+ualfa[i]*1.732051)/2;

                       vref3=(-ubeta[i]-ualfa[i]*1.732051)/2;  // 计算确定扇区数需要的3个参考量

    // vref1、vref2、vref3

                       if(vref1>0)          a=1;

                       else   a=0;        

                       if(vref2>0)          b=1;

                       else   b=0;

                       if(vref3>0)          c=1;

                       else   c=0;

                       a=4*c+2*b+a;

                       switch(a){

    case 1:sector[i]=1;break;                          

                                case 2:sector[i]=5;break;

                                case 3:sector[i]=0;break;

                                case 4:sector[i]=3;break;

                                case 5:sector[i]=2;break;

                                case 6:sector[i]=4;break;

                                default:break;

                       }                                                      // 根据相应的关系确定各个Uout所在的扇区

             }

    }

    // 主程序

    main()

    {

    int     anticlk[6]={0x1666,0x3666,0x2666,0x6666,0x4666,0x5666};

    // 逆时针旋转的6个基本矢量

    int     i,k=0,cmp1,cmp2;

    float           x,y,z;  

             disable();                                                         // 屏蔽所有中断

             initial();                                                           // 系统初始化

             calu();                                                              // 计算ualfa,ubeta的值

             SECTOR();                                                     // 确定各点的扇区,在实际应用时应该由即时

    // 的ualfa和ubeta即时算出

    while(1)     {

                       for(i=0;i<200;i++)  {

                                *ACTRB=anticlk[sector[i]];                  // 重新装配ACTRA

                                x=ubeta[i];

                                y=(1.732051*ualfa[i]+ubeta[i])/2;

                                z=(-1.732051*ualfa[i]+ubeta[i])/2;        // 以上3句计算3个相应的参考量

                                switch(sector[i])  {

                                         case 0 :cmp1=(int)(-z*TP),cmp2=(int)(x*TP);break;

                                         case 1 :cmp1=(int)(y*TP),cmp2=(int)(z*TP);break;

                                         case 2 :cmp1=(int)(x*TP),cmp2=(int)(-y*TP);break;

                                         case 3 :cmp1=(int)(z*TP),cmp2=(int)(-x*TP);break;

                                         case 4 :cmp1=(int)(-y*TP),cmp2=(int)(-z*TP);break;

                                         case 5 :cmp1=(int)(-x*TP),cmp2=(int)(y*TP);break;

                                         default : break;

                                }       // 以上根据uout所处的扇区计算相应的cmp1和cmp2的值

                                *CMPR4=cmp1;                          // 比较寄存器4赋值

                                *CMPR5=cmp1+cmp2;               // 比较寄存器5赋值

                                if((i+k)==0)                  *T3CON=*T3CON|0X040;        // 启动定时器,只启动一次

    while(1)     {

                                         k=*EVBIFRA&0X0200;

                                         if(k==0x0200)    break;      // 如果T3的中断标志建立,则停止等待

                                }      

    }

    }

    }

    // 如果由于干扰引起中断,则执行此直接返回程序

    void interrupt nothing()

    {

             return;

    }

     

     

    太阳能逆变.rar
  • 谈谈我对硬件和软件设计的感受

    硬件设计是系统设计的关键,国内和国外产品的差距往往是硬件设计水平高低决定的,任何软件设计思想没有可靠的物理载体都是空中楼阁,纸上谈兵。学校的研究生很多都想避开硬件设计,对于一个全新的设计与其说不屑不如说不敢。试想一下烧几个片子的压力要比跑飞几段程序的压力大的多,尤其是功率器件,一旦烧掉,弄不好火光冲天,人的自信都没了。况且改一次板周期长,经费高,还不知行不行。其实在国外实力一般的公司也是尽量避免硬件的更新设计,产品一旦定型往往通过软件升级,这是公司的发展策略,对个人而言物以希为贵,培养一个硬件设计师往往要比软件设计师时间长花费多。在设计dsp硬件时,开始设计最小系统板,系统按功能分板设计调试,注意分板电路的稳定性可能不如整板电路,要多加入抗干扰环节,分板间的引线包括电源线地线要短,尽量在10公分以内,实在不行加入光耦隔离、采用隔离电源。切记电源线、地线的干扰远比信号干扰对系统的危害大得多,又常常被人忽视。电路板工作正常的先决条件就是电源正常!当分板电路正常后再更居情况设计整板电路。在调试时发现的问题一定要找到原因解决,即使是飞线,割线,不要寄希望于下一板改了再看,除非原理性错误。每一个功能环节多准备几套方案。DSP的选型要根据系统功能而定,2000是一个功能比较全的控制器,但运算性能相对低,但目前大部分控制类、家电类包括中低层次的工业总线通信产品足够了,281X不错但太贵,而且开发技术不成熟。54XX更像一个协处理器,其实高端产品5471就很好,功能完*,但BGA封装对产品的开发有一定难度。如果没有从事过嵌入式系统开发的朋友其实可以从51看起,许多思想是共通的,51很经典没有哪一款微处理器像51那样使用持久和普遍。在硬件设计时更多的精力放在外围电路设计上,外围电路设计的灵活性要比DSP本身高得多,难度大得多。建议多考虑CPLD。

    软件设计上,着眼点不要仅局限于某种算法和控制策略,而是软件系统框架的制定,即操作系统的选择和实现,算法和控制策略只是其中技巧性很强的子程序和子程序间参数相互关系,建议设计软件时能具有操作系统、数据结构和编译原理方面的知识,特别是使用C。对DSP的内部硬件结构一定要掌握,特别是中断结构和流程、流水线操作,不然飞都不知道怎么飞的。在语言选择上我当时是这么给自己规定的先编20个左右的汇编程序,每个代码量超过4K,使用语句范围覆盖全部语句的60%-70%,在此基础上使用C。现在发现用C构建程序的主体框架(操作系统)比较快而其不容易出错,(我现在正在用ASM根据UCOSII的思想重写自己的操作系统)但对系统实时性影响比较大的运算算法一般采用MATLAB——C——ASM的办法仿真调试优化,这里的优化不单单是利用优化器优化,而是根据数据的特点改变运算方法,以除法为例C里的/号其实掩盖了许多技巧,当除数为常数时就可以放大倒数移位相乘移位的办法进行,精度高速度快。这些办法只有掌握了ASM语言并用ASM语言思考才会熟练应用。另外我想告诉一些作算法特别是控制算法的朋友,千万不要随意评判一个算法的优劣,在程序中程序和代码优化的程度往往影响了控制效果好坏,而不是算法本身的思想。其实在实际中往往PID甚至PI、PD就够了,神经元、模糊、小波适用于研究和写论文,模糊在实际中用的多一点,主要是小日本用的比较成熟,我再恨日本人,这点也服气,小日本就是滑,许多物理现象搞不透,就用这法,还管用,题外话。

    最后我想说的是,当我们面对市场要求时,产品往往考虑的是可靠性、性能、价格而不是你用的什么芯片,在满足性能的基础上结构越简单就越可靠,芯片越通用价格就越低,能用51就不用196,能用2407就不用2812,除非把芯片本身作买点利用高成本赢取高利润。无论2000还是5000、6000系列都有市场前景,关键是要做深做透

    获取知识的方法、处理项目的能力是相通的,具体的说就是不要把目光盯在做硬件还是做软件上,用ASM还是C,要勤动手打好基础,提高自己对系统总体设计的能力,从系统的眼光看问题。为什么都是做DSP的有的毕业拿3000,有的5000、8000,除了运气和关系外,重要的是你对事物的认识深度和高度。我一直都记住这句话:有前途的人做什么都有前途,没前途的人做什么都没前途。


    二. 与其说是钻在里面,毕业设计是搞240,在老师的压力做出了一点东西,这期间主要是对DSP的各种基础知识的熟悉与理解,对DSP的真正深入是在公司工作以后。当初进公司,因为正有一个项目需要用5410要我接手。说实话,在学校期间我5000的书都没有看过一眼,可没办法,只能靠自己了。不过好的是我2000DSP的基础很好。接过项目后,我第一个星期就全部看的是5000的指令,DSP的结构倒没怎么看,因为项目硬件已成型,主要是算法。这样,花了一个星期熟悉指令与项目相关的程序,第二个星期也就开始编程了。半个月以后我对5410也就用很熟了的,当然主要还是讲在算法方面。这个项目太概做了四个月吧,系统程序是我编写的,主要有如64位加减乘除乘方开方、及时域方面的一些算法。现在又做一个控制系统,用2407开发的,硬件主要有直交变频,并把2407的所有外设资源全部用到了。现在我可以这样自夸一句吧:TI的2000系列与5000系列的我都熟悉,要我去以此做个系统,没问题。上面是把我搞DSP的经历简单说了一下的吧,在这里我想对正在学及想学DSP的难兄们说一句的是,DSP并不是很难。当然,这个前提是你的基础要好,我单片机,接口都还行,当初就是从单片机改成DSP的。有了单片机的基础再去学2000第列的DSP(下面的DSP单指2000系列,另有说明为止),你就可以把DSP看成一个super microcontroller了。相比之下,DSP除了比单片机多了更丰的外设接口(SPI,SCI、CAN、PWM、CAP、QEP等等),他就是一块单片机,只不过在单片机来说你要另加芯片的工作,DSP全部把它做在一块芯片去了,我现在看DSP也真就这么简单。前面有人提到DSP主要是做算法,这句话有一定的片面性: TI有很多系列的DSP,现在主流的DSP主要为2000系列、3000系列、4000系列、5000系列、6000系列。除了2000与5000系列是定点DSP外,其余的均为浮点系列。 TI的2000系列主要长处是在用于控制系统,因为它的资源非常丰富,前面提到,在控制系统中用到的一些外设2000系列均在片内集成了。 TI的5000系列主要长处是用于数字信号的算法处理,这里所讲算法处理主要是指在数字信号处理时的一些算法,如FIR、IIR、FFT等等。5000系列的DSP的速度比2000快,2407最快只能到40M,2800系列除外,5410的DSP可以达到160M,如现在我们主要用来做数字信号方面的处理以及简单的静态图像处理等这样一些在资源需要处于中等的一些算法。 TI的6000系列主要是用在实时图像处理,这个就更则重于算法处理。一般的硬件很少自制,我们是用TI的DSK板再加上自主板相结合。


    三. 使用C/C++语言编写基于DSP程序的注意事项 1、 不影响执行速度的情况下,可以使用c或c/c++语言提供的函数库,也可以自己设计函数,这样更易于使用“裁缝师”优化处理,例如:进行绝对值运算,可以调用fabs()或abs()函数,也可以使用if...else...判断语句来替代。 2、 要非常谨慎地使用局部变量,根据自己项目开发的需要,应尽可能多地使用全局变量和静态变量。 3、 一定要非常重视中断向量表的问题,很多朋友对中断向量表的调用方式不清楚。其实中断向量表中的中断名是任意取定的,dsp是不认名字的,它只认地址!!中断向量表要重新定位。这一点很重要。 4、 要明确dsp软件开发的第一步是对可用存储空间的分析,存储空间分配好坏关系到一个dsp程序员的水平。对于dsp,我们有两种名称的存储空间,一种是物理空间,另一种是映射空间。物理空间是dsp上可以存放数据和程序的实际空间(包括外部存储器),我们的数据和程序最终放到物理空间上,但我们并不能直接访问它们。我们要访问物理空间,必须借助于映射空间才行!!但是映射空间本身是个“虚”空间,是个不存在的空间。所以,往往是映射空间远远大于实际的物理空间,有些映射空间,如io映射空间,它本身还代表了一种接口。只有那些物理空间映射到的映射空间才是我们真正可访问(读或写)的存储空间。 5、 尽可能地减少除法运算,而尽可能多地使用乘法和加法运算代替。 6、 如果ti公司或第三方软件合作商提供了dsplib或其他的合法子程序库供调用,应尽可能地调用使用。这些子程序均使用用汇编写成,更为重要之处是通过了tms320算法标准测试。而且,常用的数字信号处理算法均有包括!! 7、 尽可能地采用内联函数!!而不用一般的函数!!可以提高代码的集成度。 8、 编程风格力求简炼!!尽可能用c语言而不用c++语言。我个人感到虽然c++终代码长了一些,好象对执行速度没有影响。 9、 因为在c5000中double型和float型均占有2个字,所以都可以使用,而且,可以直接将int型赋给float型或double型,但,尽可能地多使用int数据类型代替!这一点需要注意!! 10、 程序最后至少要加上一个空行,编译器当这个空行为结尾提示符。 11、 大胆使用位运算符,非常好用!! 12、 2003年6月份从ti的网站上下到了关于tms320c67x系列dsp的快速算法库,于是,tms320c5000和c6000全系列的快速算法库都问世了,这些算法库均可供c/c++语言直接调用,优化程度100%,实际编程时尽可能地使用(下载时可以同时下载到说明文档和ascii源程序,可以根据自己需要作出修改,修改前最好做个备份)。

  • 定点DSP如何做浮点运算

    许多DSP芯片只支持整数运算,如果现在这些芯片上进行小数运算的话,定点小数运算应该是最佳选择了,此外即使芯片支持浮点数,定点小数运算也是最佳的速度选择。

      在DSP世界中,由于DSP芯片的限制,经常使用定点小数运算。所谓定点小数,实际上就是用整数来进行小数运算。下面先介绍定点小数的一些理论知识,然后以C语言为例,介绍一下定点小数运算的方法。在TIC5000DSP系列中使用16比特为最小的储存单位,所以我们就用16比特的整数来进行定点小数运算。

      先从整数开始,16比特的储存单位最多可以表示0x0000到0xffff,65536种状态,如果它表示C语言中的无符号整数的话,就是从0到65535。如果需要表示负数的话,那么最高位就是符号位,而剩下的15位可以表示32768种状态。这里可以看出,对于计算机或者DSP芯片来说,符号并没有什么特殊的储存方式,其实是和数字一起储存的。为了使得无论是无符号数还是符号数,都可以使用同样的加法减法规则,符号数中的负数用正数的补码表示。

      我们都知道-1+1=0,而0x0001表示1,那么-1用什么来表示才能使得-1+1=0呢?答案很简单:0xffff。现在就可以打开Windows的计算器,用16进制计算一下0xffff+0x0001,结果是0x10000。那么0x10000和0x0000等价麽,我们刚才说过用16比特来表达整数,最高位的1是第17位,这一位是溢出位,在运算寄存器中没有储存这一位,所以结果是低16位,也就是0x0000。现在我们知道负数的表达方式了。举个例子:-100。首先我们需要知道100的16进制,用计算器转换一下,可以知道是0x0064,那么-100就是0x10000-0x0064,用计算器算一下得0xff9c。

      还有一种简单的转换符号的方法,就是取反加一:把数x写成二进制格式,每位0变1,1变0,最后把结果加1就是-x了。

      好,复习了整数的相关知识之后,我们进入定点小数运算环节。所谓定点小数,就是小数点的位置是固定的。我们是要用整数来表示定点小数,由于小数点的位置是固定的,所以就没有必要储存它(如果储存了小数点的位置,那就是浮点数了)。既然没有储存小数点的位置,那么计算机当然就不知道小数点的位置,所以这个小数点的位置是我们写程序的人自己需要牢记的。

      先以10进制为例。如果我们能够计算12+34=46的话,当然也就能够计算1.2+3.4或者0.12+0.34了。所以定点小数的加减法和整数的相同,并且和小数点的位置无关。乘法就不同了。12*34=408,而1.2*3.4=4.08。这里1.2的小数点在第1位之前,而4.08的小数点在第2位之前,小数点发生了移动。所以在做乘法的时候,需要对小数点的位置进行调整?!可是既然我们是做定点小数运算,那就说小数点的位置不能动!!怎么解决这个矛盾呢,那就是舍弃最低位。也就说1.2*3.4=4.1,这样我们就得到正确的定点运算的结果了。所以在做定点小数运算的时候不仅需要牢记小数点的位置,还需要记住表达定点小数的有效位数。上面这个例子中,有效位数为2,小数点之后有一位。

      现在进入二进制。我们的定点小数用16位二进制表达,最高位是符号位,那么有效位就是15位。小数点之后可以有0-15位。我们把小数点之后有n位叫做Qn,例如小数点之后有12位叫做Q12格式的定点小数,而Q0就是我们所说的整数。

      Q12的正数的最大值是0111.111111111111,第一个0是符号位,后面的数都是1,那么这个数是十进制的多少呢,很好运算,就是0x7fff/2^12=7.999755859375。对于Qn格式的定点小数的表达的数值就它的整数值除以2^n。在计算机中还是以整数来运算,我们把它想象成实际所表达的值的时候,进行这个运算。

      反过来把一个实际所要表达的值x转换Qn型的定点小数的时候,就是x*2^n了。例如0.2的Q12型定点小数为:0.2*2^12=819.2,由于这个数要用整数储存,所以是819即0x0333。因为舍弃了小数部分,所以0x0333不是精确的0.2,实际上它是819/2^12=0.199951171875。

    我们用数学表达式做一下总结:

      x表示实际的数(*一个浮点数),q表示它的Qn型定点小数(一个整数)。

      q=(int)(x*2^n)

      x=(float)q/2^n

      由以上公式我们可以很快得出定点小数的+-*/算法:

      假设q1,q2,q3表达的值分别为x1,x2,x3

      q3=q1+q2若x3=x1+x2

      q3=q1-q2若x3=x1-x2

      q3=q1*q2/2^n若x3=x1*x2

      q3=q1*2^n/q2若x3=x1/x2

      我们看到加减法和一般的整数运算相同,而乘除法的时候,为了使得结果的小数点位不移动,对数值进行了移动。

      用c语言来写定点小数的乘法就是:

      shortq1,q2,q3;

      ....

      q3=((longq1)*(longq2))>>n;

      由于/2^n和*2^n可以简单的用移位来计算,所以定点小数的运算比浮点小数要快得多。下面我们用一个例子来验证一下上面的公式:

      用Q12来计算2.1*2.2,先把2.12.2转换为Q12定点小数:

      2.1*2^12=8601.6=8602

      2.2*2^12=9011.2=9011

      (8602*9011)>>12=18923

      18923的实际值是18923/2^12=4.619873046875和实际的结果4.62相差0.000126953125,对于一般的计算已经足够精确了。

  • TMS320F2812 DSP 是运动控制系统很好的硬件支撑平台,但传统的DSP 代码开发周期较长,效率不高。

    Matlab 公司的Embedded Target for TI C2000 DSP 可解决上述问题,用户通过使用该模块,不仅可以进

    行电路的系统级仿真,还可编译生成相应的C 语言代码,进行算法的探索与设计思路的验证。

     

     

     DSP 代码自动生成流程

    首先,根据系统的设计思路在Matlab/ Simulink 平台

    下搭建系统模型( .mdl) ,仿真满意后通过Matlab 提供的

    Real Time Workshop ( RTW) 生成面向TI 编译器的工程

    文件代码( .prj) ,并进一步完成代码的编译,链接生成DSP

    可执行机器码( .out) ,最后下载到目标DSP 板上运行,完

    成系统的开发[ 2 ] 。

    上述开发过程全部在Matlab/ Simulink 环境下进行,

    开发人员不需要写任何代码,只需利用Matlab 的模型模

    块完成系统设计即可;而且开发人员在系统设计过程可对

    系统进行仿真验证,保证系统设计的正确性。图1 为DSP

    代码自动生成的开发流程。

     

     

    2  三相异步电机转速控制系统的设计

    本设计采用开环恒压频比(VVVF) 与空间矢量脉宽

    调制(SVPWM) 相结合的算法,驱动控制三相异步电动

    机。控制系统主要模块及其功能如下:

    ① RAMP_CNTL 缓升缓降模块。该模块类似低通

    滤波器,实现给定信号的缓慢变化,避免信号的突变给电

    机造成冲击。

    ②V/ F 模块。基频以下,通过对定子电压幅值与频

    率的协调控制,保持定子磁通恒定,实现恒转矩控制,在低

    频段,系统要补偿定子压降;基频以上,保持额定电压,实

    现恒功率控制。

    ③ IPARK模块。该模块实现PARK逆变换,实现两

    相旋转坐标到两相静止坐标的转换。

    ④ SVGEN 模块。该模块计算出应用SVPWM 产生

    给定定子参考电压所需的3 个比较值Ta 、Tb 、Tc ,再经

    DSP 的比较单元,产生控制功率器件的开关信号。

    ⑤ PWM 模块。配置该模块,控制DSP PWM 的工作

    模式,包括载波频率、有效电平、工作时钟频率等。

    图2 为控制系统的原理框图。

     

  • //###########################################################################
    //
    // FILE: DSP281x_ECan.c
    //
    // TITLE: DSP281x Enhanced CAN Initialization & Support Functions.
    //
    //###########################################################################
    //
    //  Ver | dd mmm yyyy | Who  | Description of changes
    // =====|=============|======|===============================================
    //  1.00| 11 Sep 2003 | H.J. | Changes since previous version (v.58 Alpha)
    //      |             |      | Added several initialization routines
    //###########################################################################

    #include "DSP281x_Device.h"     // DSP28 Headerfile Include File
    #include "DSP281x_Examples.h"   // DSP28 Examples Include File


    //---------------------------------------------------------------------------
    // InitECan:
    //---------------------------------------------------------------------------
    // This function initializes the eCAN module to a known state.
    //
    void InitECan(void)
    {

    long i;

    asm("  EALLOW");

    /* Disable Watchdog  */
       DisableDog();   
       
    /* Enable peripheral clocks  */  
       InitPeripheralClocks();   
       
    /* Set PLL multiplication factor */
       InitPll(0xA);
      
       asm("  EALLOW"); 
           
    /* Configure eCAN pins using GPIO regs*/

     GpioMuxRegs.GPFMUX.bit.CANTXA_GPIOF6 = 1;
     GpioMuxRegs.GPFMUX.bit.CANRXA_GPIOF7 = 1; 
     
    /* Configure eCAN RX and TX pins for eCAN transmissions using eCAN regs*/ 
       
        ECanaRegs.CANTIOC.bit.TXFUNC = 1;
        ECanaRegs.CANRIOC.bit.RXFUNC = 1;  

    /* Configure eCAN for HECC mode - (reqd to access mailboxes 16 thru 31) */
             // HECC mode also enables time-stamping feature
     ECanaRegs.CANMC.bit.SCB = 1;    

    /* Initialize all bits of 'Master Control Field' to zero */
    // Some bits of MSGCTRL register come up in an unknown state. For proper operation,
    // all bits (including reserved bits) of MSGCTRL must be initialized to zero
     
        ECanaMboxes.MBOX0.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX1.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX2.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX3.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX4.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX5.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX6.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX7.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX8.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX9.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX10.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX11.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX12.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX13.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX14.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX15.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX16.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX17.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX18.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX19.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX20.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX21.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX22.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX23.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX24.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX25.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX26.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX27.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX28.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX29.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX30.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX31.MSGCTRL.all = 0x00000000;

    // TAn, RMPn, GIFn bits are all zero upon reset and are cleared again
    // as a matter of precaution.

    /* Clear all TAn bits */     
     
     ECanaRegs.CANTA.all = 0xFFFFFFFF;

    /* Clear all RMPn bits */     
     
     ECanaRegs.CANRMP.all = 0xFFFFFFFF;
     
    /* Clear all interrupt flag bits */     
     
     ECanaRegs.CANGIF0.all = 0xFFFFFFFF;
     ECanaRegs.CANGIF1.all = 0xFFFFFFFF;
     
    /* Configure bit timing parameters */

     ECanaRegs.CANMC.bit.CCR = 1 ;            // Set CCR = 1
       
        while(ECanaRegs.CANES.bit.CCE != 1 ) {}   // Wait for CCE bit to be set..
       
        ECanaRegs.CANBTC.bit.BRPREG = 9;
        ECanaRegs.CANBTC.bit.TSEG2REG = 2;
        ECanaRegs.CANBTC.bit.TSEG1REG = 10; 
       
        ECanaRegs.CANMC.bit.CCR = 0 ;             // Set CCR = 0
        while(ECanaRegs.CANES.bit.CCE == !0 ) {}   // Wait for CCE bit to be cleared..
     
    /* Disable all Mailboxes  */
     
      ECanaRegs.CANME.all = 0;  // Required before writing the MSGIDs


     
    /***************************************************/
    /* Bit configuration parameters for 150 MHz SYSCLKOUT*/
    /***************************************************/
    /*

    The table below shows how BRP field must be changed to achieve different bit
    rates with a BT of 15, for a 80% SP:
    ---------------------------------------------------
    BT = 15, TSEG1 = 10, TSEG2 = 2, Sampling Point = 80%
    ---------------------------------------------------
    1   Mbps : BRP+1 = 10  : CAN clock = 15 MHz
    500 kbps : BRP+1 = 20  : CAN clock = 7.5 MHz
    250 kbps : BRP+1 = 40  : CAN clock = 3.75 MHz
    125 kbps : BRP+1 = 80  : CAN clock = 1.875 MHz
    100 kbps : BRP+1 = 100  : CAN clock = 1.5 MHz
    50  kbps : BRP+1 = 200  : CAN clock = 0.75 MHz

    The table below shows how to achieve different sampling points with a BT of 25:
    -------------------------------------------------------------
    Achieving desired SP by changing TSEG1 & TSEG2 with BT = 25 
    -------------------------------------------------------------

    TSEG1 = 18, TSEG2 = 4, SP = 80%
    TSEG1 = 17, TSEG2 = 5, SP = 76%
    TSEG1 = 16, TSEG2 = 6, SP = 72%
    TSEG1 = 15, TSEG2 = 7, SP = 68%
    TSEG1 = 14, TSEG2 = 8, SP = 64%

    The table below shows how BRP field must be changed to achieve different bit
    rates with a BT of 25, for the sampling points shown above:

    1   Mbps : BRP+1 = 6
    500 kbps : BRP+1 = 12
    250 kbps : BRP+1 = 24
    125 kbps : BRP+1 = 48
    100 kbps : BRP+1 = 60
    50  kbps : BRP+1 = 120

    */


     

    基于Matlab的TMS320LF2407程序快速设计.pdf
  • 活动很好,顶一个,没用过这个,希望能获得一块。下面说下我在学习过程中遇到的一个问题,及解决办法

    我用28027的ADC采样后,经过一个很简单的算法让PWM1根据采样值的大小输出A,B两路PWM脉冲。可是当我对A,B两路PWM的占空比都加限定在0.05至0.9之间时,就进不了PWM的中断(我在中断里读ADC采样值),ADC也不采样了,而只限制一路PWM的占空比就可以正常工作。程序在下面!

    void get_adc(void)

    {

      AdcRegs.ADCSOCFRC1.bit.SOC0=1;  //Force SOC0 to Convert

      AdcRegs.ADCSOCFRC1.bit.SOC1=1;  //Force SOC1 to Convert

      DELAY_US(1);

    Vph=AdcResult.ADCRESULT0;

    Iph=AdcResult.ADCRESULT1;

    }

    void update_compare()

    {

    float Duty1A=Vph/4095;

    float Duty1B=Iph/4095;

    Uint16 CMPA_PWM1=(1-Duty1A)*EPWM1_TIMER_TBPRD;

    Uint16 CMPB_PWM1=(1-Duty1B)*EPWM1_TIMER_TBPRD;

    //Limit pwm1A and PWM1B duty between 0.05 and 0.9

    /*  不加这一路的PWM占空比的限定时可以正常工作,加上就不行了

    if( Duty1A>=0.9)

        Duty1A=0.9;

    else if( Duty1A<0.05)

             Duty1A=0.05;

       else

        Duty1A=Duty1A;

    */    

    if(Duty1B>=0.9)

      Duty1B=0.9;

    else if(Duty1B<0.05)

       Duty1B=0.05;

        else

          Duty1B=Duty1B;

    EPwm1Regs.CMPA.half.CMPA= CMPA_PWM1;   //update CMPA

    EPwm1Regs.CMPB= CMPB_PWM1;           //update CMPB

    }

    //PWM中断程序

    interrupt void epwm1_isr(void)

    {

       EPwmTimerIntCount++;

       get_adc();

       // Update the CMPA and CMPB values

       update_compare();

       // Clear INT flag for this timer

       EPwm1Regs.ETCLR.bit.INT = 1;

       // Acknowledge this interrupt to receive more interrupts from group 3

       PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;

    }

     

    在咨询了很多朋友,和自己努力后终于调出来了,好像是数据格式的问题。我把里面设置的float型的变量全都改成整型的,然后进行放大10倍(类似于Q格式定标)就没问题了。还有也了解到28027不支持硬件上浮点型的运算

  • 首先感谢TIDeyisupport的各位管理辛苦组织这次活动!

    看到这个活动后,真的很激动,因为这一段时间一直在DSP的门边徘徊,一方面是原来触的比较少,别一方面是资源不是很充足!

    前一段时间就一直关注TMDX28069USB这个工具,可谓是艳慕已久了!希望这次能有幸得到TI的资助,一睹其强大的开发功能!

    下面我就把近几个月来对DSP从熟悉到入手的经历整理出来,可能对老手没有多大作用,但是对于处于入门边缘的网友来说绝对可以省去很多弯路!

    这个文档中有一部分是我在学习的过程中写的随笔,为了以后自己再回头看着方便吧;

    同时能够和大家分享我的入门学习过程,也是一件很开心事情,希望大家以后能使用TI DSP开发出更有用的产品;

     为了方便下载,加入Word板的附件

    从八月份开始学习DSP,在这一段时间里,熟悉了包括在DSP各厂商芯片的熟悉,确定学习用DSP型号,主要是思路是该DPS芯片在以后产品中的应用潜力和学习的难易程度,综合考虑厂家对开发的支持力度和后续的发展,网络资料,从TIMotorola,ADILucent等几家中选择,确定从TIDSP芯片开始,

     

    对于TI DSP的了解包括以下几个方面:

    学习难易程度,先从入门级芯片开始,主要学习TI DSP的开发模式和架构,因为一个厂家的芯片,在底端到高端的兼容性问题上肯定已经做了充分的考虑,这样做为入门级的芯片和基本开发模式熟悉后,再往中高端芯片熟悉会有一个递进的过程,有助于对TI各系列DSP芯片的一个综合了解,便于后期产品开发中的选型,

     

    对于学习内容需要考虑以下方面:

    主要考虑处理速度、功耗、程序存储器和数据存储器的容量、片内的资源,如定时器的数量、I/O口数量、中断数量、DMA通道数等;

     

    因为目前应用市场中TI占有很大份额,并且有相当好的技术支持力度,确定从使用TIDSP(具体型号:TMS320F28027

     

    关于DSP学习选型:

    1DSP2000(除了2812):
    进阶:标准C -> C和汇编混合编程
    说明:把DSP2000当作单片机来玩就可以了,非常简单。C2000系列的主要特性:定点、应用于控制器市场,

    主要包括:C20XF20XF24XF24XX C28x该系芯片具有大量外设资源,如:A/D、定时器、各种串口(同步和异步),WATCHDOGCAN总线/PWM发生器、数字IO脚等。是针对控制应用最佳化的DSP,在TI所有的DSP中,只有C2000FLASH,也只有该系列有异步串口可以和PCUART相连。

    2DSP5000
    主要:标准C -> C和汇编混合编程 -> DSP/BIOS -> RF3
    说明:DSP5000是个中等产品,性能不高不低,基本上也没有开发难度。C5000系列(特性:定点、低功耗),

    主要包括:C54XC54XXC55X 相比其它系列的主要特点是低功耗,所以最适合个人与便携式上网以及无线通信应用,如手机、PDAGPS等应用。处理速度在80MIPS--400MIPS之间。C54XXC55XX 一般只具有McBSP同步串口、HPI并行接口、定时器、DMA等外设。值得注意的是C55XX提供了EMIF外部存储器扩展接口,可以直接使用SDRAM,而C54XX则不能直接使用。两个系列的数字IO都只有两条。

    3DSP6000
    主要:标准C -> C和汇编混合编程
    -> DSP/BIOS -> XDAIS -> RF5
    说明:DSP6000的开发难度明显增大,不论是硬件还是软件。

    主要包括:C62XXC67XXC64X 该系列以高性能著称,最适合宽带网络和数字影像应用。32bit

    其中:C62XXC64X是定点系列,C67XX 是浮点系列。

    C62XX学习中,硬件上会初步遇到信号完整性问题,软件方面来说,DSP/BIOS是必需的,复杂的程序还需要XDAISRF3RF5的知识。

    DSP64XX系列的学习中,硬件方面需要重点考虑系统合理架构问题,信号完整性问题;软件方面,需要综合运用各种比较先进、专业的知识,例如用DSP/BIOS作为RTOS,用RF5作为程序架构,尽量采用MiniDriver来编写底层驱动程序等。如果深入编程,还会遇到令人困惑的Cache冲突问题(虽然TI最近专门针对这个难题升级了CCS),等等。

    别外对于以上TI的各系列产品还需要补充的知识:GELRTDXCSLDSP库函数

     

    对于以上综合考虑,先从C2000做为学习入门型号,后期再扩展到C5000/C6000OMAP系列的学习中;

     

    结合自已的学习能力和现有的知识体系:

    因为前期主要从事MCU相关的系统与应用开发,对于CC++有一定的熟悉程序;

    C/C++在MCU中应用过渡到DSP开发需要考虑以下一些问题(使用MCU熟悉的思绪,从存储空间,中断机制,函数库与程序库的使用,数据操作(包括数据类型,和运算)):

    1.存储空间:

           通过了解与高性能MCU类似dsp也有两种名称的存储空间,一种是物理空间,另一种是映射空间,物理空间是dsp上可以存放数据和程序的实际空间(包括外部存储器),数据和程序最终要被存放到物理空间上,但是在使用过程中并不能直接访问它们,而是需要助于映射空间来访问!同样与MCU类似映射空间远远大于实际的物理空间,而IO、外部设备等会被映射到存储空间中,通过这个访问过程来实现对IO和外部设备的访问。

    2.中断机制:

    主要考虑中断向量表的定义和使用,在DSP中同样需要中断向量表的重定位,所以要处理好中断发生后的地址跳转问题;

    3.函数库与程序库的使用:

    很明显函数库与程序库的使用是为了便于开发和提高开发效率,但是前提是要不影响系统执行效率,在一些成熟算法库的使用上需要有一个综合的评定和使用方式;

    4.数据操作:

         需要了解各种数据类型在DSP中的存储方式,运算符的使用要多参考资料(特别是除法运算(再详细了解));

     

    DSP开发流程:

    整个开发周期流程:

    1.  建立工程、添加文件(.c.lib.cmd.sa.asm);

    2.  代码编辑;

    3.  配置IDE编译选项;

    4.  Buildc/cpp->汇编.ASM->链接.OBJ->.OUT->.HEX);

    5.  Debug(断点、Profile等方式)

    整体用下图表示(包括工具部分):

     

    TIDSP开发软件包括集成开发系统(CCS), 实时操作系统(DSP/BIOS),第三方算法库标准(eXpressDSP)

      DSP/BIOS是一个用户可剪裁的实时操作系统,主要由三部分组成:多线程实时内核(抢占式多线程);实时分析工具;芯片支持库。利用实时操作系统开发程序,可以方便快速的开发复杂的DSP程序。操作系统维护调度多线程的运行,只需将定制的数字信号算法作为一个线程嵌入系统即可;芯片支持库帮助管理外设资源,复杂的外设寄存器初始化可以利用直接图形工具配置;实时分析工具可以帮助分析算法实时运行情况。

      DSP/BIOS以模块化方式提供给用户对线程、中断、定时器、内存资源、所有外设资源的管理能力都可以根据需要剪裁。实际应用中需要的定制算法作为一个线程插入DSP/BIOS的调度队列,由DSP/BIOS进行调度。

    使用前需阅读了解DSP/BIOS用户手册和DSP/BIOS设备驱动的开发与使用,具体内容包括DSP/BIOS概述、程序生成、监测、线程调度、存储器和低级函数、I/O概述和管道、流I/O和设备驱动;设备驱动开发工具包(DDK)简介、DSP/BIOS设备驱动的结构和使用、使用DSP/BIOS设备驱动、GIO类驱动、微型驱动的开发步骤、IOM接口、PIO适配器、LIO模型到IOM模型的移植和GIO APIASYNC扩展。

    DSP/BIOS开发模型及各组件在系统中的位置:

    DSP/BIOS启动流程:

    DSP/BIOS的应用程序启动时,一般遵循下面的步骤:

    1.初始化DSPDSP/BIOS程序从C/C++环境入口c_int00开始运行。对于C6000平台,在c_int00开始处,系统栈指针(B15)和全局页指针(B14)被分别设置在堆栈断的末尾和.bss断的开始。控制寄存器AMRIERCSR等被初始化;

    2.初始化.bss段:当堆栈被设置完成后,初始化任务被调用,利用.cinit的记录对.bss断的变量进行初始化;

    3.调用BIOS_init初始化用到的各个模块:BIOS_init调用MOD_init对配置用到的各个模块进行初始化,包括HWI_initHST_initIDL_init等;

    4处理.pinit表:.pinit表包含一些指向初始化函数的指针,对C++程序,全局对象类的创建也在此时完成;

    5.调用用户程序的main函数:用户main函数可以是C/C++函数或者汇编语言函数,对于汇编函数,使用_main的函数名。由于此时的硬件、软件中断还没有被使能,所以在用户主函数的初始化中需要注意,可以使能单独的中断屏蔽位,但是不能调用类似HWI_enable的接口来使能全局中断;

    6.调用BIOS_start启动DSP/BIOSBIOS_start在用户main函数退出后被调用,它负责使能使用的各个模块并调用MOD_startup启动每个模块。包括CLK_startupPIP_startupSWI_startupHWI_startup等。当TSK管理模块在配置中被使用时,TSK_startup被执行,并且BIOS_start将不会结束返回;

    7.执行idle循环:有两种方式进入idle循环。当TSK管理模块使能时,任务调度器运行的TSK_idle任务调用IDL_loop在其它任务空闲时进入idle循环;当TSK模块未被使用时,BIOS_start调用将返回,并执行IDL_loop进入永久的idle循环,此时硬件和软件中断可以抢占idle循环得到执行。由于idle循环中管理和主机的通信,因此主机和目标机之间的数据交互可以进行了。

     

     

    使用CCS完成软件的编辑、编译和在线调试,

    CCS特性:

    除了类似于VS的工具功能(编译、链接)外,CCS还包调试工具中的步进、查看变量、寄存器、存存器、调用堆栈和反汇编窗口;CCS可以可视化的实现对配置文件的生成,并生成相应的代码,所以说CCS不仅仅是一个代码生成工具,它对开发过程中的各个阶段都有很好的支持;

     

    DSP关键技术:流水操作(取指,解确(包括指令派遣,指令译码),执行)

     

    DSP中断使用与处理流程总结:

    1.  中断向量表定义;

    2.  向中断向量表中设置中断函数入口地址;

    3.  初始化中断定时器;

    4.  编写中断服务函数;

     

    中断实现:

    1.首先在.cmd中定位系统中断表:
    MEMORY
    {
    PAGE 0 :
    ......................................
    PAGE 1 :
    ......................................
       PIE_VECT   : origin = 0x000D00, length = 0x000100

    ......................................        
    }


    SECTIONS
    {
       ...................................
       PieVectTable      : > PIE_VECT,   PAGE = 1
    .....................................
    }
    2.
    C中制定该中断的结构体:

    #pragma DATA_SECTION(PieVectTable,"PieVectTable");
    struct PIE_VECT_TABLE PieVectTable;
    (在DSP28_GlobalVariableDefs.C中初始化)
    3.用一组常数(按照中断向量的顺序)初始化该名字为PIE_VECT_TABLE的表:
    typedef interrupt void(*PINT)(void);

    // Define Vector Table:
    struct PIE_VECT_TABLE {

    // Reset is never fetched from this table.
    // It will always be fetched from 0x3FFFC0 in either
    // boot ROM or XINTF Zone 7 depending on the state of
    // the XMP/MC input signal. On the F2810 it is always
    // fetched from boot ROM.

          PINT     PIE1_RESERVED;
          PINT     PIE2_RESERVED;
          PINT     PIE3_RESERVED;
          PINT     PIE4_RESERVED;
          PINT     PIE5_RESERVED;
          PINT     PIE6_RESERVED;
          PINT     PIE7_RESERVED;
          PINT     PIE8_RESERVED;
          PINT     PIE9_RESERVED;
          PINT     PIE10_RESERVED;
          PINT     PIE11_RESERVED;
          PINT     PIE12_RESERVED;
          PINT     PIE13_RESERVED;

    // Non-Peripheral Interrupts:
          PINT     XINT13;    // XINT13
          PINT     TINT2;     // CPU-Timer2
          PINT     DATALOG;   // Datalogging interrupt
          PINT     RTOSINT;   // RTOS interrupt
          PINT     EMUINT;    // Emulation interrupt
          PINT     XNMI;      // Non-maskable interrupt
          PINT     ILLEGAL;   // Illegal operation TRAP
          PINT     USER0;     // User Defined trap 0
          PINT     USER1;     // User Defined trap 1
          PINT     USER2;     // User Defined trap 2
          PINT     USER3;     // User Defined trap 3
          PINT     USER4;     // User Defined trap 4
          PINT     USER5;     // User Defined trap 5
          PINT     USER6;     // User Defined trap 6
          PINT     USER7;     // User Defined trap 7
          PINT     USER8;     // User Defined trap 8
          PINT     USER9;     // User Defined trap 9
          PINT     USER10;    // User Defined trap 10
          PINT     USER11;    // User Defined trap 11
         
    // Group 1 PIE Peripheral Vectors:
          PINT     PDPINTA;   // EV-A
          PINT     PDPINTB;   // EV-B
          PINT     rsvd1_3;
          PINT     XINT1;    
          PINT     XINT2;
          PINT     ADCINT;    // ADC
          PINT     TINT0;     // Timer 0
          PINT     WAKEINT;   // WD
              
    // Group 2 PIE Peripheral Vectors:
          PINT     CMP1INT;   // EV-A
          PINT     CMP2INT;   // EV-A
          PINT     CMP3INT;   // EV-A
          PINT     T1PINT;    // EV-A
          PINT     T1CINT;    // EV-A
          PINT     T1UFINT;   // EV-A
          PINT     T1OFINT;   // EV-A
          PINT     rsvd2_8;
         
    // Group 3 PIE Peripheral Vectors:
          PINT     T2PINT;    // EV-A
          PINT     T2CINT;    // EV-A
          PINT     T2UFINT;   // EV-A
          PINT     T2OFINT;   // EV-A
          PINT     CAPINT1;   // EV-A
          PINT     CAPINT2;   // EV-A
          PINT     CAPINT3;   // EV-A
          PINT     rsvd3_8;
         
    // Group 4 PIE Peripheral Vectors:
          PINT     CMP4INT;   // EV-B
          PINT     CMP5INT;   // EV-B
          PINT     CMP6INT;   // EV-B
          PINT     T3PINT;    // EV-B
          PINT     T3CINT;    // EV-B
          PINT     T3UFINT;   // EV-B
          PINT     T3OFINT;   // EV-B
          PINT     rsvd4_8;     
        
    // Group 5 PIE Peripheral Vectors:
          PINT     T4PINT;    // EV-B
          PINT     T4CINT;    // EV-B
          PINT     T4UFINT;   // EV-B
          PINT     T4OFINT;   // EV-B
          PINT     CAPINT4;   // EV-B
          PINT     CAPINT5;   // EV-B
          PINT     CAPINT6;   // EV-B
          PINT     rsvd5_8;     

    // Group 6 PIE Peripheral Vectors:
          PINT     SPIRXINTA; // SPI-A
          PINT     SPITXINTA; // SPI-A
          PINT     rsvd6_3;
          PINT     rsvd6_4;
          PINT     MRINTA;    // McBSP-A
          PINT     MXINTA;    // McBSP-A
          PINT     rsvd6_7;
          PINT     rsvd6_8;
         
    // Group 7 PIE Peripheral Vectors:
          PINT     rsvd7_1;
          PINT     rsvd7_2;
          PINT     rsvd7_3;
          PINT     rsvd7_4;
          PINT     rsvd7_5;
          PINT     rsvd7_6;
          PINT     rsvd7_7;
          PINT     rsvd7_8;

    // Group 8 PIE Peripheral Vectors:
          PINT     rsvd8_1;
          PINT     rsvd8_2;
          PINT     rsvd8_3;
          PINT     rsvd8_4;
          PINT     rsvd8_5;
          PINT     rsvd8_6;
          PINT     rsvd8_7;
          PINT     rsvd8_8;

    // Group 9 PIE Peripheral Vectors:  
          PINT     RXAINT;    // SCI-A
          PINT     TXAINT;    // SCI-A
          PINT     RXBINT;    // SCI-B
          PINT     TXBINT;    // SCI-B
          PINT     ECAN0INTA; // eCAN
          PINT     ECAN1INTA; // eCAN
          PINT     rsvd9_7;
          PINT     rsvd9_8;

    // Group 10 PIE Peripheral Vectors:
          PINT     rsvd10_1;
          PINT     rsvd10_2;
          PINT     rsvd10_3;
          PINT     rsvd10_4;
          PINT     rsvd10_5;
          PINT     rsvd10_6;
          PINT     rsvd10_7;
          PINT     rsvd10_8;
               
    // Group 11 PIE Peripheral Vectors:
          PINT     rsvd11_1;
          PINT     rsvd11_2;
          PINT     rsvd11_3;
          PINT     rsvd11_4;
          PINT     rsvd11_5;
          PINT     rsvd11_6;
          PINT     rsvd11_7;
          PINT     rsvd11_8;

    // Group 12 PIE Peripheral Vectors:
          PINT     rsvd12_1;
          PINT     rsvd12_2;
          PINT     rsvd12_3;
          PINT     rsvd12_4;
          PINT     rsvd12_5;
          PINT     rsvd12_6;
          PINT     rsvd12_7;
          PINT     rsvd12_8;
    };
    然后在使我们在.cmd文件中定义的表有以上属性:

    extern struct PIE_VECT_TABLE PieVectTable;(.h文件中)
    4.初始化该表(在.c文件中)使之能够为主程序所使用:
    const struct PIE_VECT_TABLE PieVectTableInit = {

          PIE_RESERVED, // Reserved space
          PIE_RESERVED,  
          PIE_RESERVED,  
          PIE_RESERVED,  
          PIE_RESERVED,  
          PIE_RESERVED,  
          PIE_RESERVED,  
          PIE_RESERVED,  
          PIE_RESERVED,  
          PIE_RESERVED,  
          PIE_RESERVED,  
          PIE_RESERVED,  
          PIE_RESERVED,  


    // Non-Peripheral Interrupts
          INT13_ISR,     // XINT13 or CPU-Timer 1
          INT14_ISR,     // CPU-Timer2
          DATALOG_ISR,   // Datalogging interrupt
          RTOSINT_ISR,   // RTOS interrupt
          EMUINT_ISR,    // Emulation interrupt
          NMI_ISR,       // Non-maskable interrupt
          ILLEGAL_ISR,   // Illegal operation TRAP
          USER0_ISR,     // User Defined trap 0
          USER1_ISR,     // User Defined trap 1
          USER2_ISR,     // User Defined trap 2
          USER3_ISR,     // User Defined trap 3
          USER4_ISR,     // User Defined trap 4
          USER5_ISR,     // User Defined trap 5
          USER6_ISR,     // User Defined trap 6
          USER7_ISR,     // User Defined trap 7
          USER8_ISR,     // User Defined trap 8
          USER9_ISR,     // User Defined trap 9
          USER10_ISR,    // User Defined trap 10
          USER11_ISR,    // User Defined trap 11

    // Group 1 PIE Vectors
          PDPINTA_ISR,   // EV-A
          PDPINTB_ISR,   // EV-B
          rsvd_ISR,
          XINT1_ISR,    
          XINT2_ISR,
          ADCINT_ISR,    // ADC
          TINT0_ISR,     // Timer 0
          WAKEINT_ISR,   // WD

    // Group 2 PIE Vectors
          CMP1INT_ISR,   // EV-A
          CMP2INT_ISR,   // EV-A
          CMP3INT_ISR,   // EV-A
          T1PINT_ISR,    // EV-A
          T1CINT_ISR,    // EV-A
          T1UFINT_ISR,   // EV-A
          T1OFINT_ISR,   // EV-A
          rsvd_ISR,
         
    // Group 3 PIE Vectors
          T2PINT_ISR,    // EV-A
          T2CINT_ISR,    // EV-A
          T2UFINT_ISR,   // EV-A
          T2OFINT_ISR,   // EV-A
          CAPINT1_ISR,   // EV-A
          CAPINT2_ISR,   // EV-A
          CAPINT3_ISR,   // EV-A
          rsvd_ISR,
         
    // Group 4 PIE Vectors
          CMP4INT_ISR,   // EV-B
          CMP5INT_ISR,   // EV-B
          CMP6INT_ISR,   // EV-B
          T3PINT_ISR,    // EV-B
          T3CINT_ISR,    // EV-B
          T3UFINT_ISR,   // EV-B
          T3OFINT_ISR,   // EV-B
          rsvd_ISR,     
        
    // Group 5 PIE Vectors
          T4PINT_ISR,    // EV-B
          T4CINT_ISR,    // EV-B
          T4UFINT_ISR,   // EV-B
          T4OFINT_ISR,   // EV-B
          CAPINT4_ISR,   // EV-B
          CAPINT5_ISR,   // EV-B
          CAPINT6_ISR,   // EV-B
          rsvd_ISR,     

    // Group 6 PIE Vectors
          SPIRXINTA_ISR,   // SPI-A
          SPITXINTA_ISR,   // SPI-A
          rsvd_ISR,
          rsvd_ISR,
          MRINTA_ISR,    // McBSP-A
          MXINTA_ISR,    // McBSP-A
          rsvd_ISR,
          rsvd_ISR,
         
    // Group 7 PIE Vectors
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  

    // Group 8 PIE Vectors
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
         
    // Group 9 PIE Vectors    
          SCIRXINTA_ISR, // SCI-A
          SCITXINTA_ISR, // SCI-A
          SCIRXINTB_ISR, // SCI-B
          SCITXINTB_ISR, // SCI-B
          ECAN0INTA_ISR, // eCAN
          ECAN1INTA_ISR, // eCAN
          rsvd_ISR,  
          rsvd_ISR,  
         
    // Group 10 PIE Vectors
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
               
    // Group 11 PIE Vectors
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  

    // Group 12 PIE Vectors
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
          rsvd_ISR,  
    };


    //---------------------------------------------------------------------------
    // InitPieVectTable:
    //---------------------------------------------------------------------------
    // This function initializes the PIE vector table to a known state.
    // This function must be executed after boot time.
    //

    void InitPieVectTable(void)
    {
    int16 i;
    Uint32 *Source = (void *) &PieVectTableInit;
    Uint32 *Dest = (void *) &PieVectTable;
      
    EALLOW;
    for(i=0; i < 128; i++)
       *Dest++ = *Source++;
    EDIS;

    // Enable the PIE Vector Table
    PieCtrl.PIECRTL.bit.ENPIE = 1;
       
    }
    5.
    中断服务程序:

    让以上的数值指向你所要的服务程序,例如:
    PieVectTable.TINT2 = &ISRTimer2;
    那么,ISRTimer2也就成了中断服务程序,
    ×××切记:一定要在主程序的开始先声明该程序:
    interrupt void ISRTimer2(void);

    .............
    .............
    然后按照您的需要编制该程序:

    interrupt void ISRTimer2(void)
    {
    CpuTimer2.InterruptCount++;
    }

     

     

    DMA关键外设的使用:

    DMA的连接方式:

    DMA中断程序关键代码:

    #include <csl_dma.h>

    extern float result[];

    extern float buffer[];

    void init_dma()

    {

          int **p;

          DMA_Handle hDma;

           DMA_Config MyConfig = {  

           0x00000050,

           0x0000A000,/*BLOCK IE is set by 1*/

           (int)result,

           (int)buffer,  

           0x00010032  };/*one frame per one block;50 elements per one frame*/

        p=(int**)_DMA_hCha0;

        *p=0;

        hDma = DMA_open(DMA_CHA0,DMA_OPEN_RESET); 

        DMA_config(hDma, &MyConfig);

           return;

    }

     

    Flash烧写流程与注意事项:

    在网上看到有的网友在烧写过程中因为一些原因发生掉电或中断时,flash被锁死,还好现在有几种办法可以解决这个问题,比较幸运的是因为比较小心,我还没有碰到过类似的情况!

     

    Flash烧写步骤:

    1.安装CCSF2812烧写插件

    2.将xxx 目录COPY CCS 开发环境中的myproject 目录下;
    CCS 中用projectàOpen……命令,加载SPI 目录下的
    xxxx.pjt;
    编译,生成.out 文件。

    3.在CCS中选择Tools —>F28XX On-Chip Flash Programer

    4.点击“Execute Operation”则显示烧写进度条;

    5.烧写完成

     

    公司DSP使用与方案:

     

    后续需要学习的问题:

    简单算法实现;

    程序加密;

     

    因为时间比较紧,没有写完,后续会把这一部分补上来和大家一起学习!

    再次感谢TI和各位组织的朋友!祝工作愉快!

     

    TI DSP学习纪要.doc
  • 刚才又看了一遍发的学习经历共享贴,发现有一段里面有几个baidu过来的词加了链接!

    里面还有其它部分是学习的时候做的笔记,但很大一部分还是自己原创并一字一字的敲出来的!

    希望不会受到这个影响不符合"原创"的规定!

    谢谢!!

  • 可以修改了!本来是重复的一个贴子!先修改了,准备和大家分享一下自己DSP/BIOS的学习和使用经历!!编辑中

    其实要想用好DSP/BIOS还是要先好好学习一下CCS里面的BIOS配置流程:

     

    这有点类似于uCos的移植过程,玩过MCU的同学都知道,移植完成后要添加一个用户task进去!

    在DSP/BIOS里添加一个线程的实现代码:

    #include <std.h>

    #include <log.h>
    #include <tsk.h>

    #include "tsktestcfg.h"

    #define NLOOPS  5

    Void task(Arg id_arg);   /* 配置工具创建的任务函数 */ 

    /*
     *  ======== main ========
     */
    Void main()
    {
    }

    /*
     *  ======== task ========
     */
    Void task(Arg id_arg)  /*任务函数*/
    {
        Int     id = ArgToInt (id_arg);  /*id_arg为当前调用的任务号,ArgToInt完成参数类型转化,以便以后的打印需要*/
        Int     i;
       
       
        LOG_printf(&trace, "start %d", id); /*调用API函数LOG_printf()打印当前执行的任务编号id*/
       
        for (i = 0; i < NLOOPS ; i++) {
       
            LOG_printf(&trace, "Loop %d: Task %d Working", i, id);
         
            TSK_yield(); /*同优先级间任务切换,挂起当前任务执行下一个同优先级的任务*/
           
            LOG_printf(&trace, "Check %d", id); /* 检查当前运行的任务号*/
            LOG_printf(&trace, "Checkagain %d", id);

        }
      
         LOG_printf(&trace, "Task %d DONE", id); /* 当前任务执行完毕输出完成的任务号id. */
    }

  • 给初学的童鞋共享一下在TMS320C6201上实现的DMA中断程序(c实现)

  • 这个活动真是,太好了,我参与了这个活动的回帖,就立马系统把同志们贡献的文字和附件的文档发到我的邮箱了,直接在邮箱就能下载附件,真是太爽了,方便查阅了,希望能获得个学习板子,太喜欢这个板子了,我同学买了一个,挺不错的。刚好赶上这个活动,自己也发了经验回复的(是附件文档),希望能得一块板子

  • 我使用过NXP ARM LPC2138SPI口,ATMEL AT91SAM7S256SPIMSP430F5438SPI口,
    还有STM32 SPI模块。都是用来读 SPI FLASH 例如 AT45DB642D之类。

    本以为对SPI已经入门了, 谁不知使用TMS320F280XSPI后,才知道自己其实还是一知半解。
    TMS320F280X SPI 真是好好给我上了一课!

    不久前有款 OLED 真彩色液晶。使用的是SSD1351控制器,SPI接口。 想测试一下它的速度。就把它接到我的
    TMS320F280XDSP 开发板上。之前使用DSPIO模拟,运行程序后OLED的效果不错的。
    本想这次使用SPI应该没事吧『虽然I/O模拟也是使用这个SPI的引进』?

    新建立一个工程 MYOLED, 拷贝一些TMS320F28X相关的头文件,C文件。把工程的设置好后,编译OK!
    加上定时器中断用来点亮一个LED,把I/O模拟的工程相关文件的两个子函数改为SPI方式的。
    在编译。文件太大非得使用FLASH下载仿真。

    发现程序不能运行! 没办法改回RAM仿真,把很多函数注释掉。仅仅留下测试OLED的程序。
    SSD1351的测试功能,向它写命令码,可以改变 GPIO1/GPIO2引脚的电平。这样测试SSD1351引脚的电平就知道SPI 驱动函数是否成功了。
    其实移植就是仅仅这两个SPI底层函数:
    void Write_Data(unsigned char Data)
    void Write_Command(unsigned char Data)
    测试好几次都没反应, 因此 就有下面的入门与详解了。
    使用的是SPIA模块,如果SPIB没有什么特别(功能设置与SPIA差不多的话)也是没什么问题的。
    但是我之前使用SPIB测试过,发觉SPIB还是与SPIA有区别的。这点我也很不解~。
    按道理应该不会这样。但事实却是如此.

    TMS320F280XSPI 支持1-16位的数据类型。
    而且 只有MSB先发送,不像ARM7/STM32等可以设MSBLSB先发送。
    TMS320F280XSPI有回环模式, 可以用于测试,自发自收。
    TMS320F280XSPITX FIFORX FIFO. 及其中断字节设置。

    看来没什么特别? 是吧~? 先别小看啊~,就是搞不定它呢!

    首先是要回环模式,这样就是一个自发自收,方便测试。

    其实现在看来,我曾经范了几点毛病。

    1. 使用8位模式,但SPIA的总线,发送接收等寄存器都是16位模式。
    2. 数据的位数设置不对
    3. 时钟极性与时钟相位。
    4. 使用了 TX FIFORX FIFO. 其实不用使用FIFO比较好。为什么?下面会讲。
    5. 没有完全理解SPIA的发送与接收是【同时】进行的概念,这点实在很惭愧!
    6. 发送是MSB对齐先发送,接收是LSB对齐接收,发送与接收是【同时】进行的!

    SSD1351的设置,是:
    时钟 空闲保持高电平。第二个时钟边沿数据采样捕获,第一时钟边沿锁存

    SCLK
    的空闲无效状态是高电平 (其实也可以是低电平,但相位就要改改了,变为第二个时钟边沿锁存,,第一时钟边沿数据采样捕获)

    数据的MSB 先发送。

    好了,看看我是如何范这些毛病的,
    void Write_Data(unsigned char Data)
    void Write_Command(unsigned char Data)

    看出参数都是8位的数据,比如要发送Data=0x55;那么传输到DSP SPI寄存器里这就出问题了!
    是吧? 因为是MSB先发送,这样0x55到了16位的SPI寄存器例如SpiaRegs.SPITXBUFSpiaRegs.SPIDAT 就变为0x0055了,由于SPIA 设置位8位模式,而且是MSB 先发送。那么就是只发送 0x0055 00(8)了,低855就没有发送了。

    因此 发送前要做如下变换:

    Uint16 tmp;

    tmp=Data;
    tmp<<=8;
    。。。。
    SpiaRegs.SPIDAT =tmp
    而接收时无需移位,SpiaRegs.SPIDATSpiaRegs.SPIRXBUF中低8位就是发送的tmp
    SPIA的数据宽度设为8位。
    SpiaRegs.SPICCR.bit.SPICHAR=7
    这个其实很简单,看看手册就知道了,不过我在网上看的HOTPOWER有关C54XSPI设置。
    就把SpiaRegs.SPICCR.bit.SPICHAR=8;来设8位的,这点我认为是不对了,虽然我不了解C54SPI设置。
    但估计也与C28X是一样的吧?哈哈!看来HOTPOWER也会范这样的低级毛病?不会吧?

    时钟极性与时钟相位,其实我的OLED要求的是
    【时钟 空闲保持高电平。第二个时钟边沿数据采样捕获,第一时钟边沿锁存,SCLK的空闲无效状态是高电平】
    这个我想当然的搞错了:

    SpiaRegs.SPICCR.bit.CLKPOLARITY=1; //
    空闲时是高电平 这是对的

    SpiaRegs.SPICTL.bit.CLK_PHASE=1; //这个是错的!**

    后来我认真看看了TI C28X SPI的数据手册,这个大家一定要好好看看啊!

    这个图就是数据在时钟下跳沿改变、锁存,在时钟上升沿被捕获采样。

    如果不明白可以看看我的《精解 SPI
    CPHA
    时钟相位 CPLK 时钟极性》

    正确如下:

    SpiaRegs.SPICCR.bit.CLKPOLARITY=1; //
    空闲时是高电平 这是对的

    SpiaRegs.SPICTL.bit.CLK_PHASE=0;//

    SPIA的发送与接收是【同时】进行的概念
    SPIA数据发送移位寄存器SpiaRegs.SPIDAT 是先发送MSB位,也就是BIT15位移位出SIMO
    同时从SOMI采样一位数据到LSB 也就是BIT0。如此类推
    BIT14移位到BIT15,然后发送到SIMO
    BIT0移位到BIT1,然后从SOMI移入一位数据到BIT0……..

    这个过程发送到SIMO和接收SOMI是同时进行的。
    因此要想知道发送到底完成没有,可以查看接收到完整的8位数据没有。不管数据线怎样,只要有MSB移出SIMO就有数据从SOMI移入BIT0,哪怕全是0或全是1.

    有点不同的是,C28X SPI手册上说当数据接收完毕的SpiaRegs.SPIDAT,就会把SpiaRegs.SPIDAT的数据输入到SpiaRegs.RXBUFRX FIFO中,并置位SpiaRegs.SPISTS.bit.INT_FLAG.
    这点,我认为TI的数据手册在忽悠我们。 真实情况是非的要关闭FIFO增强才会出现这个情况。
    就是SpiaRegs.SPIFFTX.bit.SPIFFENA=0;
    这样我们要查询到的数据发送完毕没有,只有等到SpiaRegs.SPISTS.bit.INT_FLAG置位就可以了。

    之前在网上有个 《TMS320F2812 SPI 总结》,
    http://blog.chinaunix.net/u/31491/showart_654915.html
    文中说"spi速率不能超过15M,超过后会出现严重误码"
    这个应该不对的, 我的这个OLED与C28X SPIA的通信速度就到了20M.(其实还可以到30MHZ, 恐怕OLED受不了)
    SpiaRegs.SPIBRR =0x0002; // 60MHZ/(2+1)=20MHZ SPI SPEED
    而且是烧写到FLASH里运行,一直没问题。

    哎,有点晚了,明天还要上班啦~,大家请原谅在下了,

    其实有决心写这个全是因为当时出了问题比较着急,但在网上GOOGLE却没有什么收获!真让人气愤!
    全大陆这么多大学的YY,GG ,不是很会出啥书啥书的吗?汗!
    希望各位能从这文中有点收获~,不要再被C28XSPI折腾和TI文档的折腾了~!哈哈。
    希望TI别见怪啦~!

  • 这个活动真是,太好了,我参与了这个活动的回帖,就立马系统把同志们贡献的文字和附件的文档发到我的邮箱了,直接在邮箱就能下载附件,真是太爽了,方便查阅了,希望能获得个学习板子,太喜欢这个板子了,我同学买了一个,挺不错的。刚好赶上这个活动,自己也发了经验回复的(是附件文档),希望能得一块板子

    我整理的笔记资料,大家可以下载看一下。新手很有帮助的。

    C 2000 学习笔记.pdf
  • TMS320F2812 看门狗程序

    好活动支持一个,希望能够得到TI的奖励。我的文档在附件里了

    TMS320F2812 看门狗程序.doc
  • 基于TMS320F28335的电机控制Clark变换

    在电机控制中,经常用到clark变换,它的基本思想是把三相静止、互差120°的abc坐标系中的变量变化到两相静止、互差90°的αβ坐标系中,从而简化了控制过程。其基本变换的原理为如图1所示

    图1 clark变换的基本原理

    这里采用了模块化的思想,对clark变换进行了实现。采用了TMS320F28335 高性能浮点DSC,编程使用了全浮点的C语言。
    首先列一下参数列表:
    输入信号:ia,ib;输出信号:ialfa,ibeta
    为了便于后续调用及模块化修改,将全部参数封装为一个结构体。首先定义头文件clarke.h如下:
    typedef struct { float32 As; // Input: phase-a stator variable
    float32 Bs; // Input: phase-b stator variable
    float32 Alpha; // Output: stationary d-axis stator variable
    float32 Beta;// Output: stationary q-axis stator variable
    void (*calc)(); // Pointer to calculation function
    } CLARKE;

    typedef CLARKE *CLARKE_handle;

    /*-----------------------------------------------------------------------------
    Default initalizer for the CLARKE object.
    -----------------------------------------------------------------------------*/
    #define CLARKE_DEFAULTS { 0, \
    0, \
    0, \
    0, \
    (void (*)(Uint32))clarke_calc }

    /*------------------------------------------------------------------------------
    Prototypes for the functions in CLARKE.C
    ------------------------------------------------------------------------------*/
    void clarke_calc(CLARKE_handle);
    其次编写主程序clarke.c,即
    #include "dmctype.h"
    #include "clarke.h"
    void clarke_calc(CLARKE *v)
    {
    v->Alpha = v->As;

    v->Beta = (v->As + 2*v->Bs)*0.57735026918963; // 1/sqrt(3) = 0.57735026918963
    }
    最后是主程序中的调用,主要是对现有的结构体clarke类型进行例化,然后再赋初值,送入参数再把结果读出:

    CLARKE clarkee = CLARKE_DEFAULTS;

    voidmain(void)

    {

    ……初始各变量与寄存器……

    clarkee.As=ia;

    clarkee.Bs=ib;

    clarkee.calc(&clarkee);

    ialfa=clarkee.Alpha;

    ibeta=clarkee.Beta;

    }
    传统的教科书都会提到,坐标变换,矢量控制这些东西会占用多少资源,实现起来不容易。不过对于高性能的28335 DSC来讲,就简单多了。变量的调用、读写一般需要2个时钟周期,乘法需要稍微多一点,整个变换加起来也不过十几个时钟周期,用不了100ns就可以轻松执行完一个变换过程了;

  • 分享一下DSP开发中的中断操作:

    对于各种型号DSP的中断操作都会有一个通用的操作方式如下:

    设置允许需要的非屏蔽中断
    设置这些允许的非屏蔽中断的中断来源
    总中断开启
    配置中断向量表
    挂载中断向量表(通过cmd文件挂载到指令内存)
    编写中断处理函数
    如果中断向量表首地址挂载的不是0地址,那么需要设置中断向量表地址寄存器,便于后面的读取和跳转
    根据不同的中断源,做具体的配置和硬件操作;

  • 分享CMD使用中的一点小技巧:

    如果.text文件很大将其放在一段放不下,需将其放到两个程序段中
    最长的一个length=0x002000,也放不下时.可以这样处理:
    PAGE 0 :
                PRAMH0    : origin = 0x3F8002, length = 0x0014FE
                L0RAM      : origin = 0x008000, length = 0x001000
     
    SECTIONS
                  .text:{*(.text)} >>PRAMH0|L0RAM
    这样就可以将.text文件放在两个定义段中。
     
    查看段的分配及使用情况.map的链接器(存储器)分配映射文件,链接器的map文件描述以下内容:
    通过map文件可以查看各段的分配情况,包括段的起始地址,使用的字节数等配合cmd文件的使用,可
    确定各个段的使用情况,从而保证程序的正常运行和最小的空间使用。 
     
    VisualLinker可视化链接器TI公司出品的 DSP软件开发环境CCS还提供了一种可视化生成存储器配置
    文件的工具:VisualLinker可视化链接器。如果程序原来包含了一个链接器命令文件(.cmd文件),则当
    创建可视化链接文件的时候, 原来cmd文件中的内存配置仍然会被使用。

  • 再分享一个281x定时器初始化通用模板:

    #include "DSP281x_Device.h"    
    #include "DSP281x_Examples.h" 
     
    interrupt void eva_timer1_isr(void);
    void init_eva_timer1(void);
     
    void main(void)

      InitSysCtrl();
      InitGpio();         //IO口初始化
     
      DINT;             //关CPU总中断
      InitPieCtrl();    //初始化PIE控制寄存器
      IER = 0x0000;
      IFR = 0x0000;
      InitPieVectTable();   //初始化PIE中断向量表
     
      EALLOW; 
    //将相应的向量指向中断服务程序,中断发生时,自动跳转
      PieVectTable.T1PINT = &eva_timer1_isr;
      EDIS;   
       
      init_eva_timer1();          //初始化EV-A定时器1
     
    //使能PIE中断INT2.4(T1PINT中断)
      PieCtrlRegs.PIEIER2.all = M_INT4;
      IER |= M_INT2 ;
       
      EINT;        // 使能INTM(全局中断)
      ERTM;        // Enable Global realtime interrupt DBGM
     
      for(;;);
     
    }
     
    //EV-A定时器 1初始化
    void init_eva_timer1(void)
    {   EvaRegs.GPTCONA.all = 0;
      EvaRegs.T1PR = 0x1200;      // Period---周期值
      EvaRegs.T1CMPR = 0x0000;    // Compare Reg--比较值
       
     //清除周期EV-A定时器1中断位
      EvaRegs.EVAIMRA.bit.T1PINT = 1;
      EvaRegs.EVAIFRA.bit.T1PINT = 1;
     
      EvaRegs.T1CNT = 0x0000;            //计数器初值
     
    //递增模式,x/1分频,内部时钟,使能比较,使用自己的周期,立即启动定时器计数
      EvaRegs.T1CON.all = 0x1042;
     
    //启动由EVA 定时器1周期中断产生的ADC转换
      EvaRegs.GPTCONA.bit.T1TOADC = 2;
    }
     
    //EV-A定时器 1中断服务函数
    interrupt void eva_timer1_isr(void)
    {
      ......          //中断服务内容程序
     
    //清除定时器中断位
       EvaRegs.EVAIMRA.bit.T1PINT = 1;
       EvaRegs.EVAIFRA.all = BIT7;      //BIT7---0x0080
     
    //响应中断,从而使INT2中断组继续接收中断
       PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
    }

  • F28335 EPWM使用心得体会

    用28335做一个逆变器,用到了28335 ePWM模块,刚开始对ePWM操作很模糊,无从下手,在网上也找了很多资料,发现看完了之后更加模糊,最后下定决心,看TI 28XX ePWM模块的英文文档,通过二天的努力,终于攻下了ePWM模块,现讲学习总结写出来,和学习28335的朋友们一起分享,也希望朋友们也把你们关于28335的一些好的学习心得写出来,大家相互交流下。28335在TI C2000系列DSP里面比较新的,有关资料基本上都是英文的,很不利于初学者,所以已经在学习或学习过28335的朋友可以相互帮助相互交流下,与人方便就是与己方便。

        言归正传,28335 ePWM模块总结如下:

        1、ePWM模块总共有7个模块:

       (1)时间基准模块   ----------TB    

        (2)计数器比较模块 ----------CC

         (3)动作限定模块   ----------AQ

         (4)死区控制模块   ----------DB

         (5)PWM斩波模块    ----------PC

         (6)错误控制模块   ----------TZ

         (7)事件触发模块   ----------EZ

          每个模块各自作用如下:

        TB :为输出PWM产生始终基准TBCLK,配置PWM的时钟基准计数器TBCTR,设置计数器的计数模式,配置硬件或软件同步时钟基准计数器,确定ePWM同步信号输出源;

        CC:确定PWM占空比,以及ePWM输出高低电平切换时间;

        AQ:确定计数器和比较寄存器匹配时产生动作,即ePWM 高低电平的切换;

        DB:配置输出PWM上升沿或下降沿延时时间,也可以将A、B两通道配置成互补模式,我做的逆变器就是将ePWM配置成互补模式。死区时间可以编程确定;

        PC:产生高频PWM载波信号;

        TZ:当外部有错误信号产生时,对PWM输出进行相应处理,比如全置高,或拉低,或置为高阻态,从而起到保护作用。当然该功能也可以通过软件强制产生;

        EZ:使能ePWM中断,使能ePWM触发ADC采样,确定事件产生触发的速度和清除相关事件标志位。

        ePWM模块的7个模块就像一条生产线,一级一级的经过,但DSP更高级,可以实现通过配置,使得ePWM只经过我选择的生产线,没有被选择上的就不要经过。例如,死区控制模块可以需要也可以不需要,这就看实际系统需不需要了。在实际使用ePWM时,正常的发出PWM波往往只要要配置TB、CC、AQ、DB、ET五个模块。

        2、试着阅读28335 各模块的英文资料,其实这些资料里面,详细的介绍了各模块的使用方法和原理,以及各模块所涉及到的寄存器的详细配置,“擒贼先擒王”,虽然英文资料阅读起来比较费劲,但打开Google,相信一般的都可以搞定,在结合自己的理解,会产生意想不到的收获。英文资料里面一写模块的框图,表格式很有用,这里面涵盖了该模块运行的逻辑关系,其实DSP就是块逻辑芯片,你只要通过寄存器的配置就可以让其完成各种指定的功能,所以不要把它想的太复杂。

       3、可以看看TI 例程里面各模块头文件的定义,里面有些地方会有注释,从而便于理解。另外,可以自己琢磨TI 各模块例程相关寄存器的配置,从而实际寄存器配置的用法。最后说明下,附件里面包括了:我从ePWM英文资料里面截下来的某些子模块的功能框图和配置表格;ePWM TI 英文资料;我之前在HELLO DSP论坛下的一个资料“发波配置说明”(在这里要感谢那位仁兄)。

  • 这个贴子是刚才发另一个贴子发错了,后来又发了一个贴子把漏掉的图补上!

    为了不浪费一个帖子,重新改了写几句一年来接触TI的感觉吧!

    真正的接触TI,是从成都这边利尔达的代理商开始的,有一个产品要用MSP430的芯片,不得不说他们的支持做的真的很到位!

    从那次产品做完后,感觉TI的芯片不管在工具方面,还是库的提供,还有技术支持方面,都能节约很多时间和成本;并且供货很及时;

    后来新产品应用通过代理商和TI Store买过几块demo板,两个途径都很快捷,三到五天就拿到手了!

    细数手里自己的TI的板子,还真有几块了!公司那边的就不算上了!

    第一块是利尔达的支持送给我的MSP430 LaunchPad,当时还是1.4版的,很喜欢,玩基础应用也不错!就没交公司,自己留着了!

    后来在利尔达又自己买了一块F5438块板子加UIF调试器;

    为了学LM3,在TI Store买了一块DK-LM3S9B96的板子!

    后来公司从别的地方拿到一块DSP C28027的板子!是要开发应用的!只是做事情的时候用过,因为资源比较紧张,没怎么好好熟悉,

    就是后来空的时候拿过来学了一段时间,感觉这一段时间的学习虽然没有很深入,但是在产品开发中还是会起到很大作用的!

  • 不好意思!上一贴图没有发上来!重发一次!

    1.进入CCS环境,打开已经建好的工程,并load生成的.out文件,找到要察看代码执行周期的代码处。如图1所示。
     
      
    1
    1
    选择ccs->Profiler->enable clock,如图所示。




    2
    2
    选择Profiler->clock setup子菜单,在Instruction Cycle中输入你的DSP时钟周期,它的单位为纳秒,例如,2407的系统时钟为40MHz,你就该填入25,如果是2812系统时钟为150MHz,就该填入6.67ns,其他配置不动,然后确定。如图3所示。


      
    3
    3
    选择Profiler菜单下的Start New Session子菜单,出现如图4所示的对话框,可以改名字,也可以不改,本例中不修改,直接确定。


      
    4
    4
    通过第四部设定后就出现了如图5所示的一个窗体。



    这个窗体中,有四个选项卡,其中Files为以源文件列出统计数据,Functions选项卡用于剖析程序中的函数,Ranges用于剖析一段连续的代码,Setup用于设置开始点和结束点,用于剖析不连续的代码。
    窗体的左边按钮的含义为:(这里介绍主要的)


    剖析所有的函数。


    建立剖析区域。


    设置开始点。


    设置结束点。
    在窗体中剖析数据有一个表格,用红框圈起来的,每个表格的字段名的含义为:
    Code size:剖析代码的大小,以程序存储器最小可寻址单元为单位,此值在剖析过程中不会发生变化。
    Incl. Count:
    在统计过程中,程序运行进入剖析代码段的次数

    Incl. Total:
    在统计工程中剖析代码段消耗的所有时钟周期(如果是统计时钟周期的话,CCS还可以统计子程序调用等其他计数,统计其他特性则显示相应的值)。

    Incl. Maximum:
    执行剖析代码段一遍(包括在剖析代码段中对子程序的调用)消耗的最大时钟周期(由于每次进入剖析代码段的初始条件不同等原因,每次运行剖析代码段消耗的时钟周期可能不同);

    Incl. Minimum:  
    执行剖析代码段一遍(包括在剖析代码段中对子程序的调用)消耗的最小时钟周期

    Incl. Average:
    剖析代码段执行一遍(包括在剖析代码段中对子程序的调用)消耗的平均时钟周期。
    --
    以上这三个就是用户关心的代码执行的时钟周期。


    Excl. Count:在统计过程中,程序运行进入剖析代码段的次数,与Incl.Count的值相同。
    Excl. Maximum:
    剖析代码段执行一遍(不包括在剖析代码段中对子程序的调用)消耗的最大时钟周期。

    Excl. Minimum:
    剖析代码段执行一遍(不包括在剖析代码段中对子程序的调用)消耗的最小时钟周期。

    Excl. Average:
    剖析代码段执行一遍(不包括在剖析代码段中对子程序的调用)消耗的平均时钟周期。

    5
    以剖析函数为例,找到该函数,然后将光标放在该函数的函数名上,选择建立剖析区域按钮,图中用红框框起来的那个按钮。如图6所示。




    图六。
    6 出现对话框,如图7所示,因为我们做的是function,所以不用修改,如果做的是一段代码,只要把下拉菜单里的function改成Range即可。

      
    7
    7
    点击OK后出现,如图8所示,各个字段已经被赋予了初值。


      
    8
    8
    接下来运行程序RUN,就可以剖析出你所选中的代码的执行周期了。如图所示。且这些值是随着程序运行的时间而变化的,动态显示。



    9
        
    值得注意的是,图中显示的是时钟周期,不是时间,要看时间的化,用时钟周期乘以前面设定的时钟周期ns值,如6.67ns,就是最终函数执行的时间了

     

  • 我自己申请了几个2500,然后自己焊接的,焊接的板子是普通的洞洞板。不知道是焊接上出错了还是怎么的就是不能工作啊

  • MCU对2500的单发送程序,大家可以根据SmartRF Studio 7给出的寄存器信息更改程序以获得自己所要求的功能

    #include "../header/cc2500.h"
    /***********************************************
    函 数: Byte_Write()
    功 能: 写1字节数据到SPI接口
    输 入: byte
    输 出: /
    描 述: /
    ***********************************************/
    void Byte_Write(unsigned char byte)
    {
    unsigned char i;

    for(i = 0x00; i < 0x08; i++)
    {
    if(byte&0x80)
    iSPI_Sdi= positive;
    else
    iSPI_Sdi= negative;

    byte <<= 0x01;
    iSPI_Sck = positive;
    iSPI_Sck = negative;
    }
    }
    /***********************************************
    函 数: Byte_Read()
    功 能: 读1字节数据
    输 入: /
    输 出: byte
    描 述: /
    ***********************************************/
    uchar Byte_Read(void)
    {
    unsigned char i;
    unsigned char byte;

    iSPI_Sdo = positive;

    for(i = 0x00; i < 0x08; i++)
    {
    byte <<= 0x01;

    iSPI_Sck = positive;

    if(iSPI_Sdo)
    byte |= 0x01;
    else
    byte &= 0xfe;

    iSPI_Sck = negative;
    }

    return byte;
    }
    /***********************************************
    函 数: cc2500_Register_Write()
    功 能: 写控制数据到cc2500内部寄存器
    输 入: addr,para
    输 出: /
    描 述: /
    ***********************************************/
    void cc2500_Register_Write(unsigned char addr,unsigned char para)
    {
    iSPI_Sck = negative;
    iSPI_Scs = negative;

    addr &= 0x3f; /* bit7 = 0(write),bit6 = 0(no burst) */

    Byte_Write(addr);

    Byte_Write(para);

    iSPI_Scs = positive;
    }
    /***********************************************
    函 数: cc2500_PowerTable_Write()
    功 能: 写发射功率表数据到cc2500内部寄存器
    输 入: /
    输 出: /
    描 述: /
    ***********************************************/
    void cc2500_PowerTable_Write(void)
    {
    uchar i;

    iSPI_Sck = negative;
    iSPI_Scs = negative;

    Byte_Write(Reg_PA_Table|Burst_Write);

    for(i = 0x00;i < 0x08;i++)
    {
    Byte_Write(flash_Power_Table[i]);
    }

    iSPI_Scs = positive;
    }
    /***********************************************
    函 数: cc2500_Strobe_Write()
    功 能: 写控制数据到cc2500内部寄存器
    输 入: command
    输 出: /
    描 述: command = 0x30 - 0x3d
    ***********************************************/
    void cc2500_Strobe_Write(unsigned char command)
    {
    iSPI_Sck = negative;
    iSPI_Scs = negative;

    command &= 0x3f;

    Byte_Write(command);

    iSPI_Scs = positive;
    }
    /***********************************************
    函 数: RF_Fifo_Write()
    功 能: 写数据到cc2500 FIFO 数据
    输 入: write_buff
    输 出: /
    描 述: command = 0x30 - 0x3d
    ***********************************************/
    void RF_Fifo_Write(unsigned char *write_buff)
    {
    unsigned char i;

    iSPI_Sck = negative;
    iSPI_Scs = negative;

    /* 写cc2500-FIFO命令 */
    Byte_Write(0x7f);

    /* 写cc2500-FIFO数据 */
    for(i = 0x00;i < C_FIFO_Byte;i++)
    {
    Byte_Write(*write_buff);

    write_buff ++;
    }

    iSPI_Scs = positive;
    }
    /***********************************************
    函 数: RF_Fifo_Read()
    功 能: 读数据从cc2500 FIFO 数据
    输 入: read_buff
    输 出: /
    描 述: /
    ***********************************************/
    void RF_Fifo_Read(unsigned char *read_buff)
    {
    unsigned char i;

    iSPI_Sck = negative;
    iSPI_Scs = negative;

    /* 读cc2500-FIFO命令 */
    Byte_Write(0xff);

    /* 读cc2500-FIFO数据 */
    for(i = 0x00;i < C_FIFO_Byte;i++)
    {
    *read_buff = Byte_Read();

    read_buff ++;

    }

    iSPI_Scs = positive;
    }
    /***********************************************
    函 数: CC2500_Reset_Chip()
    功 能: 复位CC2500芯片
    输 入: /
    输 出: /
    描 述: /
    ***********************************************/
    void CC2500_Reset_Chip(void)
    {
    /* 写CC2500芯片Reset */
    cc2500_Strobe_Write(Strobe_SRES); //sres 重启芯片命令
    }
    /***********************************************
    函 数: RF_Setup_receiver()
    功 能: CC2500设置为接收状态
    输 入: /
    输 出: /
    描 述: /
    ***********************************************/
    void RF_Setup_receiver(void)
    {
    iRF_PaEnable = disable;
    cc2500_Strobe_Write(Strobe_SRX);
    }
    /***********************************************
    函 数: RF_Setup_transmiter()
    功 能: CC2500设置为发射状态
    输 入: /
    输 出: /
    描 述: /
    ***********************************************/
    void RF_Setup_transmiter(void)
    {
    iRF_PaEnable = enable;
    cc2500_Strobe_Write(Strobe_STX);
    }
    /***********************************************
    函数:RF_Clear_Rxfifo(void)
    功能:冲洗接受FIFO
    ************************************************/
    /*void RF_Clear_Rxfifo(void)
    { iRF_PaEnable = disable;
    cc2500_Strobe_Write(Strobe_SFRX);
    }

    /************************************************
    函数:RF_Clear_Txfifo(void)
    功能:冲洗接受FIFO
    ************************************************/
    /*void RF_Clear_Txfifo(void)
    {
    iRF_PaEnable = enable;
    cc2500_Strobe_Write(Strobe_SFTX);
    }


    /***********************************************
    函 数: Initialisation_RF()
    功 能: 上电初始化cc2500
    输 入: /
    输 出: /
    描 述: Fdef = 41.25khz , BW = 135khz
    Rate = 10kbps , Fif = 228.5khz
    ***********************************************/
    void Initialisation_RF(void)
    {
    unsigned char i;

    iRF_PaEnable = disable;

    CC2500_Reset_Chip();

    for(i = 0x00;i < 0xff;i++)
    {
    _nop_();
    _nop_();
    _nop_();
    }

    cc2500_Register_Write(Reg_Fsctrl1,0x0c);

    /* frequency offset = 0 */
    cc2500_Register_Write(Reg_Fsctrl0,0x00);

    /* Fosc = 26Mhz,Freq = 0x5bc4ec,base freq = Fosc/65536 * Freq = 2386Mhz */
    cc2500_Register_Write(Reg_Freq2,0x5c);
    cc2500_Register_Write(Reg_Freq1,0x58);
    cc2500_Register_Write(Reg_Freq0,0x9d);

    /* Fosc = 26Mhz,BW_E = 10,BW_M = 00,channel BW = Fosc/8/(4+BW_M) = 203Khz */
    cc2500_Register_Write(Reg_Mdmcfg4,0x86);

    /* DATA_E = 0b0000 1000, DATA_M = 0b1001 0011,data rate = (256+DATA_M)*(2^DATA_E)*Fosc/(2^28) = 10kbps */
    cc2500_Register_Write(Reg_Mdmcfg3,0x83);
    cc2500_Register_Write(Reg_Mdmcfg2,0x83);

    /* enable FEC,preamble bytes = 24bits */
    cc2500_Register_Write(Reg_Mdmcfg1,0xf2);
    /* default Fchannel step = 200khz */
    cc2500_Register_Write(Reg_Mdmcfg0,0xf8);

    /* frequency = base freq + Fchannel*Channr = 2386mhz + 200khz*71 = 2400.2mhz */
    cc2500_Register_Write(Reg_Channr,0x00);
    cc2500_Register_Write(Reg_Deviatn,0x44);

    /* default RX front-end current config */
    cc2500_Register_Write(Reg_Frend1,0xb6);

    /* power table */
    cc2500_PowerTable_Write();
    /* PA_POWER[2:0] = 000 */
    cc2500_Register_Write(Reg_Frend0,0x10);

    /* auto calibration from IDLE to RX O TX,Xosc is off in sleep mode,Xosc stable time 150us */
    cc2500_Register_Write(Reg_Mcsm0,0x18);

    /* RSSI always */
    cc2500_Register_Write(Reg_Mcsm1,0x00);

    /* default recommond value */
    cc2500_Register_Write(Reg_Foccfg,0x1d);

    /* default recommond value */
    cc2500_Register_Write(Reg_Bscfg,0x1c);

    /* default recommond value */
    cc2500_Register_Write(Reg_Agcctrl2,0xc7);
    cc2500_Register_Write(Reg_Agcctrl1,0x00);
    cc2500_Register_Write(Reg_Agcctrl0,0xb2);

    /* default recommond value */
    cc2500_Register_Write(Reg_Fscal3,0xea);
    cc2500_Register_Write(Reg_Fscal2,0x0a);
    cc2500_Register_Write(Reg_Fscal1,0x00);
    cc2500_Register_Write(Reg_Fscal0,0x11);

    /* Asserts when sync word has been sent / received, and de-asserts at the end of the packet */
    cc2500_Register_Write(Reg_Iocfg2,0x06);
    /* Fosc/8 output */
    cc2500_Register_Write(Reg_Iocfg1,0x36);
    /* clear channel indicate */
    cc2500_Register_Write(Reg_Iocfg0,0x09);

    /* enable auto flush FIFO when CRC is error,no address check */
    cc2500_Register_Write(Reg_Pktctrl1,0x08);

    /* whitening off,packet format is normal mode,enable CRC */
    cc2500_Register_Write(Reg_Pktctrl0,0x04);

    /* FIFO packet length is C_FIFO_Byte */
    cc2500_Register_Write(Reg_Pktlen,C_FIFO_Byte);

    /* sync byte */
    cc2500_Register_Write(Reg_Sync1,C_SYNC_Byte1);
    cc2500_Register_Write(Reg_Sync0,C_SYNC_Byte0);


    RF_Setup_receiver();
    }

  • 接受程序

    #include "../header/global.h"
    /****************************************/
    #define positive 1
    #define negative 0

    #define mode_fifo 1 /* 1=fifo mode ; 0=direct mode */
    /******** cc2500 strobe command *********/
    #define Strobe_SRES 0x30 /* reset chip */
    #define Strobe_SFSTXON 0x31 /* enable calibration frequency */
    #define Strobe_SXOFF 0x32 /* turn off crystal oscillator */
    #define Strobe_SRX 0x34 /* enable rx */
    #define Strobe_STX 0x35 /* enable tx */
    #define Strobe_SIDLE 0x36 /* enter idle */
    #define Strobe_SPWD 0x39 /* enter power down when CS goes high */
    #define Strobe_SFRX 0x3A /* flush FIFO rx buffer */
    #define Strobe_SFTX 0x3B /* flush FIFO tx buffer */

    /******* cc2500 register address ********/
    #define Burst_Write 0x40

    #define Reg_Iocfg2 0x00 /* GDO2 output pin configuration */
    #define Reg_Iocfg1 0x01 /* GDO1 output pin configuration */
    #define Reg_Iocfg0 0x02 /* GDO0 output pin configuration */

    #define Reg_FIFOTHR 0x03 /* RX FIFO and TX FIFO thresholds */

    #define Reg_Sync1 0x04 /* Sync word, high byte */
    #define Reg_Sync0 0x05 /* Sync word, low byte */

    #define Reg_Pktlen 0x06 /* Packet length */
    #define Reg_Pktctrl1 0x07 /* Packet automation control */
    #define Reg_Pktctrl0 0x08 /* Packet automation control */

    #define Reg_ADDR 0x09 /* Device address */

    #define Reg_Channr 0x0A /* Channel number */
    #define Reg_Fsctrl1 0x0B /* Frequency synthesizer control */
    #define Reg_Fsctrl0 0x0C /* Frequency synthesizer control */
    #define Reg_Freq2 0x0D /* Frequency control word, high byte */
    #define Reg_Freq1 0x0E /* Frequency control word, middle byte */
    #define Reg_Freq0 0x0F /* Frequency control word, low byte */
    #define Reg_Mdmcfg4 0x10 /* Modem configuration */
    #define Reg_Mdmcfg3 0x11 /* Modem configuration */
    #define Reg_Mdmcfg2 0x12 /* Modem configuration */
    #define Reg_Mdmcfg1 0x13 /* Modem configuration */
    #define Reg_Mdmcfg0 0x14 /* Modem configuration */
    #define Reg_Deviatn 0x15 /* Modem deviation setting */

    #define Reg_Mcsm2 0x16 /* Main Radio Cntrl State Machine config */
    #define Reg_Mcsm1 0x17 /* Main Radio Cntrl State Machine config */
    #define Reg_Mcsm0 0x18 /* Main Radio Cntrl State Machine config */
    #define Reg_Foccfg 0x19 /* Frequency Offset Compensation config */
    #define Reg_Bscfg 0x1A /* Bit Synchronization configuration */
    #define Reg_Agcctrl2 0x1B /* AGC control */
    #define Reg_Agcctrl1 0x1C /* AGC control */
    #define Reg_Agcctrl0 0x1D /* AGC control */

    #define Reg_WOREVT1 0x1E /* High byte Event 0 timeout */
    #define Reg_WOREVT0 0x1F /* Low byte Event 0 timeout */
    #define Reg_WORCTRL 0x20 /* Wake On Radio control */

    #define Reg_Frend1 0x21 /* Front end RX configuration */
    #define Reg_Frend0 0x22 /* Front end TX configuration */
    #define Reg_Fscal3 0x23 /* Frequency synthesizer calibration */
    #define Reg_Fscal2 0x24 /* Frequency synthesizer calibration */
    #define Reg_Fscal1 0x25 /* Frequency synthesizer calibration */
    #define Reg_Fscal0 0x26 /* Frequency synthesizer calibration */

    #define Reg_RCCTRL1 0x27 /* RC oscillator configuration */
    #define Reg_RCCTRL0 0x28 /* RC oscillator configuration */

    #define Reg_Fstest 0x29 /* Frequency synthesizer cal control */

    #define Reg_PTEST 0x2A /* Production test */
    #define Reg_AGCTEST 0x2B /* AGC test */
    #define Reg_TEST2 0x2C /* Various test settings */
    #define Reg_TEST1 0x2D /* Various test settings */
    #define Reg_TEST0 0x2E /* Various test settings */

    #define Reg_PA_Table 0x3e
    /******* cc2500 status_reg addr ********/
    #define Reg_PARTNUM 0x30 /* Part number */
    #define Reg_VERSION 0x31 /* Current version number */
    #define Reg_FREQEST 0x32 /* Frequency offset estimate */
    #define Reg_LQI 0x33 /* Demodulator estimate for link quality */
    #define Reg_RSSI 0x34 /* Received signal strength indication */
    #define Reg_MARCSTATE 0x35 /* Control state machine state */
    #define Reg_WORTIME1 0x36 /* High byte of WOR timer */
    #define Reg_WORTIME0 0x37 /* Low byte of WOR timer */
    #define Reg_PKTSTATUS 0x38 /* Current GDOx status and packet status */
    #define Reg_VCO_VC_DAC 0x39 /* Current setting from PLL cal module */
    #define Reg_TXBYTES 0x3A /* Underflow and # of bytes in TXFIFO */
    #define Reg_RXBYTES 0x3B /* Overflow and # of bytes in RXFIFO */
    /****************************************/
    /* 发射功率表 */
    code unsigned char flash_Power_Table[0x08]= {0xfe,0xbb,0xa9,0x7f,0x6e,0x97,0xc6,0x8d};


  • ///*********************************************主程序

           /***********************************************

    * copyrite (c) 2007

    *文件名:  main.c

    *作者:  larry

    *当前版本:  v1.0

    *建立时间:        2008-07-28 15:29

    *完成日期:        

    ;联系:            13510074992

                   ;E-MAIL:          pjh78@163.com

    *描述:            测试cc2500通讯性能(W78e52B,5V VDD,33.177M OSC)    

    ************************************************/

    #include    "../header/main.h"              

    /***********************************************

    函 数: main()

    功 能: 主体循环函数

    输 入: /

    输 出: /

    描 述: /

    ***********************************************/

    void    main(void)

    {

           /* 上电初始化系统 */

    PowerOn_Initialisation();          

           while(1)

           {  

      /*

       while(1)

       //{

    //if(!KEY3)

    {

       lcd_printf_string("tom1WAVE", ROW(0x00)|LEN(0x08)|COL(0x00));

               lcd_printf_string(" CC2500 ", ROW(0x01)|LEN(0x08)|COL(0x00));

    RF_Fifo_Write(&demo[number][0]);

                   RF_Setup_transmiter();    

                   while(!iRF_Gio2)

    //while(!(P3&0x04))

                   {                    

                   }

                   while(iRF_Gio2)

    //while(P3&0x04)

                   {                    

                   }

                   if((++number) > 0x03)

                       number    = 0x00;

                   RF_Setup_receiver();  

    }

    */

       // }

    if(!KEY4)

    {

       lcd_printf_string("tom2WAVE", ROW(0x00)|LEN(0x08)|COL(0x00));

               lcd_printf_string(" CC2500 ", ROW(0x01)|LEN(0x08)|COL(0x00));    

    }

     //Initialisation_RF();

               //KeyScan();

               if(iSPI_Irq)

               {

                  //P2     &= 0xfd;

      mDelay(100);

      /*  

                   while(iSPI_Irq)

                   {

                   }

                    */        

                   RF_Fifo_Read(&rece_buff);

                   lcd_printf_string("CC2500RX", ROW(0x00)|LEN(0x08)|COL(0x00));

               if(rece_buff[0]==0x12)

     {

    lcd_printf_string("  1234  ", ROW(0x01)|LEN(0x08)|COL(0x00));

        }

      else if(rece_buff[0]==0x56)

         {

      lcd_printf_string("  5678  ", ROW(0x01)|LEN(0x08)|COL(0x00));

     }

    else if  (rece_buff[0]==0x9a)

       {

      lcd_printf_string("  9abc  ", ROW(0x01)|LEN(0x08)|COL(0x00));

     }

       else  if(rece_buff[0]==0xde)

      {

    lcd_printf_string("  def0  ", ROW(0x01)|LEN(0x08)|COL(0x00));

     }

                  RF_Setup_receiver();  

                  // P2     |= 0x02;  

               }

           }  

    }

    /***********************************************

    函 数: Timer0Int

    功 能: timer0中断函数

    输 入: /  

    输 出: /

    描 述: /

    ***********************************************/

    void    Timer0Int(void) interrupt   1

    {

       TH0     = 0xF5;

       TL0     = 0x33;                             // 33.177M OSC,timer0 计时1ms

       if(Time_Count)

           Time_Count --;

       if(Time_second)

       {

           if((--Time_second) == 0x00)

           {

               flag_master = false;

           }

       }

    }

    void mDelay(unsigned int Delay)    //延时Delay = 1000 时间为1S

    {

       unsigned int i;

       for(;Delay>0;Delay--)

      {  

          for(i=0;i<200;i++)

          {;}

      }

    }

  • 利用TMS320F2812实现电力系统的各种参数测量

          通过对电力参数、谐波源特征和现有电力参数测量技术的分析,建立基于FFT的电力参
    数测量模型和谐波分析模型;为了消除FFT频谱泄漏,采用数字锁相同步方法进行误
    差修正;最后采用TI公司的TMS320F2812作为核心处理器,构建多通道数据采集、
    DSP数据处理、外部扩展存储、锁相倍频电路等关键模块的软硬件系统。充分利用DSP
    的运算功能来实现针对电力参数的实时测量、实时采样、有效值运算、功率计算、谐波
    分析等关键运算,同时进行实时按键处理,将测得的参数和波形进行显示。在系统调试
    方面使用JTAG接口进行DSP调试,既简化了系统设计,又提高了系统的性能

    电力系统的电压、电流的理想波形是标准的正弦波,正弦波供电能够减少铁损并提
    高效率。然而正弦波形只是一种理想状态,实际上是不可能完全实现的。对于一个畸变
    的非正弦周期函数,可以用傅里叶级数表示:

           由于电力系统中的非正弦周波都是不规则的畸变波形,所以无法从函数解析式转化为上式,进而获得谐波参数。常用的方法是对该种波形的连续时间信号进行等间隔采样,并把采样值转化为数字序列,然后借助相关算法进行谐波分析。  电力参数的测量主要包括:电流有效值、电压有效值、有功功率、无功功率、视在
    功率、功率因数、频率等。而根据被采集信号方法的不同,交流电参量的采样测量方法主要有两种:直流采样法和交流采样法。直流采样法是把交流电压、电流信号转化为直流电压,采样经过整流后的直流量,对采样值只需作一次比例变换即可得到被测量的数值,这种方法的主要优点是算法简单,便于滤波。但直流采样法存在一些问题:测量精度直接受整流电路的精度和稳定性的影响;整流电路参数调整困难且受波形因素影响较小;此外,用直流采样法测量工频电压、电流是通过测量平均值来求出有效值的,当电路中谐波含量不同时,平均值与有效值之间的关系也将发生变化,给计算结果带来了误差。因此,要获得高精度、高稳定性的测量结果,必须采用交流采样技术。 

            本系统的硬件平台采用了以DSP为主控制器的系统结构,系统总框图如下图所示。该系统主要由TMS320F2812为主控制器,同时与扩展的数据存储器和程序存储器组成DSP的最小系统,为了测量还加入了电压、电流传感器,A/D转换及控制电路,看门狗和电源监视电路,此外还扩展了人机接口电路——键盘和LCD显示电路。

     

    由于系统使用的变量很多,因此所设计的DSP系统要进行数据存储器和程序存储器的扩展   如下图所示

            为了防止死机现象发生,在硬件上采用了看门狗(Watchdog)电路。看门狗电路的核心是一个可重触发单稳态电路。要使看门狗电路能正常工作,在软件设计上,在CPU正常执行程序期间,定时给看门狗电路发送重触发脉冲,使其复位。一旦因干扰使CPU程序“跑飞”,看门狗电路不再收到定时触发脉冲,看门狗电路在暂态过程结束后发生翻转,输出一个宽态度足以引起CPU重新复位或产生不可屏蔽中断的脉冲信号,它由单稳态电路中电阻、电容元件参数确定。电路如下

     

    电压互感器与电流互感器主要有两个作用:在仪表不能对被测电压和电流进行直接测量时,对电压和电流进行变化以扩大仪表的使用范围及使仪表与主回路隔离,保证工作人员和仪表的安全。本装置需要测量的是三相交流电,电压一般为220V左右,为使互感器的电压输入能够在较大范围内变化,选用SPT204A电压互感器和SCT245A电流互感器来得到精度高、线形度好的5V输出交流电压。SPT204A是一款毫安级精密电压互感器,输入额定电压、电流为100V、2mA。它具有精度高、小巧轻便、能直接焊于印刷线路板上等特点。输入电压经限流电阻R,使流过SPT204A电压互感器原边产生一个2mA的额定电流,此时副边会产生一个相同的电流。通过运算放大器的作用,可通过调节反馈电阻的值得到所要求得电压输出值。用户可调节电阻R得到要求的输出电压。电容C、电阻R是调节相移的,用户调节电阻R来改变输入、输出之间的相位差。

    A/D芯片和DSP的连接 如下图

     

    ADS8364 与2812的时序图

    由于LCD属于慢速设备,如果将总线直接与该器件相连接,就要插入很长时间的硬件等待状态,就会对整个系统的运行速度产生极大的影响,就不能进行实时信号处理了。常规的高速实时处理系统,都采用独立的CPU来进行显示功能和按键功能的处理,负责显示的CPU与DSP之间是通过串行口进行显示数据的传输和按键的读入的,这种方式适用于DSP计算任务量达,时序紧张的系统。而本系统为了简化设计而采用了一体化的设计。通过锁存的数据来模拟LCD的写操作时序,缺点是设计中没有LCD的数据回读操作功能,因此为了实现显示滚屏功能就需要在存储器中存有显示缓冲区的所有数据。 如下图

     

    软件设计

    由A/D的中断引脚说明和相应的电路设计可知,在采样定时器中断中启动A/D变换,并设置了A/D采样读取标志。此时在主循环中进行该A/D的读操作,如果该转换
    没有结束,则在下一次主循环中继续进行转换结束的监测;当监测到转换结束后,该读取操作就会产生一个外部的A/D中断,在采样中断程序中,将各通道数据读出,同时除A/D采样读取标志。在将A/D变换值读取后,设置数据处理标志,以便在主循环中进行处理。数据采集程序和数据处理程序如下:

    #define BASE_ADDR 0x809fc0
    #define ERROR*(int*)(BASE_ADDR+0)
    #define INT0*(int*)(BASE_ADDR+1)//int0
    #define INT1*(int*)(BASE_ADDR+2)
    #define INT2*(int*)(BASE_ADDR+3)
    #define INT3*(int*)(BASE_ADDR+4)
    #define CS_AD_A*(int*)0x100001//ADS8
    #define CG*(int*)0x808064
    cregister unsigned int IOF,IE,IF,ST;
    int*buf1,sample_date[16];
    void init_system(void);
    void init_Application(void);
    void nit_buffer(void);
    void init_interrupt(void);
    void init_adctrl(void);
    main()
    {init_Application();
    for(;;);}
    interrupt void ad(void)
    {
    int i;
    for(i=0;i<6;i++)//读ADS8364六个通道的结果
    {*(buf1+i)=CS_AD_A&0x3fff;}
    }
    void init_system(void)
    {
    CG=0x1058;
    }
    void init_Application(void)
    {
    init_system();
    init_buffer();
    init_interrupt();
    init_adctrl();
    }
    void init_buffer(void)
    {
    int i;
    buf1=sample_date;
    for(i=0;i<16;i++)
    *(buf1+i)=0;
    }

    void init_interrupt(void)
    {
    IE=1;
    IF=0;
    INT0=(0x60000000|(unsigned int)ad);//加载中断服务程序入口地址
    ST=0x2000;
    }
    void init_adctrl(void)
    {
    CS_AD_A=0x0f;
    }

    用快速傅立叶变换FFT来进行谐波分析程序

    #include "DSP281x_Device.h"
    #include "fft.h"
    #include "const.h"

    #define N_FFT     8

    /* Create an Instance of FFT module                 */
    #define     N   128
    #pragma DATA_SECTION(ipcb, "FFTipcb");
    #pragma DATA_SECTION(mag, "FFTmag");

    CFFT32  fft=CFFT32_128P_DEFAULTS;

    long ipcb[N_FFT][2*N];
    long mag[N_FFT][N];

    /* Define window Co-efficient Array  and place the
    .constant section in ROM memory    */
    const long win[N/2]=HAMMING128;

    Uint16 fftflag=0;   //FFT转换启动标志:0不启动;1:启动

    extern Uint16 SampleTable[N_SAMPLE+1][N_ANALOG];

    void fft_data()
    {
        Uint16 i,j;

        if (fftflag==0)
        {
           for (i=0;i<N_FFT;i++)
               for (j=0;j<N;j++)
               {
                   ipcb[i][2*j]=((unsigned long)SampleTable[j][2*i])<<16;
               }
           fftflag=1;
        }
    }

    void fft_subroutine()
    {
        Uint16 i;

        if (fftflag==1)     // If the samples are acquired
        {
           for (i=0;i<N_FFT;i++)
           {

       /* Initialize FFT module                            */
               fft.ipcbptr=&ipcb[i][0];
               fft.magptr=&mag[i][0];
               fft.winptr=(long *)win;
               fft.init(&fft);

                   {
         CFFT32_brev2(&ipcb[i][0],&ipcb[i][0],N);
    //     CFFT32_brev2(&ipcb[i][0],&ipcb[i][0],N);  // Input samples in Real Part

    /*     fft.win(&fft);
         CFFT32_brev2(ipcb,ipcb,N);
         CFFT32_brev2(ipcb,ipcb,N);  // Input after windowing
       */
                       fft.izero(&fft);
                       fft.calc(&fft);
                       fft.mag(&fft);
                   }

           }
                       fftflag=0;      // Enable the next acquisition
              GpioDataRegs.GPATOGGLE.bit.GPIOA15=1;
        }

    }

     基于TMS3202812系统硬件平台的设计以及软件编程实现,硬件方面主要论述了存储器的电路设计、看门狗电路设计、仿真器接口电路设计,A/D变
    换及锁相环电路设计、电压、电流互感电路设计、电源管理设计等具体的硬件电路设计这些也是DSP系统设计的难点和关键点,还是很有价值的。