打印
[应用相关]

STM32关于AD采样迟延产生的误差分析(转载)

[复制链接]
1635|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
heimaojingzhang|  楼主 | 2018-12-5 12:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

  近日和队友做了一个频谱分析仪。采用超外差原理,利用AD9851扫频输出1~30MHZ的频率(幅度经测试在15MHZ左右达到740mV,即幅度先上升后下降),与输入信号进行混频后(混频器采用AD835),出来的信号经过低通,再送到AD811+AD603进行放大,最后送入AD637进行真有效值转换,转换后将有效值送到STM32F103进行AD采集。

       但在计算频率的过程中发现一个奇怪的现象,第一次计算出的频率值是正确的,但以后每一次总比正确值高10KHZ,从程序上说即往后推迟了一个点。为什么会这样呢?


沙发
heimaojingzhang|  楼主 | 2018-12-5 12:42 | 只看该作者

  先来看看AD的配置函数中启动AD的两个函数:(以软件触发为例)

(1)ADC_Cmd(ADC1, ENABLE);和

(2)ADC_ExternalTrigConvCmd(ADC1, ENABLE);

第一个函数控制的是ADC-<CR2的第0位:ADON(开关AD转换位)

这里要注意的是,AD上电后到转换需要有一个迟延,笔者写这篇**正是要讨论这个迟延带来的的误差!

当第一次设置ADON位时,相当于给ADC上电,但这是并不会转换数据,而是要等待一个时间。起初笔者在初始化时将ADON置位,但并没有立即开启软件触发,而是等到发送一个频率后再开启软件触发,但是我在这个时侯同时也设置了ADON,程序如下:


  for (fre=start,i=0; fre<=end; fre+=step,i++)

       {

       #ifdef SERIAL_LOAD

              DDS_SerialSendData(fre);

       #else

              DDS_SendData(fre);

       #endif

              OSTimeDlyHMSM(0,0,0,7);           

              ADC_Cmd(ADC1, ENABLE);

              ADC_SoftwareStartConvCmd(ADC1, ENABLE);

              while(!ADC_DMA_Flag);        

              if (ADC_DMA_Flag==1)         

              {

                     ADC_DMA_Flag = 0;

              Fre_Amplitude=Filter_Average(ADC_FreAmplitude,NUM_OF_SAMPLE);

              }

       }


使用特权

评论回复
板凳
heimaojingzhang|  楼主 | 2018-12-5 12:42 | 只看该作者

关闭AD在DMA中断完成。程序的设计思路如下:发送一个频率值à延迟一个时间à启动ADà等待AD采集完毕à对采集的数据进行均值滤波à存储滤波后的幅值à发送下一个频率值à重复上述步骤知道扫频完毕。

问题正如一开始所描述的那样,只有上电的时候第一次采样得到的频率值是正确的,以后都比正确值要多10KHZ,表现在程序上就是往后移了一个点。

分析:由于在DMA中断中不仅关闭了软件触发,而且还清零了ADON位,就相当于给ADC断了电,这样在下一轮频率扫描的时,发送第一个频率值后置位ADON相当于给AD上电,但由于迟延,并不会进行数据转换,这样就解释了为什么上电的时候(因为初始化置位了ADON,即ADC上电了)数据是正确的,而以后则推迟一个频点!

后更改如下:

       for (fre=start,i=0; fre<=end; fre+=step,i++)

       {

       #ifdef SERIAL_LOAD

              DDS_SerialSendData(fre);

       #else

              DDS_SendData(fre);

       #endif

              OSTimeDlyHMSM(0,0,0,7);           

              //ADC_Cmd(ADC1, ENABLE);

              ADC_SoftwareStartConvCmd(ADC1, ENABLE);

              while(!ADC_DMA_Flag);        

              if (ADC_DMA_Flag==1)         

              {

                     ADC_DMA_Flag = 0;

               Fre_Amplitude=Filter_Average(ADC_FreAmplitude,NUM_OF_SAMPLE);

              }

       }

同时将中断中只关闭软件触发,而不清零ADON位。

这里还有一点要注意,发送频点到开启软件触发AD采样的延时应该为多少?起初我设置了OSTimeDlyHMSM(0,0,0,1);即1ms。但采样回来的数据不正确,后来经过调试,改成延时7ms即:OSTimeDlyHMSM(0,0,0,7);这样数据就正确了。这里主要考虑整个系统的响应时间,即从AD9851发送频率,经过混频、滤波、放大再到有效值检波的整个时间。当然如果是7ms的话,从1MHZ以10KHZ步进扫到30MHZ就需要7ms*2901=20307ms=20.307S!!这个时间是比较长的。暂时没有想到什么办法解决。


使用特权

评论回复
地板
晓伍| | 2018-12-6 12:57 | 只看该作者
好帖子 经验啊

使用特权

评论回复
5
heimaojingzhang|  楼主 | 2018-12-12 13:21 | 只看该作者

感谢您的肯定啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

85

主题

4142

帖子

4

粉丝