打印
[STM32F0]

单片机ADC采样FFT计算试验

[复制链接]
2091|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位没显示全。

        电路图





实物图






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







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


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




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




ADC采集的波形,采样率1M 。




示波器波形






SPWM单片机程序
dingshiqispwm.tar.gz (5.99 KB)

ADC——FFT单片机程序
adcfft1.tar.gz (28.48 KB)


视频地址

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

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

_jisuanfudu:        [url=home.php?mod=space&uid=72445]@[/url] 计算幅度
                [url=home.php?mod=space&uid=72445]@[/url] 入r0= 实部,r1= 虚部
                @ 出r0 = 幅度
                @ Mag ~=Alpha * max(|I|, |Q|) + Beta * min(|I|, |Q|)
                @ Alpha * Max + Beta * Min
        push {r1-r3,lr}
        movs r0, r0
        bpl _shibubushifushu
        mvns r0, r0                                @ 是负数转成正数
        adds r0, r0, # 1        
_shibubushifushu:                                @ 实部不是负数
        movs r1, r1
        bpl _xububushifushu
        mvns r1, r1                                @ 是负数转成正数
        adds r1, r1, # 1
_xububushifushu:                                @ 虚部不是负数
        cmp r0, # 0
        bne _panduanxubushibushi0               
        mov r0, r1                                
        pop {r1-r3,pc}
_panduanxubushibushi0:        
        cmp r1, # 0
        bne _jisuanfudu1
        pop {r1-r3,pc}
_jisuanfudu1:
        ldr r2, = 31066                @ Alpha q15 0.948059448969
        ldr r3, = 12867                @ Beta q15 0.392699081699
        cmp r1, r0
        bhi _alpha_min_beta_max
_alpha_max_beta_min:
        muls r0, r0, r2
        muls r1, r1, r3
        asrs r0, r0, # 15
        asrs r1, r1, # 15
        adds r0, r0, r1
        movs r1, # 1
        pop {r1-r3,pc}
_alpha_min_beta_max:
        muls r0, r0, r3
        muls r1, r1, r2
        asrs r0, r0, # 15
        asrs r1, r1, # 15
        adds r0, r0, r1
        movs r1, # 0
        pop {r1-r3,pc}

_lvboqi:
                        @滤波器
                        @R0=地址,R1=长度,r2=表指针地址,r3=ADC数值
                        @出R0=结果
        push {r1-r7,lr}        
        ldr r5, [r2]                @读出表指针
        lsls r6, r1, # 1        
        strh r3, [r0, r5]        @数值写到滤波器缓冲区
        adds r5, r5, # 2
        cmp r5, r6
        bne _lvboqimeidaohuanchongquding
        movs r5, # 0
_lvboqimeidaohuanchongquding:
        str r5, [r2]
        movs r7, # 0
_lvboqixunhuan:
        cmp r5, r6
        bne _lvbozonghe
        movs r5, # 0
_lvbozonghe:
        ldrh r4, [r0, r5]
        adds r5, r5, # 2
        adds r7, r7, r4
        subs r1, r1, # 1
        bne _lvboqixunhuan
        asrs r0, r7, # 10        @修改
        pop {r1-r7,pc}

        
_fftjisuan:
                                @ 入口 R0=数据地址
                                @ 输出实部=0X20000000-0X20000400
                                @ 输出虚部=0X20000400-0X20000800
                                @ 结果左移6位(乘64)
        push {r0-r7,lr}
_fft1:
        ldr r1, = 0x20000000       @ 输出地址
        movs r2, # 128             @ 蝴蝶数量
        ldr r3, = hudieweifanzhuan @ 蝴蝶位反转表
_fft1xunhuan:
        ldr r6, [r3]               @ 取出位反转表里的地一个数据
        ldr r7, [r3, # 0x04]       @ 取出第二个
        ldr r6, [r0, r6]           @ 根据位反转表找到对应的输入数据  
        ldr r7, [r0, r7]           @ 第二个
        adds r4, r6, r7            @ 求出蝴蝶上
        subs r5, r6, r7            @ 求出蝴蝶下
        str r4, [r1]
        str r5, [r1, # 0x04]       @ 把反过来的顺序排列
        adds r1, r1, # 0x08        @ 输出的地址自增
        adds r3, r3, # 0x08        @ 反转表自增
        subs r2, r2, # 1           @ 蝴蝶数减1
        bne _fft1xunhuan           @ 蝴蝶数不到

_fft2:
        ldr r0, = 0x20000000       @ 实部输出地址0x20000000
        movs r4, # 1               
        lsls r4, r4, # 10         
        adds r4, r4, r0            @ 虚部输出地址 0x20000400
        mov r8, r4                 @ 实部和虚部中间
_fft2xunhuan:
        ldr r4, [r0]               @ 取出数据0
        ldr r5, [r0, # 0x08]       @ 取出数据2
        ldr r6, [r0, # 0x04]       @ 取出数据1
        ldr r7, [r0, # 0x0c]       @ 取出数据3
        adds r1, r4, r5            @ 计算蝴蝶上
        subs r2, r4, r5            @ 计算蝴蝶下
        mov r3, r6                @ 0 r 蝴蝶上实部
        movs r4, # 0
        subs r4, r4, r7                @ 0i 蝴蝶上虚部
        mov r5, r6                @ 3r 蝴蝶下实部
        mov r6, r7                @ 3i 蝴蝶下虚部
        movs r7, # 1
        lsls r7, r7, # 10       @ 内存实部和虚部中间
        adds r7, r7, r0         @ R7等于虚部首地址  
        str r1, [r0]            @ 蝴蝶上保存实部
        str r2, [r0, # 0x08]    @ 蝴蝶下实部
        str r3, [r0, # 0x04]    @ 第二组蝴蝶上实部
        str r4, [r7, # 0x04]    @ 第二组蝴蝶上虚部
        str r5, [r0, # 0x0c]        @ 第二组蝴蝶下实部
        str r6, [r7, # 0x0c]    @ 第二组下虚部
        adds r0, r0, # 0x10     @ 蝴蝶组自增
        cmp r0, r8     
        bne _fft2xunhuan        @ 地址不到循环
_fft3:
        ldr r6, = xuanzhuanyinzi       @ 旋转因子自增变量
        ldr r2, = fft3xuanzhuanyinzi   @ 旋转因子第三步的表
        ldr r0, = 0x20000000           @ 实部输出地址
        str r2, [r6]                   @ 旋转因子表首地址写到变量
        movs r1, # 1
        lsls r1, r1, # 10            
        adds r1, r1, r0                @ 虚部输出地址
        mov r8, r1                       @ R8虚部地址自增变量
        mov r9, r0                     @ R9实部地址自增变量
        mov r10, r2                       @ 旋转因子地址写到R10
        movs r5, # 0x10                       @ 两组蝴蝶的距离        
        mov r11, r5                    @ 写到R11
        movs r5, # 4                   @ 旋转因子数量
        mov r12, r5                       @ 旋转因子数量写到R12
        bl _fftg

_fft4:
        ldr r6, = xuanzhuanyinzi        @ 旋转因子自增变量
        ldr r2, = fft4xuanzhuanyinzi        @ 旋转因子第四步表
        ldr r0, = 0x20000000                @ 实部地址
        str r2, [r6]                        @ 第四步旋转因子表写到自增变量
        movs r1, # 1
        lsls r1, r1, # 10
        adds r1, r1, r0                        @ r1 = 虚部地址
        mov r8, r1                        @
        mov r9, r0
        mov r10, r2
        movs r5, # 0x20
        mov r11, r5
        movs r5, # 8
        mov r12, r5
        bl _fftg


_fft5:
        ldr r6, = xuanzhuanyinzi
        ldr r2, = fft5xuanzhuanyinzi
        ldr r0, = 0x20000000
        str r2, [r6]
        movs r1, # 1
        lsls r1, r1, # 10
        adds r1, r1, r0
        mov r8, r1
        mov r9, r0
        mov r10, r2
        movs r5, # 0x40
        mov r11, r5
        movs r5, # 16
        mov r12, r5
        bl _fftg

_fft6:
        ldr r6, = xuanzhuanyinzi
        ldr r2, = fft6xuanzhuanyinzi
        ldr r0, = 0x20000000
        str r2, [r6]
        movs r1, # 1
        lsls r1, r1, # 10
        adds r1, r1, r0
        mov r8, r1
        mov r9, r0
        mov r10, r2
        movs r5, # 0x80
        mov r11, r5
        movs r5, # 32
        mov r12, r5
        bl _fftg
_fft7:
        ldr r6, = xuanzhuanyinzi
        ldr r2, = fft7xuanzhuanyinzi
        ldr r0, = 0x20000000
        str r2, [r6]
        movs r1, # 1
        lsls r1, r1, # 10
        adds r1, r1, r0
        mov r8, r1
        mov r9, r0
        mov r10, r2
        movs r5, # 1
        lsls r5, r5, # 8
        mov r11, r5
        movs r5, # 64
        mov r12, r5
        bl _fftg

_fft8:
        ldr r6, = xuanzhuanyinzi
        ldr r2, = fft8xuanzhuanyinzi
        ldr r0, = 0x20000000
        str r2, [r6]
        movs r1, # 1
        lsls r1, r1, # 10
        adds r1, r1, r0
        mov r8, r1
        mov r9, r0
        mov r10, r2
        movs r5, # 1
        lsls r5, r5, # 9
        mov r11, r5
        movs r5, # 128
        mov r12, r5
        bl _fftg
        pop {r0-r7,pc}
_fftg:
        push {lr}                @ LR保存到堆栈
        movs r4, # 0
        mov lr, r4
_fftxunhuan:
        mov r0, r9                @ R0实部地址自增变量地址
        mov r1, r8                @ R1虚部地址自增变量地址        
        mov r2, r10                @ 旋转因子表地址地址
        mov r3, r11                @ 两组蝴蝶的距离
        ldr r4, [r0]                @ r4=蝴蝶上实部
        ldr r5, [r1]                @ r5=蝴蝶上虚部
        ldr r6, [r0, r3]        @ r6=蝴蝶下实部
        ldr r7, [r1, r3]        @ r7=蝴蝶下虚部
        ldr r3, [r2]                @ SR
        ldr r2, [r2, # 0x04]        @ SI
        push {r4,r5}                @ R4 R5保存到堆栈
                                @ (a+bi)(c+di)=(ac-bd)+(ad+bc)i
        mov r4, r6                @ r4=蝴蝶下实部
        muls r4, r4, r3                @ 乘旋转因子        ac
        mov r5, r7                @ R5=蝴蝶下虚部
        muls r5, r5, r2                @ 乘旋转因子        bd
        subs r4, r4, r5                @ ac-bd
        asrs r4, r4, # 15        @ 截断Q15
        mov r5, r6
        muls r5, r5, r2                @ ad
        muls r7, r7, r3                @ bc
        adds r7, r7, r5         @ ad+bc
        asrs r7, r7, # 15        @ 截断Q15
        pop {r2,r5}                @ R2= 蝴蝶上实部
                                @ r5= 蝴蝶上虚部
        adds r3, r2, r4            @ 上实部加下实部=结果上实部
        subs r2, r2, r4            @ 下实部减上实部=结果下实部
        adds r4, r5, r7                @ 上虚部加下虚部=结果上虚部
        subs r5, r5, r7                @ 上虚部减下虚部=结果下虚部
        mov r6, r11                @ r6=蝴蝶距离
        asrs r3, r3, # 1        @ 右移一位防止溢出
        asrs r4, r4, # 1        @ 右移一位防止溢出
        asrs r2, r2, # 1        @ 右移一位防止溢出
        asrs r5, r5, # 1        @ 右移一位防止溢出
        str r3, [r0]                @ 保存上实部
        str r4, [r1]                @ 保存上虚部
        str r2, [r0, r6]        @ 保存下实部
        str r5, [r1, r6]        @ 保存下虚部
        adds r0, r0, # 0x04        @ 实部地址加4
        adds r1, r1, # 0x04        @ 虚部地址加4
        mov r9, r0                @ r9=当前实部地址
        mov r8, r1                @ R8=当前虚部地址
        mov r2, r10                @ r2= 当前旋转因子地址
        adds r2, r2, # 0x08        @ R2 = 旋转因子地址加8
        mov r10, r2             @ 保存回去
        mov r4, lr                @ 一个蝴蝶旋转因子变量
        adds r4, r4, # 1        @ 自增
        mov lr, r4                 @ 保存回去
        mov r7, r12             @ 取出旋转因子总数量
        cmp r4, r7              @ 到没到数量
        bne _fftxunhuan         @ 没到继续循环
        movs  r4, # 0                @ 到了R4=0
        mov lr, r4                @ 一个蝴蝶旋转因子变量清0
        ldr r6, = xuanzhuanyinzi @ R6=旋转因子自增变量地址        
        ldr r5, = 0x20000400         @ R5=虚部地址
        ldr r6, [r6]                 @ 取出旋转因子自增变量
        mov r7, r11                @ R7= 蝴蝶距离
        mov r10, r6              @ R10 = 旋转因子自增变量
        adds r0, r0, r7                @ 实部地址加蝴蝶距离
        adds r1, r1, r7                @ 虚部地址加蝴蝶距离
        mov r9, r0                @ R9等于当前实部地址
        mov r8, r1                @ R8等于当前虚部地址
        cmp r0, r5                @ 实部到没到虚部边界
        bne _fftxunhuan                @ 没到循环计算
        pop {pc}                @ 返回
        .ltorg                        @ 文字池


使用特权

评论回复
沙发
yjmwxwx|  楼主 | 2019-6-24 13:16 | 只看该作者
本帖最后由 yjmwxwx 于 2019-6-24 18:06 编辑

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

软件计算的单次,数码管显示的是256次计算结果的平均

这次对了

刚才传错了,重新传一个。
adcfft2.tar.gz (29.07 KB)

使用特权

评论回复
板凳
598330983| | 2019-6-24 19:56 | 只看该作者
汇编做,厉害。

使用特权

评论回复
评论
yjmwxwx 2019-6-26 10:23 回复TA
语言都一样的,只要知道怎么算就容易写了。 
地板
lgqsyw| | 2019-6-25 20:50 | 只看该作者
老哥你敢不用汇编搞一个吗

使用特权

评论回复
5
蝴蝶泉2018| | 2019-6-26 10:04 | 只看该作者
做实验嘛,换个F1或者F4的芯片也不贵嘛。毕竟将来稍微复杂的程序都是C语言的,还要考虑架构,操作系统等问题

使用特权

评论回复
评论
yjmwxwx 2019-6-26 10:26 回复TA
我是种地的农民搞这个就是业余爱好,没那么多钱砸,只能用便宜的片子。 
6
yjmwxwx|  楼主 | 2019-6-26 12:39 | 只看该作者


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





不知道这个怎么算时间?

不知道官方库要多长时间?




使用特权

评论回复
7
数码小叶| | 2019-6-27 16:47 | 只看该作者
采样率1M,采集后大量的数据怎么处理的。。。

使用特权

评论回复
评论
数码小叶 2019-6-27 22:16 回复TA
@yjmwxwx :我还以为是一直采 
yjmwxwx 2019-6-27 20:03 回复TA
@yjmwxwx :计算完了再开DMA,再采256个 
yjmwxwx 2019-6-27 19:58 回复TA
不是一直采,就采256个 
8
yediezeus| | 2019-6-28 08:54 | 只看该作者

使用特权

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

本版积分规则

117

主题

2719

帖子

48

粉丝