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只有一次获奖机会
每周做一次审核。先到先得!
  • 先抢个座,C2000正在探索中,向前辈同伴们学习

  • 礼品已经收到,感谢 deyisupport ,感谢TI

  • 星期五了,又一周 ,新一 批的名单快出来了吧?希望有我的

  • deyisuppor的各位朋友辛苦了!

  • 也发一个用于计算谐波的基于FFT的计算程序,在实际中采用。

    采用F28335作为主控DSP计算,150MHz满频率运行,其中一些计算点是经过多次debug之后得出的心得,主要有如下:(见图中标红的地方)

    1. 牺牲代码尺寸,提高执行速度,
    2. 运用了IQmath进行运算,提高计算速度和效率,
    3. 连接的时候需要注意库的连接
    4. 建议最好基于TI的例程进行修改,或者自己做成通用库,经过测试后再用,不然会很痛苦

    这个分享活动很好啊,前面有个老兄提到的利用CCS进行运行效率测试,整好可以测试我这段代码, 正在开展中, 看看我做的优化效果如何。

    //###########################################################################
    //
    // FILE:    user_FFT.c
    //
    // TITLE:    user's FFT.
    //
    // DESCRIPTION:
    //         
    //
    //###########################################################################
    //31 Jul 2009
    //wangx
    //###########################################################################

    #include "DSP2833x_Device.h"     // DSP2833x Headerfile Include File


    #pragma DATA_SECTION(ipcb,"FFTipcb")
    //#pragma DATA_SECTION(mag,"FFTmag")
    #define    N128    128
          
    RFFT32  fft=RFFT32_128P_DEFAULTS;
    long ipcb[N128+2];
    //long mag[N128/2+1];
    //const long win[N128/2]=HAMMING128;
    //RFFT32_ACQ  acq=FFTRACQ_DEFAULTS;


    //用于测试,正式程序不需要
    #define FFT_cos 0
    #if FFT_cos
    int cosa[128]={
    0,        1472,    2940,    4401,    5852,    7289,    8708,    10106,
    11480,    12826,    14141,    15423,    16667,    17870,    19031,    20146,
    21213,    22228,    23190,    24096,    24944,    25731,    26457,    27119,
    27716,    28246,    28708,    29100,    29423,    29675,    29855,    29963,
    30000,    29963,    29855,    29675,    29423,    29100,    28708,    28246,
    27716,    27119,    26457,    25731,    24944,    24096,    23190,    22228,
    21213,    20146,    19031,    17870,    16667,    15423,    14141,    12826,
    11480,    10106,    8708,    7289,    5852,    4401,    2940,    1472,
    0,        -1472,    -2940,    -4401,    -5852,    -7289,    -8708,    -10106,
    -11480,    -12826,    -14141,    -15423,    -16667,    -17870,    -19031,    -20146,
    -21213,    -22228,    -23190,    -24096,    -24944,    -25731,    -26457,    -27119,
    -27716,    -28246,    -28708,    -29100,    -29423,    -29675,    -29855,    -29963,
    -30000,    -29963,    -29855,    -29675,    -29423,    -29100,    -28708,    -28246,
    -27716,    -27119,    -26457,    -25731,    -24944,    -24096,    -23190,    -22228,
    -21213,    -20146,    -19031,    -17870,    -16667,    -15423,    -14141,    -12826,
    -11480,    -10106,    -8708,    -7289,    -5852,    -4401,    -2940,    -1472
    };
    #endif

    //initial fft buffer
    void Init_FFT(void)
    {
        //Initialize FFT module
        fft.ipcbptr=ipcb;
    //    fft.magptr=mag;  
    //    fft.winptr=(long *)win;
        fft.init(&fft);
    }

    //fft proc
    void FFTProc(int *pInputData)
    {
    //    int iF;
    //    for(iF=0;iF<128;iF++)
    //        ipcb[iF]=pInputData[iF];
    //    memcpy(&ipcb,&pInputData,128*sizeof(int));

    //    牺牲代码尺寸,换取运行速度
        ipcb[0]=pInputData[0];
        ipcb[1]=pInputData[1];
        ipcb[2]=pInputData[2];
        ipcb[3]=pInputData[3];
        ipcb[4]=pInputData[4];
        ipcb[5]=pInputData[5];
        ipcb[6]=pInputData[6];
        ipcb[7]=pInputData[7];
        ipcb[8]=pInputData[8];
        ipcb[9]=pInputData[9];
        ipcb[10]=pInputData[10];
        ipcb[11]=pInputData[11];
        ipcb[12]=pInputData[12];
        ipcb[13]=pInputData[13];
        ipcb[14]=pInputData[14];
        ipcb[15]=pInputData[15];
        ipcb[16]=pInputData[16];
        ipcb[17]=pInputData[17];
        ipcb[18]=pInputData[18];
        ipcb[19]=pInputData[19];
        ipcb[20]=pInputData[20];
        ipcb[21]=pInputData[21];
        ipcb[22]=pInputData[22];
        ipcb[23]=pInputData[23];
        ipcb[24]=pInputData[24];
        ipcb[25]=pInputData[25];
        ipcb[26]=pInputData[26];
        ipcb[27]=pInputData[27];
        ipcb[28]=pInputData[28];
        ipcb[29]=pInputData[29];
        ipcb[30]=pInputData[30];
        ipcb[31]=pInputData[31];
        ipcb[32]=pInputData[32];
        ipcb[33]=pInputData[33];
        ipcb[34]=pInputData[34];
        ipcb[35]=pInputData[35];
        ipcb[36]=pInputData[36];
        ipcb[37]=pInputData[37];
        ipcb[38]=pInputData[38];
        ipcb[39]=pInputData[39];
        ipcb[40]=pInputData[40];
        ipcb[41]=pInputData[41];
        ipcb[42]=pInputData[42];
        ipcb[43]=pInputData[43];
        ipcb[44]=pInputData[44];
        ipcb[45]=pInputData[45];
        ipcb[46]=pInputData[46];
        ipcb[47]=pInputData[47];
        ipcb[48]=pInputData[48];
        ipcb[49]=pInputData[49];
        ipcb[50]=pInputData[50];
        ipcb[51]=pInputData[51];
        ipcb[52]=pInputData[52];
        ipcb[53]=pInputData[53];
        ipcb[54]=pInputData[54];
        ipcb[55]=pInputData[55];
        ipcb[56]=pInputData[56];
        ipcb[57]=pInputData[57];
        ipcb[58]=pInputData[58];
        ipcb[59]=pInputData[59];
        ipcb[60]=pInputData[60];
        ipcb[61]=pInputData[61];
        ipcb[62]=pInputData[62];
        ipcb[63]=pInputData[63];
        ipcb[64]=pInputData[64];
        ipcb[65]=pInputData[65];
        ipcb[66]=pInputData[66];
        ipcb[67]=pInputData[67];
        ipcb[68]=pInputData[68];
        ipcb[69]=pInputData[69];
        ipcb[70]=pInputData[70];
        ipcb[71]=pInputData[71];
        ipcb[72]=pInputData[72];
        ipcb[73]=pInputData[73];
        ipcb[74]=pInputData[74];
        ipcb[75]=pInputData[75];
        ipcb[76]=pInputData[76];
        ipcb[77]=pInputData[77];
        ipcb[78]=pInputData[78];
        ipcb[79]=pInputData[79];
        ipcb[80]=pInputData[80];
        ipcb[81]=pInputData[81];
        ipcb[82]=pInputData[82];
        ipcb[83]=pInputData[83];
        ipcb[84]=pInputData[84];
        ipcb[85]=pInputData[85];
        ipcb[86]=pInputData[86];
        ipcb[87]=pInputData[87];
        ipcb[88]=pInputData[88];
        ipcb[89]=pInputData[89];
        ipcb[90]=pInputData[90];
        ipcb[91]=pInputData[91];
        ipcb[92]=pInputData[92];
        ipcb[93]=pInputData[93];
        ipcb[94]=pInputData[94];
        ipcb[95]=pInputData[95];
        ipcb[96]=pInputData[96];
        ipcb[97]=pInputData[97];
        ipcb[98]=pInputData[98];
        ipcb[99]=pInputData[99];
        ipcb[100]=pInputData[100];
        ipcb[101]=pInputData[101];
        ipcb[102]=pInputData[102];
        ipcb[103]=pInputData[103];
        ipcb[104]=pInputData[104];
        ipcb[105]=pInputData[105];
        ipcb[106]=pInputData[106];
        ipcb[107]=pInputData[107];
        ipcb[108]=pInputData[108];
        ipcb[109]=pInputData[109];
        ipcb[110]=pInputData[110];
        ipcb[111]=pInputData[111];
        ipcb[112]=pInputData[112];
        ipcb[113]=pInputData[113];
        ipcb[114]=pInputData[114];
        ipcb[115]=pInputData[115];
        ipcb[116]=pInputData[116];
        ipcb[117]=pInputData[117];
        ipcb[118]=pInputData[118];
        ipcb[119]=pInputData[119];
        ipcb[120]=pInputData[120];
        ipcb[121]=pInputData[121];
        ipcb[122]=pInputData[122];
        ipcb[123]=pInputData[123];
        ipcb[124]=pInputData[124];
        ipcb[125]=pInputData[125];
        ipcb[126]=pInputData[126];
        ipcb[127]=pInputData[127];
        RFFT32_brev(ipcb,ipcb,N128);
        fft.calc(&fft);
        fft.split(&fft);
    //    fft.mag(&fft);//仅需要各次谐波的实部虚部值的时候,无须该计算
    }


    void FFTGetComplex(int nHarmonic, COMPLEX *pResult)
    // 该函数在FFTProc函数执行后调用,得到各次谐波的复数表达形式
    // 输入:谐波次数(0=dc, 1=基波, 2=2次谐波, ...)
    {
        int i;
        //that is i=nHarmonic*2;
        i= (nHarmonic<<1);
        pResult->nReal = ipcb[i]*2;
        pResult->nImage = ipcb[i+1]*2;
    }

    void fft128base(long *real,long *image,int *inputdata)
    {
       //real
        *real =((long)inputdata[0]-(long)inputdata[64])*100;
        *real+=((long)inputdata[1]-(long)inputdata[65]-(long)inputdata[63]+(long)inputdata[127])*9988/100;
        *real+=((long)inputdata[2]-(long)inputdata[66]-(long)inputdata[62]+(long)inputdata[126])*9952/100;
        *real+=((long)inputdata[3]-(long)inputdata[67]-(long)inputdata[61]+(long)inputdata[125])*9892/100;
        *real+=((long)inputdata[4]-(long)inputdata[68]-(long)inputdata[60]+(long)inputdata[124])*9808/100;
        *real+=((long)inputdata[5]-(long)inputdata[69]-(long)inputdata[59]+(long)inputdata[123])*9700/100;
        *real+=((long)inputdata[6]-(long)inputdata[70]-(long)inputdata[58]+(long)inputdata[122])*9569/100;
        *real+=((long)inputdata[7]-(long)inputdata[71]-(long)inputdata[57]+(long)inputdata[121])*9415/100;

        *real+=((long)inputdata[8]-(long)inputdata[72]-(long)inputdata[56]+(long)inputdata[120])*9239/100;
        *real+=((long)inputdata[9]-(long)inputdata[73]-(long)inputdata[55]+(long)inputdata[119])*9040/100;
        *real+=((long)inputdata[10]-(long)inputdata[74]-(long)inputdata[54]+(long)inputdata[118])*8819/100;
        *real+=((long)inputdata[11]-(long)inputdata[75]-(long)inputdata[53]+(long)inputdata[117])*8577/100;
        *real+=((long)inputdata[12]-(long)inputdata[76]-(long)inputdata[52]+(long)inputdata[116])*8315/100;
        *real+=((long)inputdata[13]-(long)inputdata[77]-(long)inputdata[51]+(long)inputdata[115])*8032/100;
        *real+=((long)inputdata[14]-(long)inputdata[78]-(long)inputdata[50]+(long)inputdata[114])*7730/100;
        *real+=((long)inputdata[15]-(long)inputdata[79]-(long)inputdata[49]+(long)inputdata[113])*7410/100;

        *real+=((long)inputdata[16]-(long)inputdata[80]-(long)inputdata[48]+(long)inputdata[112])*7071/100;
        *real+=((long)inputdata[17]-(long)inputdata[81]-(long)inputdata[47]+(long)inputdata[111])*6716/100;
        *real+=((long)inputdata[18]-(long)inputdata[82]-(long)inputdata[46]+(long)inputdata[110])*6344/100;
        *real+=((long)inputdata[19]-(long)inputdata[83]-(long)inputdata[45]+(long)inputdata[109])*5957/100;
        *real+=((long)inputdata[20]-(long)inputdata[84]-(long)inputdata[44]+(long)inputdata[108])*5556/100;
        *real+=((long)inputdata[21]-(long)inputdata[85]-(long)inputdata[43]+(long)inputdata[107])*5141/100;
        *real+=((long)inputdata[22]-(long)inputdata[86]-(long)inputdata[42]+(long)inputdata[106])*4714/100;
        *real+=((long)inputdata[23]-(long)inputdata[87]-(long)inputdata[41]+(long)inputdata[105])*4276/100;
        
        *real+=((long)inputdata[24]-(long)inputdata[88]-(long)inputdata[40]+(long)inputdata[104])*3827/100;
        *real+=((long)inputdata[25]-(long)inputdata[89]-(long)inputdata[39]+(long)inputdata[103])*3369/100;
        *real+=((long)inputdata[26]-(long)inputdata[90]-(long)inputdata[38]+(long)inputdata[102])*2903/100;
        *real+=((long)inputdata[27]-(long)inputdata[91]-(long)inputdata[37]+(long)inputdata[101])*2430/100;
        *real+=((long)inputdata[28]-(long)inputdata[92]-(long)inputdata[36]+(long)inputdata[100])*1951/100;
        *real+=((long)inputdata[29]-(long)inputdata[93]-(long)inputdata[35]+(long)inputdata[99])*1467/100;
        *real+=((long)inputdata[30]-(long)inputdata[94]-(long)inputdata[34]+(long)inputdata[98])*980/100;
        *real+=((long)inputdata[31]-(long)inputdata[95]-(long)inputdata[33]+(long)inputdata[97])*491/100;
        *real= *real/6400;

        //image
        *image=-((long)inputdata[32]-(long)inputdata[96])*100;
        *image-=((long)inputdata[1]-(long)inputdata[65]+(long)inputdata[63]-(long)inputdata[127])*491/100;
        *image-=((long)inputdata[2]-(long)inputdata[66]+(long)inputdata[62]-(long)inputdata[126])*980/100;
        *image-=((long)inputdata[3]-(long)inputdata[67]+(long)inputdata[61]-(long)inputdata[125])*1467/100;
        *image-=((long)inputdata[4]-(long)inputdata[68]+(long)inputdata[60]-(long)inputdata[124])*1951/100;
        *image-=((long)inputdata[5]-(long)inputdata[69]+(long)inputdata[59]-(long)inputdata[123])*2430/100;
        *image-=((long)inputdata[6]-(long)inputdata[70]+(long)inputdata[58]-(long)inputdata[122])*2903/100;
        *image-=((long)inputdata[7]-(long)inputdata[71]+(long)inputdata[57]-(long)inputdata[121])*3369/100;

        *image-=((long)inputdata[8]-(long)inputdata[72]+(long)inputdata[56]-(long)inputdata[120])*3827/100;
        *image-=((long)inputdata[9]-(long)inputdata[73]+(long)inputdata[55]-(long)inputdata[119])*4276/100;
        *image-=((long)inputdata[10]-(long)inputdata[74]+(long)inputdata[54]-(long)inputdata[118])*4714/100;
        *image-=((long)inputdata[11]-(long)inputdata[75]+(long)inputdata[53]-(long)inputdata[117])*5141/100;
        *image-=((long)inputdata[12]-(long)inputdata[76]+(long)inputdata[52]-(long)inputdata[116])*5556/100;
        *image-=((long)inputdata[13]-(long)inputdata[77]+(long)inputdata[51]-(long)inputdata[115])*5957/100;
        *image-=((long)inputdata[14]-(long)inputdata[78]+(long)inputdata[50]-(long)inputdata[114])*6344/100;
        *image-=((long)inputdata[15]-(long)inputdata[79]+(long)inputdata[49]-(long)inputdata[113])*6716/100;

        *image-=((long)inputdata[16]-(long)inputdata[80]+(long)inputdata[48]-(long)inputdata[112])*7071/100;
        *image-=((long)inputdata[17]-(long)inputdata[81]+(long)inputdata[47]-(long)inputdata[111])*7410/100;
        *image-=((long)inputdata[18]-(long)inputdata[82]+(long)inputdata[46]-(long)inputdata[110])*7730/100;
        *image-=((long)inputdata[19]-(long)inputdata[83]+(long)inputdata[45]-(long)inputdata[109])*8032/100;
        *image-=((long)inputdata[20]-(long)inputdata[84]+(long)inputdata[44]-(long)inputdata[108])*8315/100;
        *image-=((long)inputdata[21]-(long)inputdata[85]+(long)inputdata[43]-(long)inputdata[107])*8577/100;
        *image-=((long)inputdata[22]-(long)inputdata[86]+(long)inputdata[42]-(long)inputdata[106])*8819/100;
        *image-=((long)inputdata[23]-(long)inputdata[87]+(long)inputdata[41]-(long)inputdata[105])*9040/100;
        
        *image-=((long)inputdata[24]-(long)inputdata[88]+(long)inputdata[40]-(long)inputdata[104])*9239/100;
        *image-=((long)inputdata[25]-(long)inputdata[89]+(long)inputdata[39]-(long)inputdata[103])*9415/100;
        *image-=((long)inputdata[26]-(long)inputdata[90]+(long)inputdata[38]-(long)inputdata[102])*9569/100;
        *image-=((long)inputdata[27]-(long)inputdata[91]+(long)inputdata[37]-(long)inputdata[101])*9700/100;
        *image-=((long)inputdata[28]-(long)inputdata[92]+(long)inputdata[36]-(long)inputdata[100])*9808/100;
        *image-=((long)inputdata[29]-(long)inputdata[93]+(long)inputdata[35]-(long)inputdata[99])*9892/100;
        *image-=((long)inputdata[30]-(long)inputdata[94]+(long)inputdata[34]-(long)inputdata[98])*9952/100;
        *image-=((long)inputdata[31]-(long)inputdata[95]+(long)inputdata[33]-(long)inputdata[97])*9988/100;
        *image= *image/6400;
        //
    }

    //ad FFT
    void ADFFTCalc(void)
    {
        ADDataCopy();    
        (*Calculate1)(&Snapshot_ADBuf.Analog1[0], &AD_PORT1);
        (*Calculate2)(&Snapshot_ADBuf.Analog2[0], &AD_PORT2);
        (*Calculate3)(&Snapshot_ADBuf.Analog3[0], &AD_PORT3);
        (*Calculate4)(&Snapshot_ADBuf.Analog4[0], &AD_PORT4);
        (*Calculate5)(&Snapshot_ADBuf.Analog5[0], &AD_PORT5);
        (*Calculate6)(&Snapshot_ADBuf.Analog6[0], &AD_PORT6);
        (*Calculate7)(&Snapshot_ADBuf.Analog7[0], &AD_PORT7);
        (*Calculate8)(&Snapshot_ADBuf.Analog8[0], &AD_PORT8);
        (*Calculate9)(&Snapshot_ADBuf.Analog9[0], &AD_PORT9);
        (*Calculate10)(&Snapshot_ADBuf.Analog10[0], &AD_PORT10);
        (*Calculate11)(&Snapshot_ADBuf.Analog11[0], &AD_PORT11);
        (*Calculate12)(&Snapshot_ADBuf.Analog12[0], &AD_PORT12);
        (*Calculate13)(&Snapshot_ADBuf.Analog13[0], &AD_PORT13);
        (*Calculate14)(&Snapshot_ADBuf.Analog14[0], &AD_PORT14);
        (*Calculate15)(&Snapshot_ADBuf.Analog15[0], &AD_PORT15);
        (*Calculate16)(&Snapshot_ADBuf.Analog16[0], &AD_PORT16);
        (*Calculate17)(&Snapshot_ADBuf.Analog17[0], &AD_PORT17);
        (*Calculate18)(&Snapshot_ADBuf.Analog18[0], &AD_PORT18);

    }

    //基波计算函数
    //============================================================================================================//
    //    只计算基波分量,并计算有效值,根据实际需求选用;//                                                          //
    //    long  RealResult,ImageResult;
    //    fft128base(&RealResult,&ImageResult,&Snapshot_ADBuf.Analog1[0]);                                          //
    //    Uab500.harm[1].nReal  =RealResult;                                                                          //
    //    Uab500.harm[1].nImage =ImageResult;                                                                          //
    //    Uab500.Abs=_IQ1sqrt((
    //                        (long)abs(Uab500.harm[1].nReal) *
    //                        (long)abs(Uab500.harm[1].nReal) +
    //                        (long)abs(Uab500.harm[1].nImage) *
    //                        (long)abs(Uab500.harm[1].nImage)
    //                        )<<1)>>1;
    //============================================================================================================//
    //    仅在需要开平方计算的时候使用,且要求所有数据为非负值,否则要求使用转换公式进行转换
    //    原因:sqrt(double)所以无法直接使用,_IQ1sqrt(Q1)
    //============================================================================================================//      
    void FFT_BASE(int *inputdata, SAM_DATA *AD_PORT)
    {
       long  RealResult, ImageResult;
       Uint32 AbsMid;
      // Uint32 AbsMid_har2;
       fft128base(&RealResult,&ImageResult,inputdata);
       AD_PORT->harm[1].nReal  = RealResult;                                                                          //
       AD_PORT->harm[1].nImage = ImageResult;
       AbsMid=   (long)AD_PORT->harm[1].nReal  * (long)AD_PORT->harm[1].nReal
               + (long)AD_PORT->harm[1].nImage * (long)AD_PORT->harm[1].nImage;
       
       // 开方函数。                                                                                        //
       AD_PORT->Abs_Base=(_IQ1sqrt((AbsMid>>3))<<1);

       if(AD_PORT->Abs_Base<0)
       {
            AD_PORT->Abs_Base+=65536;
       }
    }

    //全波计算函数(1+3+5+7+11次谐波)
    //============================================================================================================//
    //    计算0~63次谐波,并计算有效值,根据实际需求选用                                                              //
    //    FFTProc(Snapshot_ADBuf.Analog1);                                                                          //
    //    AbsMid=0;                                                                                                  //
    //    for(i=1;i<7;i++)                                                                                          //
    //    {                                                                                                          //
    //        FFTGetComplex(i,&Uab500.harm[i]);                                                                      //
    //        AbsMid = AbsMid+Uab500.harm[i].nReal*Uab500.harm[i].nReal+Uab500.harm[i].nImage*Uab500.harm[i].nImage;//
    //    }                                                                                                          //
    //    Uab500.Abs = sqrt(AbsMid);
    //============================================================================================================//
    void FFT_FULL(int *inputdata, SAM_DATA *AD_PORT)
    {
        Uint32 AbsMid,AbsBase;

        FFTProc(inputdata);   
        FFTGetComplex(1,&AD_PORT->harm[1]);
        AbsMid = (long)AD_PORT->harm[1].nReal  * (long)AD_PORT->harm[1].nReal
                + (long)AD_PORT->harm[1].nImage * (long)AD_PORT->harm[1].nImage;
        
        // 基波有效值
        if(RMS_Choose==1)     
        {
            AbsBase=AbsMid;
            AD_PORT->Abs_Base=(_IQ1sqrt((AbsBase>>3))<<1);
            if(AD_PORT->Abs_Base<0)
            {
                AD_PORT->Abs_Base+=65536;
            }
        }

        
        FFTGetComplex(0,&AD_PORT->harm[0]);
        AbsMid += (long)AD_PORT->harm[0].nReal  * (long)AD_PORT->harm[0].nReal
                + (long)AD_PORT->harm[0].nImage * (long)AD_PORT->harm[0].nImage;
        
        FFTGetComplex(3,&AD_PORT->harm[2]);
        AD_PORT->har_2 = (long)AD_PORT->harm[2].nReal  * (long)AD_PORT->harm[2].nReal
                + (long)AD_PORT->harm[2].nImage * (long)AD_PORT->harm[2].nImage;

        AbsMid += AD_PORT->har_2;
        //二次谐波计算
        AD_PORT->har_2 =_IQ1sqrt(AD_PORT->har_2>>3)<<1;
        
        FFTGetComplex(5,&AD_PORT->harm[3]);
        AbsMid += (long)AD_PORT->harm[3].nReal  * (long)AD_PORT->harm[3].nReal
                + (long)AD_PORT->harm[3].nImage * (long)AD_PORT->harm[3].nImage;
        
        FFTGetComplex(7,&AD_PORT->harm[4]);
        AbsMid += (long)AD_PORT->harm[4].nReal  * (long)AD_PORT->harm[4].nReal
                + (long)AD_PORT->harm[4].nImage * (long)AD_PORT->harm[4].nImage;
        
        FFTGetComplex(11,&AD_PORT->harm[5]);
        AbsMid += (long)AD_PORT->harm[5].nReal  * (long)AD_PORT->harm[5].nReal
                + (long)AD_PORT->harm[5].nImage * (long)AD_PORT->harm[5].nImage;

        AD_PORT->Abs_Full =_IQ1sqrt(AbsMid>>3)<<1;

        if(AD_PORT->Abs_Full<0)
        {
            AD_PORT->Abs_Full+=65536;
        }
          
    }

  • 接上续--

    算出来的谐波有什么用? 做保护:无非是比较是否超过阈值且维持了多长时间, 然后告警或者断电。

    实际测试出,循环运行一次, 需要6ms左右,一个工频周波20ms,FFT效率还是优化的比较可以。不过IQmath计算出来的FFT总感觉有点担心,因为直接调用函数而不知道内部是否正确。。。看TI的文档也是心理没底, 这种状态不知道哪位工程师有过,产品投运了,客户很满意但是自己其实总有点担心。

    void HarmonicProtect(SYS_Par *V, DC_AMINPUT *A, SWINPUT *S, PROTECT *P, COUNT *C, CHECK_NUM *N)
    {
        float32 Idc100HzMax,Idc50HzMax,temp[2];

        temp[0] = A->IdcD100Hz;
        temp[1] = A->IdcY100Hz;
        Idc100HzMax = MaxOfFloatArray(temp,2);

        temp[0] = A->IdcD50Hz;
        temp[1] = A->IdcY50Hz;
        Idc50HzMax = MaxOfFloatArray(temp,2);

        //二次谐波,报警
        if(Idc100HzMax > (float32)V->Harmonic_100HzWarningCurrent)            
        {
            if(C->DcThawIceFaultFirst.DcThawIceFaultEveryBit.Harmonic100HzWarning == 0)
            {
                C->DcThawIceFaultFirst.DcThawIceFaultEveryBit.Harmonic100HzWarning = 1;
                C->CounterHarmonic100HzWarning = 0;
            }
            else
            {
                if(C->CounterHarmonic100HzWarning >= V->Harmonic_100HzWarningTime)
                {    
                    if(V->DcThawIceFault.DcThawIceFaultEveryBit.Harmonic100HzWarning != 1)
                    {
                        V->DcThawIceFault.DcThawIceFaultEveryBit.Harmonic100HzWarning = 1;
                        AddFaultToStructWithTimeStamp(V,N,HARMONIC_100HZ_WARNING,FAULT_TYPE_VOLTAGE_CURRENT,FAULT_PRAM_RATIO_1,(Uint16)Idc100HzMax);
                        /*if(P->FaultNum == 0)
                        {
                            P->FaultNum = LED_2;//2
                            P->TripFlag = 1;
                            P->ForbidPulseFlag = 1;                        
                        }*/
                    }
                }
            }
        }
        else
        {
            C->CounterHarmonic100HzWarning = 0;
        }

        //二次谐波,跳闸
        if(Idc100HzMax > (float32)V->Harmonic_100HzFaultCurrent)            
        {
            if(C->DcThawIceFaultFirst.DcThawIceFaultEveryBit.Harmonic100HzFault == 0)
            {
                C->DcThawIceFaultFirst.DcThawIceFaultEveryBit.Harmonic100HzFault = 1;
                C->CounterHarmonic100HzFault= 0;
            }
            else
            {
                if(C->CounterHarmonic100HzFault >= V->Harmonic_100HzFaultTime)
                {    
                    if(V->DcThawIceFault.DcThawIceFaultEveryBit.Harmonic100HzFault != 1)
                    {
                        V->DcThawIceFault.DcThawIceFaultEveryBit.Harmonic100HzFault = 1;
                        AddFaultToStructWithTimeStamp(V,N,HARMONIC_100HZ_FAULT,FAULT_TYPE_VOLTAGE_CURRENT,FAULT_PRAM_RATIO_1,(Uint16)Idc100HzMax);
                        if(P->FaultNum == 0)
                        {
                            P->FaultNum = LED_7;//7
                            P->TripFlag = 1;
                            P->ForbidPulseFlag = 1;                        
                        }
                    }
                }
            }
        }
        else
        {
            C->CounterHarmonic100HzFault = 0;
        }

        //工频谐波,报警
        if(Idc50HzMax > (float32)V->Harmonic_50HzWarningCurrent)            
        {
            if(C->DcThawIceFaultFirst.DcThawIceFaultEveryBit.Harmonic50HzWarning == 0)
            {
                C->DcThawIceFaultFirst.DcThawIceFaultEveryBit.Harmonic50HzWarning = 1;
                C->CounterHarmonic50HzWarning = 0;
            }
            else
            {
                if(C->CounterHarmonic50HzWarning >= V->Harmonic_50HzWarningTime)
                {    
                    if(V->DcThawIceFault.DcThawIceFaultEveryBit.Harmonic50HzWarning != 1)
                    {
                        V->DcThawIceFault.DcThawIceFaultEveryBit.Harmonic50HzWarning = 1;
                        AddFaultToStructWithTimeStamp(V,N,HARMONIC_50HZ_WARNING,FAULT_TYPE_VOLTAGE_CURRENT,FAULT_PRAM_RATIO_1,(Uint16)Idc50HzMax);
                        /*if(P->FaultNum == 0)
                        {
                            P->FaultNum = LED_2;//2
                            P->TripFlag = 1;
                            P->ForbidPulseFlag = 1;                        
                        }*/
                    }
                }
            }
        }
        else
        {
            C->CounterHarmonic50HzWarning = 0;
        }

        //工频谐波,跳闸
        if(Idc50HzMax > (float32)V->Harmonic_50HzFaultCurrent)            
        {
            if(C->DcThawIceFaultFirst.DcThawIceFaultEveryBit.Harmonic50HzFault == 0)
            {
                C->DcThawIceFaultFirst.DcThawIceFaultEveryBit.Harmonic50HzFault = 1;
                C->CounterHarmonic50HzFault = 0;
            }
            else
            {
                if(C->CounterHarmonic50HzFault >= V->Harmonic_50HzFaultTime)
                {    
                    if(V->DcThawIceFault.DcThawIceFaultEveryBit.Harmonic50HzFault != 1)
                    {
                        V->DcThawIceFault.DcThawIceFaultEveryBit.Harmonic50HzFault = 1;
                        AddFaultToStructWithTimeStamp(V,N,HARMONIC_50HZ_FAULT,FAULT_TYPE_VOLTAGE_CURRENT,FAULT_PRAM_RATIO_1,(Uint16)Idc50HzMax);
                        if(P->FaultNum == 0)
                        {
                            P->FaultNum = LED_7;//7
                            P->TripFlag = 1;
                            P->ForbidPulseFlag = 1;                        
                        }
                    }
                }
            }
        }
        else
        {
            C->CounterHarmonic50HzFault = 0;
        }    
    }

  • 这位老兄的FFT好简洁啊, 不知道运行效率如何, 我记得当初我们做的简单调用FFT,执行时间很长, 达不到实时控制的要求。

  • 活动的板子已经收到,感谢TI举办的活动,祝TI生意红火啊

  • 现在正在使用ti载波产品TMS320F28069的硬件调试、测试,这个硬件方面的可以参加?

  • 写一写我在使用TMS320F2812的串口调试的经历

    开始接触TMS320F2812的时候,是在年后了,当时在调试串口程序

    写了程序如下:

    Send_Flag = 0;

       #if SCIA_INT

    /*设置中断服务程序入口地址*/

    EALLOW; // This is needed to write to EALLOW protected registers

    PieVectTable.TXAINT = &SCITXINTA_ISR;

    PieVectTable.RXAINT = &SCIRXINTA_ISR;

    EDIS;   // This is needed to disable write to EALLOW protected registers

    /*开中断*/

    IER |= M_INT9;

    #endif

    EINT;   // Enable Global interrupt INTM

    ERTM; // Enable Global realtime interrupt DBGM

    for(;;)

    {

     if((SciaTx_Ready() == 1) && (Send_Flag == 1))

     {

      SciaRegs.SCITXBUF = Sci_VarRx;

      Send_Flag = 0;

      i++;

      if(i == j)

      {

       i = 0;

       j = 0;

      }

     }

     #if !SCIA_INT

     if(SciaRx_Ready() == 1)

     {

      Sci_VarRx[j] = SciaRegs.SCIRXBUF.all;

      Send_Flag = 1;

      j++;

      if(j == 100)

      {

       j = 0;

      }

     }

     #endif

    }

    所写的串口中断程序如下:

    #include "DSP28_Device.h"

    unsigned int Sci_VarRx[100];

    unsigned int i,j;

    unsigned int Send_Flag;

    unsigned int * Led8  = (unsigned int *) 0x4100;

    //#define SCIA_INT 1

    interrupt void SCITXINTA_ISR1(void);

    interrupt void SCIRXINTA_ISR1(void);

    void main(void)

    {

    /*初始化系统*/

    InitSysCtrl();

    /*关中断*/

    DINT;

    IER = 0x0000;

    IFR = 0x0000;

    /*初始化PIE中断*/

    InitPieCtrl();

    /*初始化PIE中断矢量表*/

    InitPieVectTable();

    /*初始化SCIA寄存器*/

       InitSci();

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

       {

        Sci_VarRx = 0;

       }

       i = 0;

       j = 0;

       Send_Flag = 0;

      #if SCIA_INT

    /*设置中断服务程序入口地址*/

    EALLOW; // This is needed to write to EALLOW protected registers

    PieVectTable.TXAINT = &SCITXINTA_ISR1;

    PieVectTable.RXAINT = &SCIRXINTA_ISR1;

    EDIS;   // This is needed to disable write to EALLOW protected registers

    /*开中断*/

    IER |= M_INT9;

    #endif

    EINT;   // Enable Global interrupt INTM

    ERTM; // Enable Global realtime interrupt DBGM

    for(;;)

    {

     if(1 && (Send_Flag == 1))

     {

      SciaRegs.SCITXBUF = Sci_VarRx[0];

      while(SciaRegs.SCICTL2.bit.TXRDY!=1);

      Send_Flag = 0;

      i++;

      if(i == j)

      {

       i = 0;

       j = 0;

      }

     }

     #if !SCIA_INT

     if(SciaRx_Ready() == 1)

     {

      Sci_VarRx[j] = SciaRegs.SCIRXBUF.all;

      Send_Flag = 1;

      j++;

      if(j == 100)

      {

       j = 0;

      }

     }

     #endif

    }

    }  

    interrupt void  SCITXINTA_ISR1(void)

    {

    }

    interrupt void SCIRXINTA_ISR1(void)

    {

    DINT;

    PieCtrl.PIEACK.bit.ACK9=1;

    Sci_VarRx[0] = SciaRegs.SCIRXBUF.all;

    Send_Flag = 1;

    j++;

    // if(j == 100)

    // {

    //  j = 0;

    // }

      *Led8=j;

    SciaRegs.SCICTL1.bit.SWRESET =1;

    PieCtrl.PIEIFR9.bit.INTx1=1;

    EINT;

    }

    串口使用时,不通过中断接收和发送信息使用了下面的例程可以实现信息的发送与接收,但是使用了中断以后,程序不执行。

    即使我读取数据寄存器的数值和清除ACK,都不能是串口工作!

    问了很多的人都不知道有什么问题!

    后来我开始查阅资料,发现了自己的寄存器好像配置出现了问题。

    在使用TMS320f2812的时候,串口中断一直无法解决,

    后来才发现原来是配置出现了问题:

     SciaRegs.SCIFFTX.all=0xe020;

    在fftx寄存器中把使能寄存器写偏移了一个位置。

    正确的配置为:

    SciaRegs.SCICCR.all = 0x07;设置为8位输出

    SciaRegs.SCICTL1.all=0x03;//

    SciaRegs.SCIHBAUD=0x00;//

    SciaRegs.SCILBAUD=0xf3;//配置波特率为19200

    SciaRegs.SCICTL2.all=0x03;//

    SciaRegs.SCIFFRX.all=0x21;//

    SciaRegs.SCIFFTX.all=0xe020;

    SciaRegs.SCIFFCT.all=0x0000;

    SciaRegs.SCIFFRX.bit.RXFIFORESET=1;

    SciaRegs.SCICTL1.bit.SWRESET=1;使能sci

  • 基于TMS320F2812PGFA开发板

        简介:采用TI C2000系列DSP TMS320F2812设计一款实验开发板。设计周期:2012-03——2012-05。主要资源:硬件资源包含:A/D4路同步采样12ADS7862216TLC4151), D/A(816位 DAC8568216DAC7632)数字温度传感器TMP275,I2C I/O扩展:PCF8575,PWM电平转换:SN74AVC16244RS232:MAX3232, USBRS232:TUSB3410CAN:SN65HVD233RTC实时时钟:BQ4802,FLASH扩展,1602,蜂鸣器,1602液晶,独立按键,LED,达林顿步进电机驱动:ULN2003。

        第一阶段:芯片选型

        在这个阶段遇到很多问题,主要总结为:1.需要实现什么功能?2.要达到什么样的性能?3.设计难易程度?

        1.需要实现什么功能?解决办法:我设计的实验板主要用途是用来熟悉F2812硬件、软件编程、外围电路设计、熟悉常用器件使用方法。考虑到这些我在设计中使用了AD、DA、RTC、RS232、CAN、USB转串口、I/O扩展、电压电平转换等功能。因此,要选用哪一类器件,实现什么功能的问题解决了。

        2.要达到什么样的性能?解决办法:如问题1中所述,我设计的板子用于实验,因此主要考虑实现功能这一问题,对性能要求不高。那么在选择器件是选用非高性能器件即可。

        3.设计难易程度?解决办法:综合考虑问题1和问题2之后基本确定了选择芯片的范围,但这还不够。例如,在设计电源时,有这几款芯片可以考虑:TPS767D301、TPS767D318、TPS54290(高性能)、TPS54291(高性能)、TPS75533(高性能、大功率)、TPS75518(高性能、大功率等,但考虑到设计难易程度、以及参考资料、成本、性能之后选择设计较简单的TPS767D318,直接输出F2812所需的1.8V/3.3V,而不需要太多的外围器件。因此,在这个阶段应考虑以下几个方面:设计难易程度、成本、性能,具体地说,如电源需求是否复杂、是否需要辅助元器件、是否需要高性能、成本等因素。


        第二阶段:F2812硬件资源分配

        我的设计中使用了比较多IC,如果每一个芯片都分配唯一的I/O,那么即使F2812多大56个多路复用I/O引脚也不够用。我在设计中总是遇到I/O引脚不够用,失败多次,大概2周的时间都在不断的失败不断地尝试。最后,多方考虑之下,我终于的、想到了解决办法——把类似芯片归类,采用跳线的方式解决I/O复用的问题。例如:DAC7632和DAC8568划分为一类,他们采用跳线的方式共用某些引脚。

        第三阶段:PCB布局

        我没有相关的设计经验,我能做的就是参考成熟设计,多请教,多动手,不要怕,坚持。这是一个需要长期经验积累才能解决的问题,我在这里仅仅提几句。抛砖引玉。坚持就会胜利。

        第四阶段:硬件调试

        首先是调试电源,在确认电源没问题之后才能给CPU加电。很幸运,我在这没遇到问题。但接下来,就让我头痛了,用仿真器与JTAG连接时,总是出错,无法连接。最后我多次检查还是没解决,由于电源本身没问题,因为在PCB布局时不小心将排针封装改小了,我在焊接时把孔钻大,一开始没太注意,最后发现把覆铜钻没了,部分引脚接触不良。但很不幸我已开始没察觉,我在测量JTAG电压时不小心将万用表探针把5V电源引脚和DSP地线短接了,这下就悲剧了,我辛辛苦苦焊了一天的板子一下就烧毁了,F2812很脆弱,不能呢个承受>3.3V的电压,结果F2812烧了。但是还算幸运,我找到了问题所在,那一定问题出在JTAG接口接触的问题了。最后,我想了个办法,既然我不能把板子上的孔钻大,但我可以吧排针磨小啊,最后还是勉强解决这个问题了。请注意了:调试电路板,一定要预防人为短路,我的教训。

       第五阶段:软件调试

        硬件调试后,接下来的调试就要在F2812内部编程序来一一测试了。主要是:GPIO、RS232、AD、CAN、SPI、PWM、ECAP等。因为我正在进行这一阶段,不是特别熟悉,就不多说啦。


        以上就是我的些许设计心得,能力有限,疏漏及不当之处请指正。最后要感谢TI提供的样片,正因为有TI的支持我设计才得以实现。谢谢。


    板子照片:








  • 本人现在大三,刚刚接触DSP,目前说是不折不扣的菜鸟,但来到这了,不能不留点东西,整理了一下肚子里得东西,希望对大家有帮助吧。

    唉,不多写了,上附件。

    一点总结.doc
  • 项目名称:基于DSP2407的PFC控制电路

    设计要求:输入电压在85V-235V,

    输出电压:350V

    功率为:300W

    控制芯片为:TI的DSP2407芯片

    设计心得:

    在功率因数校正领域,传统的PFC模拟控制电路占据主导地位,主要是由专用的集成芯片来实现。近年来,随着数字信号处理技术的飞速发展,以DSP为核心数字信号处理芯片开始广泛的应用于开关电源中。数字控制较之模拟控制有很多优点,比如控制减少成本,适应性好,开放周期短等,数字控制将是功率因数校正领域今后的发展方向。项目是一个比较早的项目里,采用的DSP2407芯片,当时是为了要取代UC3854模拟芯片的控制,主结构采用的是BOOST主电路。

    设计中遇到的问题:1、PI参数的设计,个人觉得KP,KI是设计的难点,参数的选取直接影响着系统的稳定和速度,当时采用的是模拟设计方法,通过模拟的设计的参数转换成数字的参数,通过matlab仿真提示,在后期的调试过程中逐渐改进。

    2、除法的运算,在PFC控制电路中,考虑到系统的稳定,引入了前馈控制,一满足系统在输入电压变化时系统的输入功率的平衡,保证系统的问题,因此加入前馈控制,但是在编写程序的初期就遇到了好多问题,一是程序的除法的运算问题,初期由于程序的编写的比较繁琐以至于出现了炸机现象,后来慢慢通过优化和改进,解决了这一题

    3、采样电路的设计,要保证电路在宽电压范围能正常工作,采样电路的值要合理选取,同时还要保证采样带宽。

    实验结果如下,进攻参考,请勿盗用,呵呵

     

  • 2812串口的接收和发送都有16个字节深度的FIFO,这个FIFO可以启用或者关闭,接收和发送都有5位来指示FIFO现存的字节量。

      同时2812的串口还有通常串口常见的标志位,例如TXRDY和RXRDY等等。

      问题出现了,发现2812是这样的,当你开了串口的FIFO功能时候,TXRDY 和 RXRDY的标志位功能失效了,即,当接收到字符的时候(假如1个),开了FIFO功能,这个时候,RXRDY不指示满(此位不为1),而FIFO的TXFIFST会等于1;发送也一样道理。

      而当你关闭了串口FIFO的时候,接到字符,RXRDY就会置1了,但是TXFIFST没反应了。

      所以,根据以上,假如要用串口的话,用查询的方法,就要根据FIFO是否开启,来查询不同的标志位了(例如接收,开了的话查RXFIFST是否大于等于1,关了的话查RXRDY)!假如用中断的方法的话,就要注意在串口的寄存器里面开哪个中断了,假如开了FIFO,就要开FIFO中的匹配中断;假如关了的话就要开Tx INT ENA等中断位,当然,两边的中断都开也可以的。

     

    看上面,FIFO打开了,接收FIFO里面有一个字节了,但是RXRDY不置位,此时,由于FIFO匹配中断没打开,中断服务程序也不会进入了。

    接收的查询用:while(ScibRegs.SCIFFRX.bit.RXFIFST != 1) { }

    发送的查询用:while (ScibRegs.SCIFFTX.bit.TXFFST != 0) { }

    这里,FIFO关闭了,RXFIFST就不会增了,但是RXRDY置位了,同时,中断也进去了。

    接收的查询用:while(ScibRegs.SCIRXST.bit.RXRDY !=1) { }

    发送的查询用:while (ScibRegs.SCICTL2.bit.TXRDY != 1){ }

     

    看上面,datasheet里面这个表也很清楚了,开FIFO和关FIFO,中断的标志位是不一样的。

     

    这个笔记记在OneNote里面好久,这次正好拿来交流一下,呵呵

  • TMS320F2812烧写经验总结

    1、一般不用你换GEL.LIB文件,用原来的就可以.

    2、换完FLASH的CMD后,不要烧写,看下.MAP文件,主要是看  0X3F 7FF8处有没有烧内容.如果有别烧,改,直到这处没有烧入内容.

       一般网上的都可以用,只要没有在此出烧入内容

    3、如果没有烧入其他的内容,则可以烧了.烧完后,RESET CPU 看是不是到 0X3F FFC0处,如果不是,看 是不是你的MP/MC=0了,并且是不是FLASH启动模式,即所有4个脚都是高(只要第一个脚是高就可以,即 1XXX)

    4、如果RESET CPU 是到 0X3F FFC0处,即可以断电,并且拔掉与板子相连的仿真器接口(注意拔电脑上的USB不好使),然后上电,自动运行.

    注意:其中遇到的问题:

    烧写/时说 初始化RAM,和寻找BOOT.ASM都不用管_

    如果说是 NOT AN execuTivefile ,则在PROJECT_BULIT OPTION_LINK_OUT MODLE _absolute  file

    最重要是可以断电,并且拔掉与板子相连的仿真器接口(注意拔电脑上的USB不好使),然后上电,自动运行.我遇到的是这些,我用以上方法解决了,但不知道为什么,所以大家都说说经验,让新手烧走弯路,少LOCK2812

    2812从内部flash启动的过程

    a)程序硬件复位或者软件复位

     b)判断mp/mc是否为0,微计算机模式(为1,当为微处理器模式时,2812内部的bootrom被禁止,通过zone7从外部调引导程序启动。)

     c)为0则从boot rom启动,否则从外部启动(0x3F FC00)

     d) 到boot rom的0x3F FC00处取出复位向量,跳到boot函数:2812有一块flash地址从0x3F F000-0x3F FFFF在出厂时ti已经固化好了引导程序iniboot:Iniboot函数判断几个GPIO引脚来判断使用哪一种引导模式,比如flash boot模式,检测SPICLKA,SCITXA,GPIO34的电平,当都为高电平时表明是片内flash boot模式,那么initboot执行完后跳转到0x3F 7FF6处)

     e)采集io管脚状态,确定启动模式。2812提供几种启动模式

    SCITXDA(GPIOF4) MDXA(GPIOF12) SPISTEA(GPIOF3) SPICLK(GPIOF2)

     1                       x                 x             x      FLASH启动

     0                       1                 x             x      SPI启动

     0                       0                 1            1       SCI启动

     0                       0                 0            0       PARALLEL启动

    f)根据io状态选择boot方式

    g)如果是flash,程序退出boot函数,跳转到0x3F 7FF6(codestart)

    h)取出跳转指令,跳转到自己的指定地址或者C初始化的入口_C_INT00(0x3F6000)处(DSP281x_CodeStartBranch.asm中)

    i)在C初始化的入口_C_INT00对一些变量,堆栈和寄存器进行必要的设置,该函数在c的库函数内(RTS Library)

    j)进入main函数(0x3F658E)

    2812上电引导过程

    从上电到我们的主函数运行之间这段时间里2812到底做了些什么?2812是怎样引导程序运行的?下面叙述其启动过程。

           在2812中引脚XMP/~MC,当该引脚的为高电平时表示是微处理器模式(microprocessor),为低电平时表示微机算计模式(microcomputer),当为微处理器模式时,2812内部的bootrom背禁止,通过zone7从外部调引导程序启动。2812复位以后,其复位向量是固定的0x3F FFC0,如果为为处理器模式,那么复位后的复位向量指向的外部的地址,即0x3F FFC0是zone7处的地址,若为微机算计模式,那么0x3F FFC0指向的是2812的片内FLASH的地址。下面就以微机算计模式加以说明其过程。

           上电复位后,复位向量是指向片内Flash的0x3F FFC0,2812有一块flash地址从0x3F F000-0x3F FFFF在出厂时已经固化好了引导程序。在0x3F FFC0处是一条跳转指令,跳到iniboot(地址0x3F FB50)函数处执行iniboot代码,该iniboot代码就是ti在dsp出厂时固化在flash中的。Iniboot函数判断几个GPIO引脚来判断使用哪一种引导模式,比如flash boot模式,检测SPICLKA,SCITXA,GPIO34的电平,当都为高电平时表明是片内flash boot模式,那么initboot执行完后跳转到0x3F 7FF6处,此位置刚好在128位(CSM)密码位置之前,你要在0x3F 7FF6处纺织跳转指令,以跳转到你要去的地方,比如是boot loader或应用代码。在0x3F 7FF6 处放置跳转指令的方法如下:

    .sect "codestart"

    code_start:

       .if WD_DISABLE == 1

           LB wd_disable      ;Branch to watchdog disable code

       .else

           LB _c_int00        ;Branch to start of boot.asm in RTS library

       .endif

       .if WD_DISABLE == 1

       .text

    wd_disable:

       SETC OBJMODE      

       EALLOW            

       MOVZ DP, #7029h>>6

       MOV @7029h, #0068h

       EDIS              

       LB _c_int00        

    .endif

    .end

    MEMERY

                           {

                                   Page 0:

                                           ………..

                                   Start:origin = 0x3F 7FF6,length = 0x000002

                                           ………..

                           }

                           SECTIONS

                           {

                                   ……….

                                   Codestart   :> Start  page 0

                                     ……….

                           }

           上面的代码执行后跳到_c_int00处执行,_c_int00执行结束时调用用户的主程序main,则后续就是你自己的程序的执行了。

    TMS320F2812烧写经验总结.doc
  • 基于DSP2407的信号处理系统设计

    下面介绍基于TMS320LF2407DSP的16通道信号处理系统的硬件和软件的设计。

    1.系统硬件设计

    本系统硬件部分采用TMS320LF2407DSP为核心,兼具控制和数字信号处理的功能,其外部由16位AD转换器、外扩存储器、USB100模块、12位DA转换器、8位指示灯、数字光电隔离器等构成,硬件系统框图如下图所示。

                           

    来自前置放大电路的16通道电信号分别经过16位AD采样进入DSP中央处理单元进行数字滤波运算,处理完毕的数据通过USB100模块上传到上位机系统,在调试中可以通过DA转换器在示波器上观察经过数字处理的信号波形。8位指示灯用于调试时观察时钟的精确度。

    2.系统软件设计

    DSP在程序运行过程中,首先上电复位后根据中断向量表程序跳转到主程序入口地址,主程序关中断,对系统进行必要的初始化,对AD转换器和USB100模块进行初始化,并将AD初始化成T4定时中断触发AD转换,启动看门狗,开中断,然后主程序判断AD转换是否完成,如果AD转换没有完成则程序继续等待,如果AD转换完成,读取AD转换的对应通道的数据,调用数字滤波子程序进行数字滤波,将输出结果上传至上位机,然后等待下一个AD转换的数据输入。启动AD转换是通过AD中断服务子程序实现的,在中断服务程序中启动AD转换,转换结束后置位AD转换好标志,告诉主程序读取数据进行数字滤波。该程序的主程序流程图和中断服务程序流程图如下图所示。

    总结:①在硬件结构上利用了TMS320LF2407内部16通道的ADC并片外扩展了USB100模块,使数据采集及传输能力大大增强;②在软件结构上利用TMS320LF2407的C语言开发信号处理系统结构简单、功能可靠,程序可直接烧写到DSP内部FLASH,长时间脱机运行完全正常;③从数字信号处理算法的选择来看,IIR数字滤波器对干扰的抑制效果非常明显,在实验中通过标准正弦波进行测试证明本系统失真度小、信噪比高;④由于采用了价格低廉的TMS320C2000系列的DSP,本系统的研制成本低于采用TI公司其它系列的DSP。

     

  • 基于DSP2407的信号处理系统设计

    下面介绍基于TMS320LF2407DSP的16通道信号处理系统的硬件和软件的设计。

    1.系统硬件设计

    本系统硬件部分采用TMS320LF2407DSP为核心,兼具控制和数字信号处理的功能,其外部由16位AD转换器、外扩存储器、USB100模块、12位DA转换器、8位指示灯、数字光电隔离器等构成,硬件系统框图如下图所示。

                            

    来自前置放大电路的16通道电信号分别经过16位AD采样进入DSP中央处理单元进行数字滤波运算,处理完毕的数据通过USB100模块上传到上位机系统,在调试中可以通过DA转换器在示波器上观察经过数字处理的信号波形。8位指示灯用于调试时观察时钟的精确度。

    2.系统软件设计

    DSP在程序运行过程中,首先上电复位后根据中断向量表程序跳转到主程序入口地址,主程序关中断,对系统进行必要的初始化,对AD转换器和USB100模块进行初始化,并将AD初始化成T4定时中断触发AD转换,启动看门狗,开中断,然后主程序判断AD转换是否完成,如果AD转换没有完成则程序继续等待,如果AD转换完成,读取AD转换的对应通道的数据,调用数字滤波子程序进行数字滤波,将输出结果上传至上位机,然后等待下一个AD转换的数据输入。启动AD转换是通过AD中断服务子程序实现的,在中断服务程序中启动AD转换,转换结束后置位AD转换好标志,告诉主程序读取数据进行数字滤波。该程序的主程序流程图和中断服务程序流程图如下图所示。

    总结:①在硬件结构上利用了TMS320LF2407内部16通道的ADC并片外扩展了USB100模块,使数据采集及传输能力大大增强;②在软件结构上利用TMS320LF2407的C语言开发信号处理系统结构简单、功能可靠,程序可直接烧写到DSP内部FLASH,长时间脱机运行完全正常;③从数字信号处理算法的选择来看,IIR数字滤波器对干扰的抑制效果非常明显,在实验中通过标准正弦波进行测试证明本系统失真度小、信噪比高;④由于采用了价格低廉的TMS320C2000系列的DSP,本系统的研制成本低于采用TI公司其它系列的DSP。

     

  • 一、EPWM有什么模式和功能

    6个EPWM

    包含子模式

    This guide describes the Enhanced Pulse Width Modulator (ePWM) Module. It includes an overview of the module and information about each of the sub-modules:

    •TB----  Time-Base Module

    •CC----  Counter Compare Module

    •AQ----  Action Qualifier Module

    •DB----  Dead-Band Generator Module

    •PC----  PWM Chopper (PC) Module

    •TZ----  Trip Zone Module

    •ET----  Event Trigger Module

    The ePWM peripheral performs a digital to analog (DAC) function, where the duty cycle is equivalent to a DAC analog value; it is sometimes referred to as a Power DAC.

    the ePWM is built up from smaller single channel modules with separatere sources and that can operate together as required to form a system

    一个完整的PWM通道有两个PWM输出组成:EPWMxA   EPWMxB

     

    The ePWM modules are chained together via a clock synchronization scheme that allows them to operate as a single system when required.  -------àECAP  extended capture peripheral modules

     

    每个EPWM支持功能:

    1、专门的带周期和频率控制的16位计数器

    2、两路PWM的输出(A,B)可以被配置为

    – Two independent PWM outputs with single-edge operation

    – Two independent PWM outputs with dual-edge symmetric operation

    –     One independent PWM output with dual-edge asymmetric operation 双边不对称操作??

    3、 Asynchronous override control of PWM signals through software.

    4、Programmable phase-control support for lag or lead operation relative to other ePWM module

    5、Hardware-locked (synchronized) phase relationship on a cycle-by-cycle basis.

    6、Dead-band generation with independent rising and falling edge delay control.

    7、Programmable trip zone allocation of both cycle-by-cycle trip and one-shot trip on fault conditions.

    8、A trip condition can force either high, low, or high-impedance state logic levels at PWM output

    9、All events can trigger both CPU interrupts and ADC start of conversion (SOC) 如何理解

    10、Programmable event prescaling minimizes CPU overhead on interrupts.

    11、PWM chopping by high-frequency carrier signal, useful for pulse transformer gate drives.

  • TI-28346参考设计原理图疑问

     

    最近准备用TI28346做个控制板,从TIcontrolSUITE工具中找到其参考原理图

    路径为ControlSUITE/Devices/Utilities/CC2834x Hardware Developer's Package-DIM100\

    C283XX_BH_CC_V0_17_R1_1

    感觉有几个地方好像有点问题

    2页的boot引导设置部分

    Boot方式的判断,仅仅是通过4GPIO口来判断输入电平,高还是低,为什么要用57.6k2.21k这么精密的电阻而非常规电阻?

     

    3页,系统供电部分

    3.3V和1.2V同时提供,但是1.8V是从3.3V获得的,

    而规格书第119页,三路同时供电没有问题,目前1.8V后于3.3V好像也会有潜在问题,为什么这边没有考虑?

     

     

    5页,ADC部分

    两个ADCBUSY信号直接连在一起

    ADCBUSY信号为高时转换中,低时表示可以读数,这样直接连不会相互影响,还是可以通过CS_N片选其中一个只读一个BUSY,但是ADC的规格书中也没有找到明确指明ADC不选中时BUSY的状态时什么,

    是不是可以用个简单门电路来处理两个BUSY信号,或者为什么不简单点用两个GPIO来判断呢?

     

     

    5页,ADC部分的钳位电路

    TL7726CD规格书中的供电电压是4.5-5.5V之间,这边使用3.3V供电

  • 各位朋友,感谢大家踊跃的分享!上周获奖名单如下:

    优秀分享奖:

    未来的某一天; changhu fang; tang feng1; guang hu; qiuli zhang; xiaole ye; James Zhu; tingyu sun; bo ning; shengming zhou; 小马克

    阳光普照奖:

    Qiang Meng; Guoyun Jin; lulu wang; Hang; anvy178; Chunyan Gao1; Langhua Wu; juan cui; Leer Peng; zilong zhao; peng cui

    恭喜上述获奖的同事们!期待未来更精彩的分享!

    TI物流公司会在未来两天内跟大家联络奖品邮寄事宜。

  • 非常感谢deyisupport对我们学习的支持!多学技术共同发展!!

  • C2000硬件设计总结

    大家分享的多是各种精彩的设计及软件方面的问题,那么我就分享一些关于硬件设计的总结,希望对大家有所帮助。

    1.电源和地的处理

    >>分为模拟电源和数字电源,最好分离供电。

    >>通常采用单个线性稳压器供电,这时仍需将模拟和数字部分分开,之间用电感或铁氧体磁珠连接,以截止噪声和高频成分。

    >>尽量稳定内核电压,内核电压有时会影响工作频率。

    >>所有电源引脚都要正确连接到供电电源。

    >>选择线性稳压器时,应全面考虑整个系统的功率、电流和电压信息,最大输出电流能力要在总电流的2倍以上。

    >>在每个电源引脚上加旁路电容,大小在0.01uF~0.1uF。

    >>对于对电源要求较高的电源输入,如A/D、D/A的电源,可以考虑用不同容值的电容并联进行去耦。

    >>在电源的输入端,应加入容值较大的电解电容。

    >>对于地,同样分为模拟地和数字地,同样需要分开。但要注意二者之间最终要有连接,即单点相连。

    >>对不同的地线层,可采用通孔连接。

    >>不能把铁氧体磁珠和地线连接在一起。因为在高频信号时,铁氧体磁珠产生高阻抗并且产生电势差。

    >>尽量加宽电源、地线宽度,最好是地线比电源线宽,它们的关系是:地线>电源线>信号线。

    >>用大面积铜层作地线用,在印制板上把没被用上的地方都与地相连接作为地线用。

    >>旁路电容器尽量紧靠电源输入引脚,力求最短的电容器引线和最小的瞬态电流回路面积,特别是高频旁路电容不能带引线。

     

    2.时钟电路

    >>在X1和X2引脚之间连接一个晶体和两个电容,利用DSP内部的振荡电路产生时钟信号。

    >>还可以利用封装好的晶体振荡器,直接输入到X1。

    >>如果X2不用,必须将其悬空。

    >>连接的两个电容一般取12pF。

    >>晶体振荡器应放在离X1、X2较近的地方,走线应该尽量短,并且在同一层上,不能跨层。

    >>时钟频率较高时,可以对时钟线进行地线护送。

    >>时钟发送侧串接一个22~220欧左右的阻尼电阻。

    >>采用晶体振荡器时,其电源输入端可以加铁氧体磁珠,以避免对其他电源产生影响。

    >>在晶振或时钟芯片下需敷铜防止干扰。

     

    3.JTAG接口

    >>仿真头与DSP设备间的距离不能大于6英寸。

    >>大于6英寸时,需要加缓冲设备,并加上拉电阻。

    >>在EMU0和EMU1引脚上使用10k欧的上拉电阻。

    >>#TRST引脚使用220-2.2k欧的下拉电阻。

    >>在EMU0、EMU1和#TRST引脚加旁路电容以减少干扰。

    >>对于多个DSP结构,必须用物理结构相同的组件对TMS、TDI、TDO和TCK进行缓冲。

    >>TMS、TDI和TCK要有上拉电阻。

     

    4.ADC

    >>注意将数字电源和模拟电源以及数字地和模拟地分开。

    >>输入模拟信号时,采用一个运算放大器作为驱动器和缓冲器。

    >>注意模拟信号的输入范围。

    >>没有使用的模拟信号输入端要连接到模拟地。

    >>ADC没有使用时,模拟电源也要保持连接。

    >>使用外部参考源时,要选择合适的滤波电容和偏置电阻。

     

    5.高速信号线的处理

    >> DSP与Flash、SRAM之间是主要的高速数字信号线,所以器件之间的距离要尽量近,其连线尽可能短,并且直接连接。

    >>引线弯折越少越好,最好采用全直线,需要转折,可用45度折线或圆弧转折。

    >>元件连接过程中所用的过孔越少越好。

    >>在相邻的两个层,走线的方向务必取为相互垂直。

    >>对特别重要的信号线或局部单元实施地线包围的措施。可在如时钟信号、高速模拟信号等这些不易受到干扰的信号走线的同时在外围加上保护的地线,将要保护的信号线夹在中间。

    >>差分信号要求在同一层上且尽可能的靠近平行走线,差分信号线之间不允许插入任何信号,并要求等长。

    >>把高速信号和其它信号分开,并且把输入和输出端口或连接口分开。

     

    6.其他

    >>不能有悬空数字输入。

    >>时钟信号与I/O信号处于正交位置。

    >>对进入PCB的信号进行滤波,在IC的每一个点引脚处用高频低电感陶瓷电容(14MHz用0.1 mF,超过15MHz用0.01mF)进行去耦。

    >>用多级滤波来衰减多频段电源噪声。

    >> 

     

    以上是我总结的硬件设计中的一些问题,当然总结的不是很全面。

    另外,可能有不足的地方,欢迎指正。。。。

  • 看到奖品是piccolo的两款,让我感觉眼前一亮,嘿嘿。自己现在用到的芯片就是piccolo系列的28035。但是苦于手头没有学习版。自己的最小系统版供电和仿真器连接都很复杂。若能有幸得到这么个奖品将会感觉非常开心啊。我把自己当初设计最小系统的过程给描述出来吧。主要 就是参考官方的文档进行设计的。麻烦能审核下看看如何的哦。

    由于piccolo系列产品众多,我就选择中端的28035作为本次的设计样片。其他的是多了些简单外设,接法大同小异。首先需要了解我们要用到哪些外设,这个就得先考虑我们所针对的应用场合:

    l   要闭环控制不?要,那就需要采样ADC

    l   要闭环的话就得控制开关器件吧?要,那就得用到PWM口吧;

    l   要做硬保护?这个可以有,如果做硬保护,那就要用到IO口,用于故障信号输入与指示,如果不做硬保护,好吧。那就用IO接个LED作故障指示吧。

    l   要通信吧?要,那就要关注下SCI,SPI,CAN,LIN以及其他通信方式;

    l   要外部存储吧?要,那就要用到IIC,IIS

    l   要用外部晶振吗?如果不用就要对晶振入口作相应处理。如果用,好吧,那要考虑是用有源的还是无源的……

    l   要烧写调试吧?要,那就要配置JTAG

    l   等等,还有一些自己需要配置的。在此得先作个大概的考虑。然后再去有针对性的datasheet,将会事半功倍。

    请看图,数据手册第一页。看了之后想下自己需要哪些功能,我已将我需要的功能勾选,应用于一般电力电子变换拓扑。

    再找到数据手册的对应芯片的引脚图,对引脚及其功能复用有大致了解。结合引脚介绍对需要功能与引脚有更深层次的认识

     

    进阶之引脚通览篇

    在引脚信号描述前有这么一段文字,我已把关键字句标出,我们得出以下结论;

    l  复位时,系统默认GPIO口使能,有GPIO的复用引脚是失效的,如PWM引脚;

    l  所有的GPIO口都有若上拉,所以在实际设计时,即便是引脚悬空也不要紧的。

    l  AIO--模拟IO口是没有内部上拉的,这也就是意味着不用的AIO要加上拉或下拉电阻拉为确定电平;

    l  然后NOTE中的供电的说明若用内部VREG提供1.8VIO口电源,那么那些IO口将可能不稳,所以如果用片上电压调整器提供1.8V,关键敏感信号避免用这些IO口,然后若用外部1.8V电源时需注意上电时序,先加1.8V

    l  由此得出如下结论:需重点关注GPIO口、AIO、的未使用配置情况,还需关注供电的问题,这将在后续讨论; 

    JTAG

    由此可得出若用有源晶振需用XCLKIN,若用无源晶振则用X1X2,在使用中选定了一种晶振方式,就需在系统配置的时候将另一种晶振方式的通道在寄存器配置中禁用。重点均如图中标示。在此不一一赘述。本文选用无源晶振,且用不到XCLKOUT,故需注意,该引脚不用时需直接接DGND而不经下拉电阻!

    5.复位引脚

    芯片自带了上电复位、欠压复位、看门狗复位等方式,该引脚乃是有内部若上拉的OD门,本设计中将使用TPS70151为芯片供电,并用其XRS引脚保障2803X的上电时序,作为第二重保障。

    ADC

    根据你的需要选择合适的ADC口作为模拟量的采集输入端,如果害怕因外部电压不稳而带来误差,那么久还需要用到VREF,将输入外部电源到VREF由此消去采集两种的误差。使结果更加精确。有一点要注意的。AIO口!!AIO口是模拟接口。所以如果该口不用的话,需直接拉至AGND模拟地上,如下图

    电源

    电源可以采用单电源或者双电源供电方式,因为DSP内部有调整器,故若采用内部调整器VREG则可只提供3.3V的供电,但有些GPIO引脚会出现不稳的情况。故此处结合70151设计了双输出3.3V&1.8V的电路,具体请关注我后续的基于TPS70151DSP稳压源设计。

    GPIO

    后续就是GPIO及其复用口的配置了,本设计中要用到GPIO口的PWM复用功能,SPI,SCI,以及基本GPIO功能。由于配置简单,故在此一并说明。

    PWM口分为EPWMHRPWM分别是可以实现增强PWM和高精度的PWM,接口后缀分别以BA结尾,如

    SCISPI也是多口复用同一功能,用户可根据端口使用情况进行选择,由于无需外围电路,都是直接连接型的,故在此也不赘述。只需记得不用的GPIO口推荐用下拉电阻下拉至数字地,以使得电平确定。

  • TMS2812 FFT库调用问题

       现在我在调试FFT的时候遇见好多问题,前面都解决掉了,就是FFT转换成幅值mag的时候怎么都不正确。

       我的调用方法如下(刚刚从网上直接修改的网友代码,和我的大同小异):

    #include "DSP281x_Device.h" // DSP281x Headerfile Include File

    #include "DSP281x_Examples.h" // DSP281x Examples Include File

    /* for test fft */

    #include "fft.h"

    // Prototype statements for functions found within this file.

       interrupt void adc_isr(void);

    // Global variables used in this example:

       Uint16 LoopCount;

       Uint16 ConversionCount;

       Uint16 Voltage1[128];

    #define N 128 //FFT Length

    #pragma DATA_SECTION(ipcb, "FFTipcb");

    #pragma DATA_SECTION(mag,"FFTmag");

    RFFT32 fft=RFFT32_128P_DEFAULTS;

    long ipcb[N+2]; //In place computation buffer(这里直接用的RFFT,所以长度是N+2)

    long mag[N/2+1]; //Magnitude buffer

    const long win[N/2]=HAMMING128; //Window coefficient array

    RFFT32_ACQ acq=FFTRACQ_DEFAULTS; //Instance the module

    main()

    {

       int i;

       InitSysCtrl();//初始化cpu

       DINT;//关中断

       InitPieCtrl();//初始化pie寄存器

    /* Initialize acquisition module */

       acq.buffptr=ipcb;

       acq.tempptr=ipcb;

       acq.size=N;

       acq.count=N;

       acq.acqflag=1;

    /* Initialize FFT module */

       fft.ipcbptr=ipcb;

       fft.magptr=mag;// 这里是调用新的存储空间存储幅值

       fft.init(&fft);

       IER = 0x0000;//禁止所有的中断

       IFR = 0x0000;

       InitPieVectTable();//初始化pie中断向量表

    // Interrupts that are used in this example are re-mapped to

    // ISR functions found within this file.

       EALLOW; // This is needed to write to EALLOW protected register

       PieVectTable.ADCINT = &adc_isr;

       EDIS; // This is needed to disable write to EALLOW protected registers

       AdcRegs.ADCTRL1.bit.RESET = 1; // Reset the ADC module

       asm(" RPT #10 || NOP"); // Must wait 12-cycles (worst-case) for ADC reset to take effect

       AdcRegs.ADCTRL3.all = 0x00C8; // first power-up ref and bandgap circuits

       AdcRegs.ADCTRL3.bit.ADCBGRFDN = 0x3; // Power up bandgap/reference circuitry

       AdcRegs.ADCTRL3.bit.ADCPWDN = 1; // Power up rest of ADC

    // Enable ADCINT in PIE

       PieCtrlRegs.PIEIER1.bit.INTx6 = 1;

       IER |= M_INT1; // Enable CPU Interrupt 1

       EINT; // Enable Global interrupt INTM

       ERTM; // Enable Global realtime interrupt DBGM

       LoopCount = 0;

       ConversionCount = 1;

    // Configure ADC

       AdcRegs.ADCMAXCONV.all = 0x0001; // Setup 2 conv's on SEQ1

       AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; // Setup ADCINA3 as 1st SEQ1 conv.

       AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1; // Setup ADCINA2 as 2nd SEQ1 conv.

       AdcRegs.ADCTRL2.bit.EVA_SOC_SEQ1 = 1; // Enable EVASOC to start SEQ1

       AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // Enable SEQ1 interrupt (every EOS)

    // Configure EVA

    // Assumes EVA Clock is already enabled in InitSysCtrl();

       EvaRegs.T2CMPR = 0x0000; // Setup T1 compare value 这里改了 我的采样是6.4k的,用的t2计数器,具体设置应该没错

       EvaRegs.T1PR = ; // Setup period register

       EvaRegs.GPTCONA.bit.T1TOADC = 1; // Enable EVASOC in EVA

       EvaRegs.T1CON.all = 0x1042; // Enable timer 1 compare (upcount mode)

    // Wait for ADC interrupt

       while(1)

       {

           //LoopCount++;

           if (acq.acqflag==0) // If the samples are acquired

           {

               DINT;

               //RFFT32_brev(ipcb,ipcb,N);

               //RFFT32_brev(ipcb,ipcb,N); // Input samples in Real Part

               // 这里不知道为什么 会调用两次(FFT库的调用例子是这样做的)

               fft.win(&fft);

               //RFFT32_brev(ipcb,ipcb,N);

               //RFFT32_brev(ipcb,ipcb,N); // Input samples in Real Part

               // 这里不知道为什么 会调用两次(FFT库的调用例子是这样做的)

               fft.calc(&fft);

               fft.split(&fft);

               fft.mag(&fft);

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

               {

                   mag=sqrt(mag);

                   //这里调用后mag只有在i==0,i==1的时候有比较大的值,其他点都很小,

                   //我用的是50hz的正弦信号,理论上mag[0]应该是DC分量(好像是N倍的关系),

                   //mag[1]应该是50hz的信号幅值(N/2倍的关系),但是实际计算出来不对,

                   //我不送信号和送信号的时候这里的计算值基本上不变,我再调节信号幅值后,

                   //mag[1]是变化的(不稳定),理论上这里出来的值是稳定的,信号的幅值,

                   //实际不是,请网友们帮我看看问题出在哪里。我实在是头大了。

               }

               acq.acqflag=1; // Enable the next acquisition

               EINT;

           }

       }

    }

    interrupt void adc_isr(void)

    {

       Voltage1[ConversionCount] = AdcRegs.ADCRESULT0>>4;

       if(acq.acqflag==1)

       {

           acq.input=((unsigned long)Voltage1[ConversionCount])<<16;

           acq.update(&acq);

       }

    // Reinitialize for next ADC sequence

       AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // Reset SEQ1

       AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // Clear INT SEQ1 bit

       PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE

    }

  • CCS调试出现的问题

       .out文件已经编译成功,也可以下载进去,下载进去后,ccs3.3就感觉比较慢,还没开始调试,就出现这样的错误、

    Trouble Setting Breakpoint with the Action "Terminate GEL_Go()" at 0x3f2fc7:

    Error 0x0000000A/-1150

    Error during: Memory, Break Point,

    JTAG protocol reset.

    Sequence ID: 7

    Error Code: -1150

    Error Class: 0x0000000A

    怀疑由于仿真器引起问题,更换多个仿真器仍未得解,最后通过更换GEL文件,解决问题!

  • 本人原来的任务是用DSP作一个控制系统,所以在学习的过程中积累一些小经验和大家分享。 希望对大家有用DSP2812的CAP捕获测频、QEP测速、MAX7219、步进电机、SCI_VB等等(版权所有转载请注明) 由于学习需要接触DSP。最近用DSP的QEP和CAP功能在学习的过程中遇到了很多问题,更悲剧的是网上的资源不是很全,经常有各种各样的问题,我曾经在好几个论坛里求助但是回应的寥寥无几。所以我将我的学习过程和大家分享,希望对大家有所帮助。  一、恐怕大部分同学都用过单片机,驱动数码管差不多都是锁存器或者三极管,但是这样的方案占用八个以上的IO口,而且程序里还要写循环,无意中发现这个max7219,很好用。附件里有程序,已通过测试,和DSP2812完美结合。注意,7219是SPI通讯,但是DSP的SPI只有一组,我采用GPIO模拟SPI,比SPI还要容易些。 需要注意的是,7219芯片的正负极要加一个小电容0.1uf就行,滤波的,否则芯片会不亮或者乱码。 二、CAP 附件有程序,用T1产生一个1K的脉冲,用CAP6捕获。非常准确。 差不多算是自学,我用里一个多月的时间学习CAP和QEP,大家遇到的主要问题有这些:1,无法进入中断,其实这个不难,主要是DSP的大部分中断有三级,我们经常忘而已。所以建议大家养成习惯,EVAEVB初始化的时候需要中断就将中断标志位清零并使能中断,在PIE里使能对应的中断组并清零中断应答位,在主程序里(习惯而已,大家都这样写我也是,呵呵)打开CPU对应的中断组,最好重新定义一下中断向量的入口,然后在中断程序里面执行中断,程序末尾要记得将中断标志位和中断应答位写1清零。2、可以进入中断但是每次进入中断,但是不知道如何处理数据,这个请大家参考《捕捉中断详解》一文,我忘了原名叫什么里,我待会儿放在附件里。3、可以进入中断,会处理数据但是,每次进入中断的时候FIFO的状态寄存器的值一直是3不是2(是1的时候是不会进入中断的)。注意里,这个问题好多人碰到过,网上很多人留言,但是没人回应解决方案,我也被这个问题困扰了很长时间。原因是——信号源的问题,测量外部信号一定要是比较稳定的方波,上升沿和下降沿如果时间过长就会出现这种情况,请大家注意。 三、QEP 关于QEP,有很多和CAP相似的地方。我就不罗嗦了,我把容易碰到的问题说下。1,被测信号一定要是正交的,我买的传感器不是正交的程序一直错误过了好久才发现。2,和CAP一样被测信号上升沿和下降沿要尽可能陡峭。否则数据会引起很大的跳变。 QEP的程序已经写好了但是由于我的传感器不是正交信号只能过段时间才能调试了。以免误导大家我就不放了,以后更新。

    由于我的编码器坏了,用T1和T2产生九十度相位的脉冲,分别由CAP6和 QEP34测量其频率T1 T2 使T1PWM T2PWM 产生九十度相位的脉冲,T3为CAP6提供时基;T3为QEP34 定时,T4为QEP34提供时基。 将T1PWM或者T2PWM 引脚接到 CAP6 可以测出他们的频率为1000HZ,很准确。 将T1PWM和T2PWM引脚 接到QEP3 QEP4 通过算法测出频率为951HZ 而且有跳动,没有找到原因,调了很长时间。 此程序用了我整整一天的时间,由于水平实在太菜,上面提到的误差和跳动一直没有调出来。如果网友们有好的解决办法请告诉我,多谢!我用DSP测速或者测频率信号老是不能被识别。我是外部传感器产生脉冲经过74HC14然后给DSP,结果CAP要么进不了中断要么每次 进中断的时候状态值为3。郁闷啊,后来我用信号发生器产生方波进过74HC14再给DSP,还是不行。

    步进电机的驱动程序,四相四拍,写的比较简单。如果是初学者的话请注意步进电机的原理,看懂了就好办了。 注意事项: 1,步进电机接线方式,通电顺序要和接线方式对应。 2、注意频率,有好多初学者想让步进电机转动快点减小了每一相的通电周期以期望得到将频率增大的效果,但是,步进电机一般是通过减速装置有减速比的,所以步进电机速度不可能太快。更重要的是如果频率大,导通时间过短,步进电机得不到足够大的转矩就不会转。这就是为什么经常发现步进电机只会震动但是不转的原因。至于最小频率时多少请查看自己步进电机的手册。我的是12V的四相步进电机64/1的转速比。最小频率大概500吧。 3、驱动方式四相四拍和四相八拍大概差不多,八拍的转矩更大,我程序里没写。 还有,我前几次发的程序里有很多参数和程序是没有用的,只是当时为了调试而设置的,请大家注意区别。

    vb程序是附件vb_SCI.rar DSP的程序是 CapSpeed_SCI.rar 最近一直在学习PID,因为涉及到PID参数的整定,需要观察波形,做了个vb的界面和DSP通讯,DSP将读取到的数据用串口发送给PC,vb读取数据并将数据绘制成波形,已经经过检测,效果良好。具体的细节在这里就不多说了,希望大家一起交流、进步。

  • 新手的好资料, 关于仿真器的安装, 谢谢TI 的支持!

    setup.pdf
  • 虽然很多回复都是网上可以下载到的心得代码,还是支持下TI 的活动,倾向于用TI的产品,希望能幸运获奖,谢谢

  • 最近老板让接手一个项目,使用激光和CCD测量微位移。前边有师兄做过这个项目,不过貌似精度上面还需要改进。目前国内还很少有公司生产这种设备,国外的产品又太贵,老板想把它做成能上市的产品。因为师兄的资料都有,就有点基础可以借鉴。这个项目的主体框图如下

    使用了TMS320F2812作为主控芯片,据我一个工作了的师兄说,外面很多公司会在DSP上跑系统,汗颜。。。这个设计里面没跑系统,仅仅把它当做一块能快速处理和运算的单片机用。事件管理器内带计数器用于CCD驱动脉冲计数、ADC模块用于采集光强信息、键盘输入电路用于功能选择、SPI数码管显示模块、SPI DA转换模拟电压输出模块、SCI串口通信模块用于与上位机进行数据通信、数控电位器控制模块用于自适应调节CCD信号强弱。

    这个设计中使用TMS320f2812最主要的功能是进行CCD的算法处理。激光反射后照到的像元被比较器筛选出来,大概是形成一个圆点。DSP要对这部分的像元进行运算处理,以得到真正的那个反射点的像元,大概是这个圆的圆心吧。但我自己在想反射的激光束射在CCD上应该是有点变形的椭圆吧,这个不知道要用什么算法对齐了,值得思考。我自己其实想用TI现在力推的piccolo系列的DSP来取代TMS320F2812,因为以前师兄做这个是为了高速测量,而我现在不需要这么快。piccolo的f28027主频是40-60MHZ,应该足够我的应用。32x32硬件乘法累加器、32位计数器、SPI、SCI也都有,就是IO数量上有点吃紧,得规划一下。f28027的价格比较便宜。

  • 支持啊!我就是说说我在实际工作中遇到的问题,首先先从数据手册说起,我要设计一个基于C28027为核心的交流电机转速控制板,当时看数据手册时,

    1引脚和11引脚标明为 CPU逻辑电源引脚,当时我毫不犹豫的画到电源上,等板子做回来发现,JTAG找不到芯片,老是提示CPU ID匹配,实在是无语啊!以为是XDS100仿真器出问题了,重新买了一个,问题依旧,后来仔细阅读数据手册才发现,这个引脚如果没有外接电源是直接外接1.2uF的电容即可,内部VREG可以产生1.2VCPU用电压。

    这是我的一个小经验

  • TMS320F2812处理器是TI 公司C2000系列处理器中的一款,主频可以达到150Mhz,我目前在项目中就是使用这款处理器。

    该处理器在电机控制等工业控制领域,有着大量的应用。TMS320C28x™ 控制器是 业界第一款 32 位基于 DSP 的控制器,具有板载快闪存储器和高达 150MIPS

    的性能。它将微控制器 (MCU) 综合控制外设和简便易用与 TI 一流的 DSP 技术的处理能力与 C 效率相结合。 在编程工具上,Code Composer Studio™ IDE 提供

    强健、成熟的核心功能与简便易用的配置和图形可视化工具,在开发过程中可以提供很多帮助。我使用的是CCS2.1版,我觉得该版本有的功能还需要改进。CCS

    与MS Visual Studio开发环境很相似,所以上手很快。但是在VS可以在上下文菜单中快速的查看函数、Struct等的定义,在我使用的CCS版本中似乎没有,这使我

    感到很不方便。

            F2812中有大量的外设寄存器, 在具体的应用中,要把这些寄存器根据实际需要进行配置。这也是程序在初始化期间需要做的主要工作,在配置完成后,才可

    以进入正常的流程,即业务逻辑处理阶段。以我的应用为例,F2812主要完成下列工作:2路A/D采样,2路PWM输出,6路GPIO输出。在此基础上,我将进行运算

    处理,实现主要功能。 传统的寄存器访问方式,通过Macro定义实现。在TI提供的头文件中,提供了一种新的方式:bit field 和struct 方式,即位域加结构的方式。

    在这种方式中,定义struct来表示与某个外设相关的一组寄存器,然后由Linker程序负责将寄存器映射到内存中。

          如对于定时器寄存器,定义:

    struct CPUTIMER_REGS

    {

    Uint32 TIM; // Timer counter register

    Uint32 PRD; // Period register

    Uint16 TCR; // Timer control register

    Uint16 rsvd1; // reserved

    Uint16 TPR; // Timer pre-scale low

    Uint16 TPRH; // Timer pre-scale high

    };

    这样,如果DSP内有多个定时器,则可以通过声明多个变量实现对三个定时器寄存器的访问,便于代码复用。

    利用编译器的DATA_SECTION #pragma,为每个变量分配一个数据段。然后,通过在cmd文件,Linker将每个数据段映射为内存中与该外设寄存器相对应的内存地址。

    这时,还不能实现对寄存器,如TIM中的每一位的访问。需要对每个寄存器,为其定义位域,使每一位都可以访问,如定义TCR的位域:

    struct TCR_BITS

    { // bits description

    Uint16 rsvd1:4; // 3:0 reserved

    Uint16 TSS:1; // 4 Timer Start/Stop

    Uint16 TRB:1; // 5 Timer reload

    Uint16 rsvd2:4; // 9:6 reserved

    Uint16 SOFT:1; // 10 Emulation modes

    Uint16 FREE:1; // 11

    Uint16 rsvd3:2; // 12:13 reserved

    Uint16 TIE:1; // 14 Output enable

    Uint16 TIF:1; // 15 Interrupt flag

    };

    然后,定义一个Union,允许该寄存器既可以按bit访问,也可以作为整体访问:

    union TCR_REG

    {

    Uint16 all;

    struct TCR_BITS bit;

    };

    在如此这样对每个寄存器都定义好后,重写struct CPUTIMER_REGS如下:

    struct CPUTIMER_REGS

    {

    union TIM_GROUP TIM; // Timer counter register

    union PRD_GROUP PRD; // Period register

    union TCR_REG TCR; // Timer control register

    Uint16 rsvd1; // reserved

    union TPR_REG TPR; // Timer pre-scale low

    union TPRH_REG TPRH; // Timer pre-scale high

    };

    这时,每个寄存器都可以按bit或作为整体访问了。 这样的方式,对于程序员来说,更容易理解,程序也更容易维护。 这样做的坏处:产生的代码长度稍大一些。 另外,对于有些特殊的寄存器,如WDCR,就没有定义Bit field和Union。 上面讲了这么多,那么我们是否需要将这些寄存器全部自己定义呢?答案是不需要。因为TI公司已经为我们提供了现成的.H文件,为我们做好了这些工作。在编程时,我们只需要搞清楚需要把那个头文件包含进来就行了。

  • F2812内部集成了ADC转换模块。该模块是一个12位、具有流水线结构的模数转换器,内置双采样保持器(S/H),可多路选择16通道输入,快速转换时间运行在

    25 MHz、ADC时钟或12.5 Msps,16个转换结果寄存器可工作于连续自动排序模式或启动/停止模式。在实际使用中,ADC的转换结果误差较大,如果直接将此转

    换结果用于控制回路,必然会降低控制精度。(最大转换误差可以达到9%左右)

    F2812的ADC转换精度较差的主要原因是存在增益误差和失调误差,要提高转换精度就必须对两种误差进行补偿。

    对于ADC模块采取了如下方法对其进行校正:

    选用ADC的任意两个通道(如A3,A4)作为参考输入通道,并分别提供给它们已知的直流参考电压作为输入(RefHigh和RefLow),通过读取相应的结果寄存器

    获取转换值,利用两组输入输出值求得ADC模块的校正增益和校正失调,然后利用这两个值对其他通道的转换数据进行补偿,从而提高了ADC模块转换的准确度。

    实现校准的硬件电路在本文中不作描述,在有关资料中可以查到。

    下面是该算法的C语言实现:

    //首先计算两个通道的参考电压转换后的理想结果

    // A4 = RefHigh = 2.5V ( 2.5*4095/3.0 = 3413 ideal count)

    // A3 = RefLow = 0.5V ( 0.5*4095/3.0 = 683 ideal count)

    #define REF_HIGH_IDEAL_COUNT 3413

    #define REF_LOW_IDEAL_COUNT 683

    #define SAMPLES 63

    //定义所需的各个变量

    Uint16 Avg_RefHighActualCount;

    Uint16 Avg_RefLowActualCount;

     Uint16 CalGain; // Calibration Gain

    Uint16 CalOffset; // Calibration Offset

    Uint16 SampleCount;

    Uint16 RefHighActualCount;

    Uint16 RefLowActualCount;

    //对各个变量进行初始化

    void InitCalib()

    { Avg_RefLowActualCount = 0;

    Avg_RefLowActualCount = 0;

    Avg_RefHighActualCount = 0;

    RefHighActualCount = 0;

    RefLowActualCount = 0;

    CalGain = 0;

    CalOffset = 0;

    SampleCount = 0;

    }

    //获得校准增益和校准失调

    // Algorithm: Calibration formula used is:

    //

    // ch(n) = ADCRESULTn*CalGain - CalOffset

    // n = 0 to 15 channels

    // CalGain = (RefHighIdealCount - RefLowIdealCount)

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

    // (Avg_RefHighActualCount - Avg_RefLowActualCount)

    //

    // CalOffset = Avg_RefLowActualCount*CalGain - RefLowIdealCount

    //

    // A running weighted average is calculated for the reference inputs:

    //

    // Avg_RefHighActualCount = (Avg_RefHighActualCount*SAMPLES + RefHighActualCount) / (SAMPLES+1)

    //

    // Avg_RefLowActualCount = (Avg_RefLowActualCount*SAMPLES + RefLowActualCount) / (SAMPLES+1)

    // void GetCalibParam()

    {

    RefHighActualCount = AdcRegs.ADCRESULT4 >>4;

    RefLowActualCount = AdcRegs.ADCRESULT3 >>4;

    if(SampleCount > SAMPLES)

         SampleCount = SAMPLES;

    Avg_RefHighActualCount = (Avg_RefHighActualCount * SampleCount + RefHighActualCount) / (SampleCount+1);

    Avg_RefLowActualCount = (Avg_RefLowActualCount * SampleCount + RefLowActualCount) / (SampleCount+1);

    CalGain = (REF_HIGH_IDEAL_COUNT - REF_LOW_IDEAL_COUNT) / (Avg_RefHighActualCount - Avg_RefLowActualCount);

    CalOffset = Avg_RefLowActualCount*CalGain - RefLowIdealCount; SampleCount++;

    }

    //在ADC_ISR中,对其他各个通道的结果进行修正:

    interrupt void adc_isr(void)

    {

    GetCalibParam();

    ......

    newResult n= AdcRegs.ADCRESULTn*CalGain - CalOffset;

    ......

    }

    通过上面的代码,配合硬件电路改动,可以大幅实现提高ADC采样的精度,实现更灵敏、更精确的控制。

  • 基于C28346和F28335以DMA方式实现的McBSP

    目前想实现的功能是C28346和F28335之间通过McBSP以DMA的方式进行数据传输:C28346发送一个数组给F28335,F28335接收完成后,将数据发还给C28346.校验无误后执行全数组+1操作,然后重复发送。

    下面是两块芯片的McBSP的参数设置:

    C28346:

    void mcbsp_init_dlb1()

    {     McbspaRegs.SPCR2.all=0x0000;                // Reset FS generator, sample rate generator & transmitter

         McbspaRegs.SPCR1.all=0x0000;                // Reset Receiver, Right justify word

    //    McbspaRegs.SPCR1.bit.DLB = 1;       // Enable DLB mode. Comment out for non-DLB mode.

          McbspaRegs.MFFINT.all=0x0;                        // Disable all interrupts

          McbspaRegs.RCR2.all=0x0000;                        // Single-phase frame, 1 word/frame, No companding(Receive)

          McbspaRegs.RCR1.all=0x0;

          McbspaRegs.XCR2.all=0x0000;                        // Single-phase frame, 1 word/frame, No companding(Transmit)

          McbspaRegs.XCR1.all=0x0;

          McbspaRegs.SRGR2.bit.CLKSM = 1;                // CLKSM=1 (If SCLKME=0, i/p clock to SRG is LSPCLK)

          McbspaRegs.SRGR2.bit.FPER = 31;                // FPER = 32 CLKG periods

          McbspaRegs.SRGR1.bit.FWID = 0;      // Frame Width = 1 CLKG period

          McbspaRegs.SRGR1.bit.CLKGDV = 3;        // CLKG frequency = LSPCLK/(CLKGDV+1)

          McbspaRegs.PCR.bit.FSXM = 1;                // FSX generated internally, FSR derived from an external source

          McbspaRegs.PCR.bit.CLKXM = 1;                // CLKX generated internally, CLKR derived from an external source

       //*************** Initialize McBSP Data Length

         InitMcbspa16bit();

       //************* Enable Sample rate generator

       McbspaRegs.SPCR2.bit.GRST=1; // Enable the sample rate generator

       delay_loop();                // Wait at least 2 SRG clock cycles

       McbspaRegs.SPCR2.bit.XRST=1; // Release TX from Reset

       McbspaRegs.SPCR1.bit.RRST=1; // Release RX from Reset

       McbspaRegs.SPCR2.bit.FRST=1; // Frame Sync Generator reset

    }

    F28335:

    void mcbsp_init_dlb()

    {    McbspaRegs.SPCR2.all=0x0000;                // Reset FS generator, sample rate generator & transmitter

        McbspaRegs.SPCR1.all=0x0000;                // Reset Receiver, Right justify word

    //   McbspaRegs.SPCR1.bit.DLB = 1;       //禁止回送模式

        McbspaRegs.MFFINT.all=0x0;                        // Disable all interrupts

        McbspaRegs.RCR2.all=0x0000;                        // Single-phase frame, 1 word/frame, No companding(Receive)

        McbspaRegs.RCR1.all=0x0;

        McbspaRegs.XCR2.all=0x0000;                        // Single-phase frame, 1 word/frame, No companding(Transmit)

        McbspaRegs.XCR1.all=0x0;

        McbspaRegs.SRGR2.bit.CLKSM = 1;                // CLKSM=1 (If SCLKME=0, i/p clock to SRG is LSPCLK)

        McbspaRegs.SRGR2.bit.FPER = 31;                // FPER = 32 CLKG periods

        McbspaRegs.SRGR1.bit.FWID = 0;      // Frame Width = 1 CLKG period

        McbspaRegs.SRGR1.bit.CLKGDV = 1;        // CLKG frequency = LSPCLK/(CLKGDV+1)

        McbspaRegs.PCR.bit.FSXM = 1;                // FSX generated internally, FSR derived from an external source

        McbspaRegs.PCR.bit.CLKXM = 1;                // CLKX generated internally, CLKR derived from an external source

       //*************** Initialize McBSP Data Length

         InitMcbspa16bit();

       //************* Enable Sample rate generator

       McbspaRegs.SPCR2.bit.GRST=1; // Enable the sample rate generator

       delay_loop();                // Wait at least 2 SRG clock cycles

       McbspaRegs.SPCR2.bit.XRST=1; // Release TX from Reset

       McbspaRegs.SPCR1.bit.RRST=1; // Release RX from Reset

       McbspaRegs.SPCR2.bit.FRST=1; // Frame Sync Generator reset

    }

  • DSP2812程序烧写进FLASH后,无法进入中断的解决办法:

    DSP2812, 工作时钟150MHZ,调试时将程序下载至外扩RAM,正常运行,中断都能进去;调试成功后将程序烧写至内部FLASH,主程序运行正常,主循环里的指示灯一直在闪烁,程序里共三个中断:CPUTIMER0,CAP1,T1周期中断,三个中只有CPUTIMER0正常,但CAP1及T1周期中断子程序进不了.

    解决方法:

    1.仔细对照文档,看烧写过程有没有什么操作不当的地方。

    2.确信烧写完全正确的情况下,调试从flash复制到内部内存后的程序 和 直接load 程序时,与中断有关的寄存器的值什么不同。

    3.调试从flash复制到内部内存后的程序方法:仿真器连上,debug->reset CPU,使CPU处于reset状态,file->load symbols->load symbols only,然后选择out文件,这样只载入符号定义,便于调试,然后按F5开始运行,若提示没有加载程序,不用理会直接运行,这样就会从flash中加载程序。可以通过设置硬件断点于入口地址,这样你就可以单步调试从flash启动之后的程序,看看一切是否和直接load一样。
     
    4.可以把CPUTIMER0关了然后看看能不能进那两个中断,如果可以进说明运行时间不够用了,如果不能进就要查查中断配置了
     
    5.还有可能是因为中断太频繁,而FLASH太慢,把程序搬到RAM就好了
     
     
  • 感谢TI ,先分享之前采用DSP2407设计了一个工控气动对料门,控制大型阀门开关导通原料。

    阀门控制系统是一个典型的位置反馈系统。当系统给定为0V时,电机停在0度的位置,即完全关闭;当为5V的时候,迅速转到90度的位置停下,即完全打开;当输入给定从5V调整为2.5V时,电机能迅速从90度转到45度的位置并停下。本设计的系统总体框图见下图:


      给定信号是通过CAN总线由上位机传出,被本系统DSP中的CAN控制器接收。节气门位置反馈是一个模拟的电压信号,因为TMS320LF2407 DSP自带有模数转换模块,所以反馈信号可以直接接到DSP的一路A/D引脚,当然需给DSP的A/D模块供电,并为转换提供基准参考电压。给定与反馈在DSP中经过一定的算法最终转化为占空比变化的PWM脉宽调制信号输出。为了调试方便,我们需为DSP扩展一个外部程序RAM。另外由于DSP的驱动能力有限,并且其工作电压为3.3V,所以其引脚输出或接收的一些信号包括CAN发送,CAN接收和IO口输出的信号都需经过缓冲和电平转换,才能与TTL的5V信号相接[3]。在本设计中,缓冲和电平转化由74HC245芯片一并完成,该芯片采用3.3V供电。

    CAN总线采用的双绞线,两根线分别为CAN高和CAN低。图中的PCA82C250芯片就是驱动DSP的CAN控制器与物理总线间的接口,它是专用的CAN驱动芯片,提供对总线的差动发送和接收功能。它完成CANH,CANL和CAN发送,CAN接收之间的信号转换。82C250工作电压为5V。CAN总线终端的匹配电阻选用典型值为120欧。为了增强CAN通信的抗干扰能力,在缓冲器和CAN驱动之间,我们设计了光电隔离电路。采用的是高速光隔芯片6N137,输入与输出的供电电压也都采用5V。另外,为了避免电源引起的干扰,CAN通信部分采用单独的DC-DC电源模块供电。

       在一个由CAN组成的分布式系统中,很多节点不断的向CAN总线发送不同的信号。所以我们必须屏蔽掉本系统不需要的信号。在CAN协议中,每一个节点都被分配固定的ID号。当一组信号过来,CAN接收程序首先判断该信号的ID来源,如果是所需要的,则接收。CAN控制器配置具体指令如下:
       LDP    #DP_CANMBX
       SPLK   #0DAFEH, MSGID0H  ;设置邮箱0的控制字及ID; IDE=1,AME=1,AAM=0
       SPLK   #0101H, MSGID0L  ;设置邮箱0所接收节点的ID(低位)
       SPLK   #08H, MSGCTRL0    ;位RTR=0表示数据帧
       SPLK   #0000H, MBX0A      ;接收邮箱0信息初始化
       SPLK   #0000H, MBX0B
       SPLK   #0000H, MBX0C
       SPLK   #0000H, MBX0D
       LDP    #DP_CANCTL
       SPLK   #0480H,MCR         ;正常模式DBO=1,ABO=1,STM=0
       SPLK   #0001H,MDER       ;ME3=1,MBXA发送,ME2=1接收,邮箱2,3使能
       SPLK   #0100H,CAN_IMR    ;邮箱MBX0中断使能,高中断优先级
       SPLK   #0FFFFH,CAN_IFR    ;清CAN模块的全部中断标志
       CLRC   INTM     ;开总中断
       RET       ;返回
       在上面的程序中设置了本系统的CAN控制器只接收ID标志为DAFE0101的节点发来的信息。

    在此谢谢大家指导

  • 如何提高F2812 AD的转换精度

    采用软件补偿,参考文档spra989a。

    程序经常跑飞

    程序没有结尾或不是循环的程序。

    nmi管脚没有上拉。

    在看门狗动作的时候程序会经常跑飞。

    程序编制不当也会引起程序跑飞。

    硬件系统有问题。

    程序访问了非法的地址。

    用示波器观测的时候程序跑飞

    示波器的探头接地不好,探头上的电位可能会比较高,接到信号线上产生干扰会跑飞。

    大程序有时运行异常,但加一两条空指令就正常,是何原因

    由于TMS320C采用了多级的流水线操作,因此流水线冲突是不可避免的,解决办法为在适合的问题插入1到多条NOP指令。

    参考Ti的相关文档了解详细信息

    C语言中如何从指定的地址读写数据

    #define ADDR1 (unsigned int *)0x300000

    #define ADDR2 (unsigned int *)0x300004

    *ADDR1 = 0x05;//write

    x = *ADDR2;//read

    调试TMS320C2000系列的常见问题?

    1)单步可以运行,连续运行时总回0地址: Watchdog没有关,连续运行复位DSP回到0地址。

    2)OUT文件不能load到片内flash中: Flash不是RAM,不能用简单的写指令写入,需要专门的程序写入。CCS和C Source Debugger中的load命令,不能对flash写入。 OUT文件只能load到片内RAM,或片外RAM中。

    3)在flash中如何加入断点: 在flash中可以用单步调试,也可以用硬件断点的方法在flash中加入断点,软件断点是不能加在ROM中的。硬件断点,设置存储器的地址,当访问该地址时产生中断。

    4)中断向量: C2000的中断向量不可重定位,因此中断向量必须放在0地址开始的flash内。在调试系统时,代码放在RAM中,中断向量也必须放在flash内

    DSP系统构成的常用芯片有哪些?

    1)电源: TPS73HD3xx,TPS7333,TPS56100,PT64xx...

    2)Flash: AM29F400,AM29LV400...

    3)SRAM: CY7C1021,CY7C1009,CY7C1049...

    4)FIFO: CY7C425,CY7C42x5...

    5)Dual port: CY7C136,CY7C133,CY7C1342...

    6)SBSRAM: CY7C1329,CY7C1339...

    7)SDRAM: HY57V651620BTC...

    8)CPLD: CY37000系列,CY38000系列,CY39000系列... 9)PCI: PCI2040,CY7C09449...

    10)USB: AN21xx,CY7C68xxx...

    DSP为什么要初始化?

    DSP在RESET后,许多的寄存器的初值一般同用户的要求不一致,例如:等待寄存器,SP,中断定位寄存器等,需要通过初始化程序设置为用户要求的数值。 初始化程序的主要作用:

    1)设置寄存器初值。

    2)建立中断向量表。

    3)外围部件初始化

    如何判断DSP能正常的工作。

    最简单的办法是测量它的clkout脚输出是否正常。

    有源晶振与晶体的区别,应用范围及用法

    1)晶体需要用DSP片内的振荡器,在datasheet上有建议的连接方法。晶体没有电压的问题,可以适应于任何DSP,建议用晶体。

    2)有源晶振不需要DSP的内部振荡器,信号比较稳定。有源晶振用法:一脚悬空,二脚接地,三脚接输出,四脚接电压。

    DSP系统中实现UART功能

    1,C2000系列DSP片内已集成有UART功能;

    2,用McBSP模拟实现UART功能

    3,外部扩展UART器件1)通过SPI总线扩展:MAX3100(Maxim公司)通过8位异步存储器接口扩展PC UART: 单通道;TL16C450/550/750(TI公司); 双通道:TL16C452/552/752(TI公司); 四通道:TL16C454/554/754(TI公司)

    为什么需要电平变换?

    1)DSP系统中难免存在5V/3.3V混合供电现象;

    2)I/O为3.3V供电的DSP,其输入信号电平不允许超过电源电压3.3V;

    3)5V器件输出信号高电平可达4.4V;

    4)长时间超常工作会损坏DSP器件;

    5)输出信号电平一般无需变换

    电平变换的方法

    1,总线收发器(Bus Transceiver):

    常用器件: SN74LVTH245A(8位)、SN74LVTH16245A(16位)

    特点:3.3V供电,需进行方向控制,延迟:3.5ns,驱动:-32/64mA,输入容限:5V

    应用:数据、地址和控制总线的驱动

    2,总线开关(Bus Switch)

    常用器件:SN74CBTD3384(10位)、SN74CBTD16210(20位)

    特点:5V供电,无需方向控制,延迟:0.25ns,驱动能力不增加

    应用:适用于信号方向灵活、且负载单一的应用,如McBSP等外设信号的电平变换

    3,2选1切换器(1 of 2 Multiplexer)

    常用器件:SN74CBT3257(4位)、SN74CBT16292(12位)

    特点:实现2选1,5V供电,无需方向控制,延迟:0.25ns,驱动能力不增加

    应用:适用于多路切换信号、且要进行电平变换的应用,如双路复用的McBSP

    4,CPLD

    3.3V供电,但输入容限为5V,并且延迟较大:>7ns,适用于少量的对延迟要求不高的输入信号

    5,电阻分压

    10KΩ和20KΩ串联分压,5V×20÷(10+20)≈3.3V

    时钟电路选择原则

    1,系统中要求多个不同频率的时钟信号时,首选可编程时钟芯片;

    2,单一时钟信号时,选择晶体时钟电路;

    3,多个同频时钟信号时,选择晶振;

    4,尽量使用DSP片内的PLL,降低片外时钟频率,提高系统的稳定性;

    5,C6000、C5510、C5409A、C5416、C5420、C5421和C5441等DSP片内无振荡电路,不能用晶体时钟电路;

    6,VC5401、VC5402、VC5409和F281x等DSP时钟信号的电平为1.8V,建议采用晶体时钟电路

    一个完整的单DSP应用系统包括那些方面

    DSP芯片:DSPs的核心运算单元

    电源模块:给DSP以及外围元件提供电压和监控的功能模块

    时钟电路:给DSP提供CLK输入;驱动其他需要时钟的元件

    存储器:存储数据和程序(SRAM/SDRAM/SBSRAM/ZBTRAM/FLASH)

    输入输出模块:执行数据的传输(串口/USB/CAN/Ethernet/AD/DA)

    多处理器接口:多CPU协同工作的接口(HPI/PCI/双口RAM)

    如何开始调试一个DSP系统

    先不焊接器件,用万用表量电源和地看是否短路

    先焊电源部分,看电源输出是否正常

    焊晶振和复位电路、调试。焊接DSP并对其进行调试

    加RAM,调试

    加FLASH,调试

    DSPs的异步串口扩展

    LF2407/F2812:片内集成SCI通信接口

    SPI总线扩展:MAX3100

    MCBSP模拟扩展UART接口

    DSP端接口:EMIF(存储扩展接口)

    UART扩展芯片:TL16C750、TL16C752、TL16C754、SC28L91、SC28L92

    DSPs常见音视频扩展

    音频:

    DSP端接口:MCBSP(多通道缓冲串口)MCASP(多通道音频串口)

    编解码芯片:AIC23、AIC13、PCM180X、PCM1851…

    视频:

    DSP端接口:VideoPort(DM64X、Davinci),利用CPLD做扩展视频物理连接口(其他)

    编解码芯片:TVP5150、TVP5154、SAA7111、SAA7113、SAA7121、SAA7105

    DSP系统如何消除信号干扰、静电干扰等问题

    消除干扰:模拟和数字分开,多层板,电容滤波。

    静电干扰:一般情况下,机壳接大地,即能满足要求。特殊情况下,电源输入、数字量输入串接专用的防静电器件。

    如何降低和克服PCB布线对模拟信号失真和串音的影响

    1)模拟信号与模拟信号之间的干扰:布线时模拟信号尽量走粗一些,如果有条件,2个模拟信号之间用地线间隔。(啥意思?)

    2)数字信号对模拟信号的干扰:数字信号尽量远离模拟信号,数字信号不能穿越模拟地。

    我就把我在整个过程中遇到的问题跟大家分享下,希望有帮助大家:

    JTAG接头的设计

    DSP内部有EMU0/EMU1有弱上拉,如果走线过远则需要额外接10K~30K的电阻进行上拉。

  • 基于TMS320LF2407A的PMSM矢量控制电流环的设计心得

    基于TMS320LF2407A的PMSM矢量控制电流环的设计心得.doc
  • wang wang 说:

    TMS320F28335外扩ADC

    由于采样频率的限制,使用28335时,可以用外部扩展接口扩展一个ADC,如采用ADS805,使采样频率可以达到20MHz。通过28335的DMA读取高速AD转换器ADS805的数据,能够快速有效读出数据,降低CPU资源消耗。硬件原理图如附件图示。

    系统的一些说明:
    1. 时钟:AD时钟信号CLK由DSP的ePWM产生。28335工作在150MHz,通过ePWM1A产生占空比为50%且频率约为19MHz(18.75MHz)的时钟作为ADC的采样频率。同时通过EPWM1SOCA产生与AD时钟信号反相的触发源,作为DMA转换的同步信号。19MHz的时钟信号勉强能够满足ADS805时钟信号的特征要求。但是这个信号最好添加驱动芯片以改善波形。 输出使能信号OEn由GPIO6输出得到。这样造成一个问题就是当进行AD转换的时候,AD将始终占用总线,直到AD转换完成释放总线。
    2.程序: Xinf的读时序中的建立时间设为2个CPU时钟,选通时间设为2个CPU时钟,跟踪周期设为1个CPU时钟。 使用DMA1通道读取地址0×200000(Zone7)的内容,存储在数组ADC_Result中。触发源设置为EPWM1的EPWM1SOCA,总线配置为16位传输方式。DMA传输完毕后触发中断,对读取的数据进行处理。
    心得体会:
    1. DMA配置时,需要将BURSTSIZE配置为0,也就是每次传输一个字,因为转换的数据需要实时读取。而且每次只读取一个字的数据。如果此值设置过大,会造成周期性的数据读取错误。而且相邻两点可能产生数据重复现象。
    2. Xinf读取周期配置中,建立时间要大一点,不然会出现意外的数据错误。
    3. 由于没有CPLD支持,ADS805使能信号使用GPIO6输出,这样造成在AD转换期间,Xintf总线会一直占用,直到数据转换完成。

    这位老兄,用我之前写的帖子跑来换奖品不太厚道吧 呵呵