刚上大学的时候就很喜欢示波器,这个暑假想着弄一个,现在弄的基本差不多了,以后有时间了再优化优化
串口一是用来往电脑传fft结果看是否正确的,adc采集输入正弦波,我在串口一中断里加了几个判断,让ad9834产生正弦三角或者扫频,频率增加等功能,其他GPIO都是给ad9834用的,你不用就不用管,我也在头文件里标好9834的引脚了,照着连就可以
dma中点add,选自己的adc1,要注意,如果定时器触发的话,不能选circular,我自认为的解释是如果定时器触发,就是每次触发后,adc都会自动采集数据传送到缓冲区,然后再次触发又会从缓冲区的头部开始传输,所以我一开始串口打印的adc输入值不连续,data width选word,或半字也可以,取决于你的adc分辨率,我12位,图省心选了word,
这是adc设置,转换模式里enable,选我这里选的,每次计时器溢出会触发定时器的采样,相对于中断的好处是不需要进入中断服务处理,更省时间,把时间都留给fft(尽管这样,c8t6的速度还是很慢,我每次加了频率之后,要过一两秒才能出结果,一点都不实时,有条件的还是上f4吧)
tim3像图这样设置,不分频,我给APB2的设置是36Mhz,除以351,大概是102400,1024点的fft,能测试以1000分辨率的频率,我只是拿来测试,过两天用立创30块嫖的f4vgt6就能把分辨率拉高了
时钟树,不多说了
arm的dsp库非常方便,不需要像stm32官方库要复制进去,直接在keil里打勾就可以用
然后Include arm_math.h,ad9834是我用来产生标准正弦波测试fft结果的,没有可以不用,可以直接用matlab产生正弦波数组,或者直接在keil里写正弦的数组也一样,然后fft,效果是一样的
adcbuffer是dma传输到的位置,rxbuffer是串口接收缓冲区,用来接收串口的指令来控制9834产生不同波形,index用来判断哪个是fftout里最大的值,至于fftinput为什么是*2,因为他有虚数的部分,所以等下咱们赋值的时候咱们就要*2的赋值
要加上这两行才能启动adc的定时器触发和dma
主函数里是fft过程,cfft是fft过程,紧接着是求幅值,不过求不求都一样,因为咱们的输入没有虚数,赋值那样赋值是为了让虚部设置为0
注释掉的部分,图片最上面的发送数据底下,是没有外部正弦波时用的,自己设置一个正弦数组
最底下注释掉的部分是把fft结果打印出来,然后那个printf,是我用来给串口屏显示用的,你们直接注释就行,把fftoutput【0】设为0,让直流量为0,最后打印的时候,要把fftoutput先除以4096乘以3.3(adc值转为电压值),然后除以N/2(这是离散傅里叶变化的公式),这样才是真正的信号的幅度,如果要自己修改参数,修改定时器溢出时间可以设置adc采样率,采样率越大,能正确测得的频率越高,1024是fft的点数,最后fftout的元素是以采样率/fft点数为分辨率的,也就是fftoutput[1]是1000hz,fftoutput[2]是2000hz,加油吧,printf重定向部分在我的工程写好了,没什么有价值的东西,只是有一些坑可以让也想弄fft的同学避一避,比如dma不能设置circular,adc不能用continuous mode,还有就是定时器触发,dma加定时器触发就能最大限度的把时间留给fft了,希望大家看完能觉得有用,谢谢大家,我的第一篇
通过百度网盘分享的文件:sss.zip
链接:https://pan.baidu.com/s/1DG-oLDNSIsfxCm2G97-S8A?pwd=gusq
提取码:gusq