DDS输出频率在特定点错误

2020-01-16 18:35发布

         目前在做一个基于51单片机和CPLD的DDS信号源。单片机是STC的51,CPLD是EPM240。

         基本结构是单片机负责按键输入和显示参数,CPLD负责DDS合成波形输出,最高频率2MHz

        按键输入频率值,由单片机计算出频率字通过SPI发送给CPLD。

         现在碰到的问题是,当设置输出频率的万位数为“7/8/9”时,输出频率就不对,其他情况都对。

        比如频率值为X6-X5-X4-X3-X2-X1-X0,仅当X4取值为“7/8/9”时就出错,60000或1969999时没问题,

        但是70000就输出4464,17000输出104464,117000输出1104464,也就是说除了X4之外高位变化

        都是正确的。更奇葩的是80000时输出14464,90000输出24464,都是按照10000递增,好像也没错。

        也考虑过是不是在转换频率字的过程中,数据类型出错的原因,如果给CPLD发送整数而不是存储计算值的

        变量,输出也是对的。最后附上关键代码,请高手指正!

        /////////////////////////////////////////////////////////////

        #define FREQCONS (4294967296.0/50000000.0)         //频率字计算常数,DDS累加器位宽32位,系统时钟50MHz
        unsigned long BinFreq,  TxsFreq;                                //频率值二进数和转换后的数
        unsigned char NumFreq[7]                                        //用于显示的频率值BCD码数组
        BinFreq = NumFreq[6]*1000000 + NumFreq[5]*100000 + NumFreq[4]*10000 + NumFreq[3]*1000 + NumFreq[2]*100 + NumFreq[1]*10 + NumFreq[0];
        TxsFreq = (((float)(BinFreq))*FREQCONS);

        SendCpld(TxsFreq);                                                //发送频率字给CPLD,万位为7/8/9出错
        //SendCpld(6012954);                                                //直接发送计算好的常数,则输出正确,这里为输出70000的频率字

        Fout = 2^32/50M * 70K = 6012954

        ///////////////////////////////////////////////////////////
void SendCpld(unsigned long parm2)
{       
        unsigned long DataBuf2;
       
        unsigned char i=0;                                //循环变量
       
        /*        初始化接口        */
        F_nLK = 1;                                               
        F_nCS = 1;                                               
        F_SCK = 1;                                               
        F_SDA = 1;       

        DataBuf2 = parm2;
       
        /*        ----------------------------------------------------        */
        F_nCS = 0;                                        //传输开始

        for (i=0; i<32; i++)                            //每组32位频率字
        {
                if (DataBuf2 & 0x80000000)        //判断当前位状态
                        F_SDA = 1;
                else
                        F_SDA = 0;
                F_SCK = 0;                              //产生串行时钟
                F_SCK = 1;
                F_SCK = 0;
                DataBuf2 <<= 1;                      //左移一位,传送下一位
        }

        F_nCS = 1;                                        //传输结束
        /*        ----------------------------------------------------        */
       
        F_nLK = 0;                                        //产生锁存信号
        F_nLK = 1;
}

       
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。