[STM32F0] 单片机ADC采样FFT计算试验

[复制链接]
2736|13
 楼主| yjmwxwx 发表于 2019-6-24 12:56 | 显示全部楼层 |阅读模式
本帖最后由 yjmwxwx 于 2019-6-24 13:13 编辑

去年学了点数字信号处理,我数学一点看不懂,库也不会用,没办法当时写了个FFT的函数,想用ADC采样用FFT计算但是失败了,当时写的那个256点的溢出了,加上第一次接触这东西不会搞,最近一些日子又重新捡起来这阑尾工程,调试了几天终于成功了。

        做了简单电路,两个STM32F030F4P6,一个产生正弦波另一个ADC采样256点用FFT计算得到这个正弦波的幅度。

        0x20000000-0x20000400是实部 0x20000400-0x20000800是虚部, 取出第22个数据的实部和虚部计算出幅度用数码管显示。 由于是Q15定点数,每次保存右移了1位,结果需要乘64, 数码管显示位数有限没乘64,结果只显示了后4位没显示全。

        电路图
dianlutu.png




实物图

IMG_20190624_103643.jpg

IMG_20190624_103343.jpg


下图上把单片机数据输入到电脑上软件计算的,用来和单片机计算的比对,第22个实部是-156265.198,虚部是-157711.28

截图_2019-06-24_11-26-25.png


截图_2019-06-22_22-54-39.png


单片机计算的实部,第22个是0XFFFFF675,十进制2443乘64=156352。地址是0X20000058
实部.png

单片机计算的虚部,第22个是0XFFFFF65F十进制是2465乘64=157760。 地址是0X20000458
虚部.png



结果和电脑上的差不太多,电脑上软件可能是浮点数,我这个是Q15定点数的。




ADC采集的波形,采样率1M 。
截图_2019-06-24_12-02-01.png



示波器波形
IMG_20190624_104058.jpg

IMG_20190624_104051.jpg



SPWM单片机程序
dingshiqispwm.tar.gz (5.99 KB, 下载次数: 17)

ADC——FFT单片机程序
adcfft1.tar.gz (28.48 KB, 下载次数: 38)


视频地址

https://v.youku.com/v_show/id_XNDI0MDcyMjcyMA==.html?spm=a2h0j.11185381.listitem_page1.5~A

我说数码管怎么显示的不对,内存里面是对的,刚才看代码,发现滤波器多右移了2位。。。
表比较长,只贴关键部分。

  1. _jisuanfudu:        [url=home.php?mod=space&uid=72445]@[/url] 计算幅度
  2.                 [url=home.php?mod=space&uid=72445]@[/url] 入r0= 实部,r1= 虚部
  3.                 @ 出r0 = 幅度
  4.                 @ Mag ~=Alpha * max(|I|, |Q|) + Beta * min(|I|, |Q|)
  5.                 @ Alpha * Max + Beta * Min
  6.         push {r1-r3,lr}
  7.         movs r0, r0
  8.         bpl _shibubushifushu
  9.         mvns r0, r0                                @ 是负数转成正数
  10.         adds r0, r0, # 1        
  11. _shibubushifushu:                                @ 实部不是负数
  12.         movs r1, r1
  13.         bpl _xububushifushu
  14.         mvns r1, r1                                @ 是负数转成正数
  15.         adds r1, r1, # 1
  16. _xububushifushu:                                @ 虚部不是负数
  17.         cmp r0, # 0
  18.         bne _panduanxubushibushi0               
  19.         mov r0, r1                                
  20.         pop {r1-r3,pc}
  21. _panduanxubushibushi0:        
  22.         cmp r1, # 0
  23.         bne _jisuanfudu1
  24.         pop {r1-r3,pc}
  25. _jisuanfudu1:
  26.         ldr r2, = 31066                @ Alpha q15 0.948059448969
  27.         ldr r3, = 12867                @ Beta q15 0.392699081699
  28.         cmp r1, r0
  29.         bhi _alpha_min_beta_max
  30. _alpha_max_beta_min:
  31.         muls r0, r0, r2
  32.         muls r1, r1, r3
  33.         asrs r0, r0, # 15
  34.         asrs r1, r1, # 15
  35.         adds r0, r0, r1
  36.         movs r1, # 1
  37.         pop {r1-r3,pc}
  38. _alpha_min_beta_max:
  39.         muls r0, r0, r3
  40.         muls r1, r1, r2
  41.         asrs r0, r0, # 15
  42.         asrs r1, r1, # 15
  43.         adds r0, r0, r1
  44.         movs r1, # 0
  45.         pop {r1-r3,pc}

  46. _lvboqi:
  47.                         @滤波器
  48.                         @R0=地址,R1=长度,r2=表指针地址,r3=ADC数值
  49.                         @出R0=结果
  50.         push {r1-r7,lr}        
  51.         ldr r5, [r2]                @读出表指针
  52.         lsls r6, r1, # 1        
  53.         strh r3, [r0, r5]        @数值写到滤波器缓冲区
  54.         adds r5, r5, # 2
  55.         cmp r5, r6
  56.         bne _lvboqimeidaohuanchongquding
  57.         movs r5, # 0
  58. _lvboqimeidaohuanchongquding:
  59.         str r5, [r2]
  60.         movs r7, # 0
  61. _lvboqixunhuan:
  62.         cmp r5, r6
  63.         bne _lvbozonghe
  64.         movs r5, # 0
  65. _lvbozonghe:
  66.         ldrh r4, [r0, r5]
  67.         adds r5, r5, # 2
  68.         adds r7, r7, r4
  69.         subs r1, r1, # 1
  70.         bne _lvboqixunhuan
  71.         asrs r0, r7, # 10        @修改
  72.         pop {r1-r7,pc}

  73.         
  74. _fftjisuan:
  75.                                 @ 入口 R0=数据地址
  76.                                 @ 输出实部=0X20000000-0X20000400
  77.                                 @ 输出虚部=0X20000400-0X20000800
  78.                                 @ 结果左移6位(乘64)
  79.         push {r0-r7,lr}
  80. _fft1:
  81.         ldr r1, = 0x20000000       @ 输出地址
  82.         movs r2, # 128             @ 蝴蝶数量
  83.         ldr r3, = hudieweifanzhuan @ 蝴蝶位反转表
  84. _fft1xunhuan:
  85.         ldr r6, [r3]               @ 取出位反转表里的地一个数据
  86.         ldr r7, [r3, # 0x04]       @ 取出第二个
  87.         ldr r6, [r0, r6]           @ 根据位反转表找到对应的输入数据  
  88.         ldr r7, [r0, r7]           @ 第二个
  89.         adds r4, r6, r7            @ 求出蝴蝶上
  90.         subs r5, r6, r7            @ 求出蝴蝶下
  91.         str r4, [r1]
  92.         str r5, [r1, # 0x04]       @ 把反过来的顺序排列
  93.         adds r1, r1, # 0x08        @ 输出的地址自增
  94.         adds r3, r3, # 0x08        @ 反转表自增
  95.         subs r2, r2, # 1           @ 蝴蝶数减1
  96.         bne _fft1xunhuan           @ 蝴蝶数不到

  97. _fft2:
  98.         ldr r0, = 0x20000000       @ 实部输出地址0x20000000
  99.         movs r4, # 1               
  100.         lsls r4, r4, # 10         
  101.         adds r4, r4, r0            @ 虚部输出地址 0x20000400
  102.         mov r8, r4                 @ 实部和虚部中间
  103. _fft2xunhuan:
  104.         ldr r4, [r0]               @ 取出数据0
  105.         ldr r5, [r0, # 0x08]       @ 取出数据2
  106.         ldr r6, [r0, # 0x04]       @ 取出数据1
  107.         ldr r7, [r0, # 0x0c]       @ 取出数据3
  108.         adds r1, r4, r5            @ 计算蝴蝶上
  109.         subs r2, r4, r5            @ 计算蝴蝶下
  110.         mov r3, r6                @ 0 r 蝴蝶上实部
  111.         movs r4, # 0
  112.         subs r4, r4, r7                @ 0i 蝴蝶上虚部
  113.         mov r5, r6                @ 3r 蝴蝶下实部
  114.         mov r6, r7                @ 3i 蝴蝶下虚部
  115.         movs r7, # 1
  116.         lsls r7, r7, # 10       @ 内存实部和虚部中间
  117.         adds r7, r7, r0         @ R7等于虚部首地址  
  118.         str r1, [r0]            @ 蝴蝶上保存实部
  119.         str r2, [r0, # 0x08]    @ 蝴蝶下实部
  120.         str r3, [r0, # 0x04]    @ 第二组蝴蝶上实部
  121.         str r4, [r7, # 0x04]    @ 第二组蝴蝶上虚部
  122.         str r5, [r0, # 0x0c]        @ 第二组蝴蝶下实部
  123.         str r6, [r7, # 0x0c]    @ 第二组下虚部
  124.         adds r0, r0, # 0x10     @ 蝴蝶组自增
  125.         cmp r0, r8     
  126.         bne _fft2xunhuan        @ 地址不到循环
  127. _fft3:
  128.         ldr r6, = xuanzhuanyinzi       @ 旋转因子自增变量
  129.         ldr r2, = fft3xuanzhuanyinzi   @ 旋转因子第三步的表
  130.         ldr r0, = 0x20000000           @ 实部输出地址
  131.         str r2, [r6]                   @ 旋转因子表首地址写到变量
  132.         movs r1, # 1
  133.         lsls r1, r1, # 10            
  134.         adds r1, r1, r0                @ 虚部输出地址
  135.         mov r8, r1                       @ R8虚部地址自增变量
  136.         mov r9, r0                     @ R9实部地址自增变量
  137.         mov r10, r2                       @ 旋转因子地址写到R10
  138.         movs r5, # 0x10                       @ 两组蝴蝶的距离        
  139.         mov r11, r5                    @ 写到R11
  140.         movs r5, # 4                   @ 旋转因子数量
  141.         mov r12, r5                       @ 旋转因子数量写到R12
  142.         bl _fftg

  143. _fft4:
  144.         ldr r6, = xuanzhuanyinzi        @ 旋转因子自增变量
  145.         ldr r2, = fft4xuanzhuanyinzi        @ 旋转因子第四步表
  146.         ldr r0, = 0x20000000                @ 实部地址
  147.         str r2, [r6]                        @ 第四步旋转因子表写到自增变量
  148.         movs r1, # 1
  149.         lsls r1, r1, # 10
  150.         adds r1, r1, r0                        @ r1 = 虚部地址
  151.         mov r8, r1                        @
  152.         mov r9, r0
  153.         mov r10, r2
  154.         movs r5, # 0x20
  155.         mov r11, r5
  156.         movs r5, # 8
  157.         mov r12, r5
  158.         bl _fftg


  159. _fft5:
  160.         ldr r6, = xuanzhuanyinzi
  161.         ldr r2, = fft5xuanzhuanyinzi
  162.         ldr r0, = 0x20000000
  163.         str r2, [r6]
  164.         movs r1, # 1
  165.         lsls r1, r1, # 10
  166.         adds r1, r1, r0
  167.         mov r8, r1
  168.         mov r9, r0
  169.         mov r10, r2
  170.         movs r5, # 0x40
  171.         mov r11, r5
  172.         movs r5, # 16
  173.         mov r12, r5
  174.         bl _fftg

  175. _fft6:
  176.         ldr r6, = xuanzhuanyinzi
  177.         ldr r2, = fft6xuanzhuanyinzi
  178.         ldr r0, = 0x20000000
  179.         str r2, [r6]
  180.         movs r1, # 1
  181.         lsls r1, r1, # 10
  182.         adds r1, r1, r0
  183.         mov r8, r1
  184.         mov r9, r0
  185.         mov r10, r2
  186.         movs r5, # 0x80
  187.         mov r11, r5
  188.         movs r5, # 32
  189.         mov r12, r5
  190.         bl _fftg
  191. _fft7:
  192.         ldr r6, = xuanzhuanyinzi
  193.         ldr r2, = fft7xuanzhuanyinzi
  194.         ldr r0, = 0x20000000
  195.         str r2, [r6]
  196.         movs r1, # 1
  197.         lsls r1, r1, # 10
  198.         adds r1, r1, r0
  199.         mov r8, r1
  200.         mov r9, r0
  201.         mov r10, r2
  202.         movs r5, # 1
  203.         lsls r5, r5, # 8
  204.         mov r11, r5
  205.         movs r5, # 64
  206.         mov r12, r5
  207.         bl _fftg

  208. _fft8:
  209.         ldr r6, = xuanzhuanyinzi
  210.         ldr r2, = fft8xuanzhuanyinzi
  211.         ldr r0, = 0x20000000
  212.         str r2, [r6]
  213.         movs r1, # 1
  214.         lsls r1, r1, # 10
  215.         adds r1, r1, r0
  216.         mov r8, r1
  217.         mov r9, r0
  218.         mov r10, r2
  219.         movs r5, # 1
  220.         lsls r5, r5, # 9
  221.         mov r11, r5
  222.         movs r5, # 128
  223.         mov r12, r5
  224.         bl _fftg
  225.         pop {r0-r7,pc}
  226. _fftg:
  227.         push {lr}                @ LR保存到堆栈
  228.         movs r4, # 0
  229.         mov lr, r4
  230. _fftxunhuan:
  231.         mov r0, r9                @ R0实部地址自增变量地址
  232.         mov r1, r8                @ R1虚部地址自增变量地址        
  233.         mov r2, r10                @ 旋转因子表地址地址
  234.         mov r3, r11                @ 两组蝴蝶的距离
  235.         ldr r4, [r0]                @ r4=蝴蝶上实部
  236.         ldr r5, [r1]                @ r5=蝴蝶上虚部
  237.         ldr r6, [r0, r3]        @ r6=蝴蝶下实部
  238.         ldr r7, [r1, r3]        @ r7=蝴蝶下虚部
  239.         ldr r3, [r2]                @ SR
  240.         ldr r2, [r2, # 0x04]        @ SI
  241.         push {r4,r5}                @ R4 R5保存到堆栈
  242.                                 @ (a+bi)(c+di)=(ac-bd)+(ad+bc)i
  243.         mov r4, r6                @ r4=蝴蝶下实部
  244.         muls r4, r4, r3                @ 乘旋转因子        ac
  245.         mov r5, r7                @ R5=蝴蝶下虚部
  246.         muls r5, r5, r2                @ 乘旋转因子        bd
  247.         subs r4, r4, r5                @ ac-bd
  248.         asrs r4, r4, # 15        @ 截断Q15
  249.         mov r5, r6
  250.         muls r5, r5, r2                @ ad
  251.         muls r7, r7, r3                @ bc
  252.         adds r7, r7, r5         @ ad+bc
  253.         asrs r7, r7, # 15        @ 截断Q15
  254.         pop {r2,r5}                @ R2= 蝴蝶上实部
  255.                                 @ r5= 蝴蝶上虚部
  256.         adds r3, r2, r4            @ 上实部加下实部=结果上实部
  257.         subs r2, r2, r4            @ 下实部减上实部=结果下实部
  258.         adds r4, r5, r7                @ 上虚部加下虚部=结果上虚部
  259.         subs r5, r5, r7                @ 上虚部减下虚部=结果下虚部
  260.         mov r6, r11                @ r6=蝴蝶距离
  261.         asrs r3, r3, # 1        @ 右移一位防止溢出
  262.         asrs r4, r4, # 1        @ 右移一位防止溢出
  263.         asrs r2, r2, # 1        @ 右移一位防止溢出
  264.         asrs r5, r5, # 1        @ 右移一位防止溢出
  265.         str r3, [r0]                @ 保存上实部
  266.         str r4, [r1]                @ 保存上虚部
  267.         str r2, [r0, r6]        @ 保存下实部
  268.         str r5, [r1, r6]        @ 保存下虚部
  269.         adds r0, r0, # 0x04        @ 实部地址加4
  270.         adds r1, r1, # 0x04        @ 虚部地址加4
  271.         mov r9, r0                @ r9=当前实部地址
  272.         mov r8, r1                @ R8=当前虚部地址
  273.         mov r2, r10                @ r2= 当前旋转因子地址
  274.         adds r2, r2, # 0x08        @ R2 = 旋转因子地址加8
  275.         mov r10, r2             @ 保存回去
  276.         mov r4, lr                @ 一个蝴蝶旋转因子变量
  277.         adds r4, r4, # 1        @ 自增
  278.         mov lr, r4                 @ 保存回去
  279.         mov r7, r12             @ 取出旋转因子总数量
  280.         cmp r4, r7              @ 到没到数量
  281.         bne _fftxunhuan         @ 没到继续循环
  282.         movs  r4, # 0                @ 到了R4=0
  283.         mov lr, r4                @ 一个蝴蝶旋转因子变量清0
  284.         ldr r6, = xuanzhuanyinzi @ R6=旋转因子自增变量地址        
  285.         ldr r5, = 0x20000400         @ R5=虚部地址
  286.         ldr r6, [r6]                 @ 取出旋转因子自增变量
  287.         mov r7, r11                @ R7= 蝴蝶距离
  288.         mov r10, r6              @ R10 = 旋转因子自增变量
  289.         adds r0, r0, r7                @ 实部地址加蝴蝶距离
  290.         adds r1, r1, r7                @ 虚部地址加蝴蝶距离
  291.         mov r9, r0                @ R9等于当前实部地址
  292.         mov r8, r1                @ R8等于当前虚部地址
  293.         cmp r0, r5                @ 实部到没到虚部边界
  294.         bne _fftxunhuan                @ 没到循环计算
  295.         pop {pc}                @ 返回
  296.         .ltorg                        @ 文字池


 楼主| yjmwxwx 发表于 2019-6-24 13:16 | 显示全部楼层
本帖最后由 yjmwxwx 于 2019-6-24 18:06 编辑

256点,滤波器里面右移了10位忘记修改,下面的改过来了。

软件计算的单次,数码管显示的是256次计算结果的平均 mpv-shot0002.jpg

这次对了

刚才传错了,重新传一个。
adcfft2.tar.gz (29.07 KB, 下载次数: 31)

598330983 发表于 2019-6-24 19:56 | 显示全部楼层
汇编做,厉害。

评论

语言都一样的,只要知道怎么算就容易写了。  发表于 2019-6-26 10:23
lgqsyw 发表于 2019-6-25 20:50 | 显示全部楼层
老哥你敢不用汇编搞一个吗

评论

程序不复杂,就是加法和乘法,C没怎么用不熟练  发表于 2019-6-26 10:25
蝴蝶泉2018 发表于 2019-6-26 10:04 | 显示全部楼层
做实验嘛,换个F1或者F4的芯片也不贵嘛。毕竟将来稍微复杂的程序都是C语言的,还要考虑架构,操作系统等问题

评论

我是种地的农民搞这个就是业余爱好,没那么多钱砸,只能用便宜的片子。  发表于 2019-6-26 10:26
 楼主| yjmwxwx 发表于 2019-6-26 12:39 | 显示全部楼层


测试下时间,STM32F030F4P6 48M时钟,做256点 radix-2  Q15定点数  FFT  在计算前打开SYSTICK定时器,重载值0xffffff,计算完读出0XE000ED18数据到R1=0xfed720

截图_2019-06-26_12-34-33.png

截图_2019-06-26_12-29-41.png

不知道这个怎么算时间?

不知道官方库要多长时间?
截图_2019-06-25_07-07-37.png



数码小叶 发表于 2019-6-27 16:47 | 显示全部楼层
采样率1M,采集后大量的数据怎么处理的。。。

评论

@yjmwxwx :我还以为是一直采  发表于 2019-6-27 22:16
@yjmwxwx :计算完了再开DMA,再采256个  发表于 2019-6-27 20:03
不是一直采,就采256个  发表于 2019-6-27 19:58
yediezeus 发表于 2019-6-28 08:54 | 显示全部楼层
您需要登录后才可以回帖 登录 | 注册

本版积分规则

123

主题

2971

帖子

54

粉丝
快速回复 在线客服 返回列表 返回顶部