硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1094|回复: 2
收起左侧

【安富莱二代示波器教程】第10章 示波器设计—数字信号处理

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
发表于 2018-7-4 14:26:41 | 显示全部楼层 |阅读模式
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=45785


第10章      示波器设计—数字信号处理

    本章节为大家讲解二代示波器中用到的FFT和FIR。单纯从应用上来说,比较省事,调用API函数即可,从学习的角度来说,需要大家花点精力。
10.1    FFT快速傅里叶变变换
10.2    FIR有限冲击响应滤波器
10.3     总结

10.1  FFT快速傅里叶变换
      二代示波器中做了2048点的浮点FFT。具体实现是采用ARM的DSP库函数arm_rfft_fast_f32。
  1. /*

  2. *********************************************************************************************************

  3. *    函 数 名: DSO1_WaveProcess

  4. *    功能说明: 波形通道1的FFT,FIR,最大值,最小值,平均值,峰峰值,频率和RMS的计算

  5. *    形    参: 无。

  6. *    返 回 值: 无

  7. *********************************************************************************************************

  8. */

  9. void DSO1_WaveProcess(void)

  10. {

  11.      uint16_t  i;

  12.      uint32_t  uiCycle, uiCount = 0;



  13.      /* 省略其它 */

  14.    

  15.      /* 自动触发模式才计算FFT */

  16.      if(TriggerFlag == 0)

  17.      {

  18.          /* 前10种采样率计算FFT */

  19.          if(TimeBaseId < 10)

  20.          {

  21.               /* 执行2048点浮点FFT运算 */

  22.               for(i=0; i<2048; i++)

  23.               {

  24.                    testInput_fft_2048[i] = g_DSO1->usWaveBufTemp[i];

  25.               }

  26.             

  27.               /* 2048点实序列快速FFT, 浮点 */

  28.               arm_rfft_fast_f32(&S, testInput_fft_2048, testOutput_fft_2048, ifftFlag);

  29.             

  30.               /* 求1204点的幅值 */

  31.               arm_cmplx_mag_f32(testOutput_fft_2048, testInput_fft_2048, 1024);

  32.             

  33.               /* 获得最大的幅值和所在的位置 */

  34.               uiCycle = testInput_fft_2048[1];

  35.             

  36.               for(i = 2; i < 1024; i++)

  37.               {

  38.                    if(uiCycle < testInput_fft_2048[i])

  39.                    {

  40.                        uiCycle =testInput_fft_2048[i];

  41.                        uiCount = i;

  42.                    }

  43.               }

  44.             

  45.               /* 估算频率 */

  46.               g_DSO1->uiFreq = uiCount * g_SampleFreqTable[TimeBaseId][0] / 2048;

  47.          }

  48.          /* 省略其它 */

  49.      }

  50.     /* 省略其它 */

  51. }
复制代码
上面的代码中对采集的2048点数据做浮点FFT处理,并求出幅频响应,方便示波器上频谱的展示。同时代码中也做了一个简单的波形频率估计,这个估计仅适合周期性的正弦波,方波。
    (1)对于正弦波而言,它经过FFT后,理想的幅频响应就是一根线,所以根据这个特性,只要找出幅频响应中幅值最大的值即可,它所对应的频率位置就是波形的频率。
    (2)对于方波而言,它经过FFT后,理想的幅频响应就跟手机信号一样(中间有间隔),方波是由无限多个正弦波叠加而成的,其中第一个幅值最高的就是基波,也是方波的频率。
当前提供的方法仅适合估算,要提高精度的话需要对更多的点做FFT,或者采样率正好是波形频率的整数倍,这样可以有效降低频谱泄露,准确率较高。当然,这种方法的操作难度有点大,因为我们不知道波形频率是多少,求得就是波形频率。
        关于FFT的计算,大家可以直接看我们的DSP教程,有详细讲解,务必优先看第25章,对FFT变换结果的物理意义有个认识,然后再看其它章节:http://www.armbbs.cn/forum.php?mod=viewthread&tid=3886


努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-7-4 14:28:58 | 显示全部楼层
10.2 FIR有限冲击响应滤波器
      二代示波器的FIR滤波控制界面如下:

10.1.png
                              
做了一个80阶低通FIR滤波器,分别可以在2Msps采样率,200Ksps采样率和20Ksps采样率下工作。每个采样率下做了7种截止频率。
      FIR滤波在信号处理任务里面被调用:
  1. /*

  2. *********************************************************************************************************

  3. *    函 数 名: DSO1_WaveProcess

  4. *    功能说明: 波形通道1的FFT,FIR,最大值,最小值,平均值,峰峰值,频率和RMS的计算

  5. *    形    参: 无。

  6. *    返 回 值: 无

  7. *********************************************************************************************************

  8. */

  9. void DSO1_WaveProcess(void)

  10. {

  11.      uint16_t  i;

  12.      uint32_t  uiCycle, uiCount = 0;



  13.    

  14.      /* 省略其它 */



  15.      /* 自动触发模式才计算FFT */

  16.      if(TriggerFlag == 0)

  17.      {

  18. /* 省略其它 */



  19.          /* 前10种采样率计算FFT */

  20.          if(TimeBaseId < 10)

  21.          {

  22.               /* 执行650点,80阶Fir滤波器 */

  23.               /* 单通道2Msps */

  24.               if((TimeBaseId == 1)&&(g_DSO1->ucFirFlter_Step100KHz !=0 ))

  25.               {

  26.                    DSO_FirFilter_Step100KHz();

  27.               }

  28.                   

  29.               /* 单通道200Ksps */

  30.               if((TimeBaseId == 4)&&(g_DSO1->ucFirFlter_Step10KHz !=0 ))

  31.               {

  32.                    DSO_FirFilter_Step10KHz();

  33.               }

  34.                   

  35.               /* 单通道20Ksps */

  36.               if((TimeBaseId == 7)&&(g_DSO1->ucFirFlter_Step1KHz !=0 ))

  37.               {

  38.                    DSO_FirFilter_Step1KHz();

  39.               }

  40.          }

  41.      }

  42.      /* 省略其它 */

  43. }
复制代码
根据不同的采样率,分别做了个处理,我们这里以函数DSO_FirFilter_Step100KHz()为例进行说明。这个函数的实现如下:
  1. #define FIR_LENGTH_SAMPLES   650    /* 采样点数 */

  2. #define BLOCK_SIZE           650    /* 调用一次arm_fir_f32处理的采样点个数 */

  3. #define NUM_TAPS             81     /* 滤波器系数个数 */

  4. #define FIR_StateBufSize     BLOCK_SIZE + NUM_TAPS - 1



  5. /*

  6. *********************************************************************************************************

  7. *                                     滤波器系数

  8. *********************************************************************************************************

  9. */

  10. /* 80阶FIR低通滤波器系数 通过fadtool获取系数 Fs = 2Msps, Fc = 100KHz */

  11. const float32_t firCoeffs32LP_100KHz[NUM_TAPS] = {

  12.   -3.126438727e-19f,-0.0002058673272f,-0.0004228431499f,-0.0006468905485f,-0.0008642434841f,

  13.   -0.001048665727f,-0.001161655295f,-0.001156177954f,-0.0009838859551f,-0.0006050768425f,

  14.   8.391786605e-19f,0.0008203662583f,  0.00180617522f, 0.002865221584f, 0.003865677863f,

  15.    0.004645895679f, 0.005031134468f, 0.004856021609f,  0.00399050815f, 0.002366269007f,

  16.   -2.110346192e-18f,-0.002989985514f,-0.006377025973f,-0.009831513278f, -0.01293939352f,

  17.     -0.0152332196f, -0.01623356342f, -0.01549717132f, -0.01266706176f,   -0.007519159f,

  18.   3.381513724e-18f, 0.009749332443f,   0.0213866625f,  0.03438147902f,  0.04804687202f,

  19.     0.06158847734f,  0.07416618615f,  0.08496309072f,  0.09325480461f,  0.09847255051f,

  20.      0.1002533659f,  0.09847255051f,  0.09325480461f,  0.08496309072f,  0.07416618615f,

  21.     0.06158847734f,  0.04804687202f,  0.03438147902f,   0.0213866625f, 0.009749332443f,

  22.   3.381513724e-18f,   -0.007519159f, -0.01266706176f, -0.01549717132f, -0.01623356342f,

  23.     -0.0152332196f, -0.01293939352f,-0.009831513278f,-0.006377025973f,-0.002989985514f,

  24.   -2.110346192e-18f, 0.002366269007f,  0.00399050815f, 0.004856021609f, 0.005031134468f,

  25.    0.004645895679f, 0.003865677863f, 0.002865221584f,  0.00180617522f,0.0008203662583f,

  26.   8.391786605e-19f,-0.0006050768425f,-0.0009838859551f,-0.001156177954f,-0.001161655295f,

  27.   -0.001048665727f,-0.0008642434841f,-0.0006468905485f,-0.0004228431499f,-0.0002058673272f,

  28.   -3.126438727e-19f

  29. };



  30. /* 其它截止频率对应的系数未贴出 */



  31. /*

  32. *********************************************************************************************************

  33. *    函 数 名: DSO_FirFilter_Step100KHz

  34. *    功能说明: FIR滤波器。

  35. *    形    参: 无         

  36. *    返 回 值: 无

  37. *********************************************************************************************************

  38. */

  39. void DSO_FirFilter_Step100KHz(void)

  40. {

  41.      arm_fir_instance_f32 S;

  42.      uint16_t i;

  43.    

  44.      /* 获取要滤波的数值 */

  45.      for(i = 0; i < BLOCK_SIZE; i++)

  46.      {

  47.          FirDataInput[i] =g_DSO1->usWaveBufTemp[i+g_DSO1->sCurTriPos+g_DSO1->sCurTriStep];

  48.      }

  49.    

  50.      /* FIR低通滤波器,截止频率100KHz */

  51.      if(g_DSO1->ucFirFlter_Step100KHz == 1)

  52.      {

  53.          arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&firCoeffs32LP_100KHz[0], &firStateF32[0], BLOCK_SIZE);

  54.      }

  55.      /* FIR低通滤波器,截止频率200KHz */

  56.      else if(g_DSO1->ucFirFlter_Step100KHz == 2)

  57.      {

  58.          arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&firCoeffs32LP_200KHz[0], &firStateF32[0], BLOCK_SIZE);

  59.      }

  60.      /* FIR低通滤波器,截止频率300KHz */

  61.      else if(g_DSO1->ucFirFlter_Step100KHz == 3)

  62.      {

  63.          arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&firCoeffs32LP_300KHz[0], &firStateF32[0], BLOCK_SIZE);

  64.      }

  65.      /* FIR低通滤波器,截止频率400KHz */

  66.      else if(g_DSO1->ucFirFlter_Step100KHz == 4)

  67.      {

  68.          arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&firCoeffs32LP_400KHz[0], &firStateF32[0], BLOCK_SIZE);

  69.      }

  70.      /* FIR低通滤波器,截止频率500KHz */

  71.      else if(g_DSO1->ucFirFlter_Step100KHz == 5)

  72.      {

  73.          arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&firCoeffs32LP_500KHz[0], &firStateF32[0], BLOCK_SIZE);

  74.      }

  75.      /* FIR低通滤波器,截止频率600KHz */

  76.      else if(g_DSO1->ucFirFlter_Step100KHz == 6)

  77.      {

  78.          arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&firCoeffs32LP_600KHz[0], &firStateF32[0], BLOCK_SIZE);

  79.      }

  80.      /* FIR低通滤波器,截止频率700KHz */

  81.      else if(g_DSO1->ucFirFlter_Step100KHz == 7)

  82.      {

  83.          arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&firCoeffs32LP_700KHz[0], &firStateF32[0], BLOCK_SIZE);

  84.      }

  85.    

  86.      /* 80阶FIR滤波 */

  87.      arm_fir_f32(&S, FirDataInput, FirDataOutput, BLOCK_SIZE);

  88.    

  89.      ·

  90.      for(i = 0; i < DSOSCREEN_LENGTH; i++)

  91.      {

  92.          g_DSO1->usWaveBuf[i] =FirDataOutput[i+50];

  93.      }

  94. }
复制代码
上面的代码中有三个重要的地方:
      (1)滤波器系数的生成,使用Matlab的fdatool工具箱即可,详情可以学习我们DSP教程的第37章节,有详细讲解:http://www.armbbs.cn/forum.php?mod=viewthread&tid=3886 。如果初学的话,可以按照教程讲解实际动手生成一次,看看跟代码中的系数是否一致,一致的话,说明已经成功生成。
      (2)FIR滤波器有一个重要的概念就是群延迟,当波形经过FIR滤波器后,输出的波形会有一定的延迟。对于线性相位的FIR,这个群延迟就是一个常数。但是实际应用中这个群延迟是多少呢,关于群延迟的数值,Matlab的fdatool 工具箱会根据用户的配置计算好。比如我们这里设计的80阶FIR低通滤波器的群延迟就是40,反应在实际的采样值上就是滤波后输出数据的第41个才是实际滤波后的波形数据起始点。
程序中为了方便起见,每次都是处理650个数据,直接使用滤波结果的后600个数据。更多关于延迟的知识,看我们DSP教程第37章的37.8小节即可。
      (3)FIR滤波器涉及到的函数arm_fir_init_f32和arm_fir_f32也是在DSP教程第37章进行了讲解。

关于二代示波器的FIR滤波器设计就为大家说这么多,更多这方面的知识需要学习我们的DSP教程。

努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-7-4 14:29:58 | 显示全部楼层
10.3    总结
    如果大家不熟悉FFT和FIR的话,务必要优先学习我们DSP教程的相关章节,磨刀不费砍柴工。有了一定的认识后,再来二代示波器的基础上做实战演练即可。

努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-13 16:32 , Processed in 0.252277 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表