1.总体逻辑
按下STM32F4的KEY0按键,通过外部中断的方式对按键进行检测,然后开启一次带DMA的固定点数的ADC采集,采集完成后在DMA的中断发送采集到的数据,然后清空数据区准备下一次的按键中断。电脑接受到串口数据后对数据进行简单处理和傅里叶变化,然后实时显示在电脑上。
开发板:正点原子探索者STM32F407ZG
2.STM32
源工程文件
可以拿着正点原子的官方例程进行修改,这里只展示部分重要代码
1.外部中断处理函数
DMA传输完成中断函数
DMA缓存区大小设置
在ADC.h中设置
主函数
采样率的计算
目前是21M的时钟,一个时钟周期是0.047us,采集3个周期,转化12.5个周期就是15.5个周期
采样时间:0.047x15.5=0.7285us
采样率为:1/0.714=1.37268M
理论最高采集0.6863M信号,即686.3K信号
3.Python实时显示
这里的傅里叶变化只会显示最后的 POINT 个点的傅里叶变化情况
import serial
import matplotlib.pyplot as plt
import numpy as np
import time
LINE = 1 # 是否用线的方式连接
OFFSET = 1 # 是否减去偏置值
POINT = 140 # 这里设置的大小和STM32中DMA缓存区的大小要一致
count = 0
# 设置画布大小
fig, (ax1, ax2) = plt.subplots(1, 2)
line1, = ax1.plot([], [])
line2, = ax2.plot([], [])
ax1.set_xlim(0, 100)
ax2.set_xlim(0,POINT*10000)
ax1.set_ylim(0, 5)
ax2.set_ylim(0, 100)
ax1.set_title('Time Domain')
ax2.set_title('Frequency Domain')
# 初始化数据
x = []
y = []
yfft = []
xfft = np.linspace(0,POINT*10000,POINT)
# 创建曲线对象
if LINE:
line1, = ax1.plot([], [])
line2, = ax2.plot([], [])
else:
line1, = ax1.plot([], [],'.')
line2, = ax2.plot([], [],'.')
# 开始绘图
start_time = time.time()
ser = serial.Serial('COM3', 115200) # 根据自己的情况进行更改
# 循环读取串口数据并绘图
while True:
count+=1
# 读取串口数据
if(ser.inWaiting()):
line = ser.readline()
ser.flush()
if len(line) :
real_vol = int(line) * (3.3 / 4096)
print(real_vol)
else:
real_vol = 0
# 实时更新x轴
t = time.time() - start_time
# 更新数据
x.append(t)
y.append(real_vol)
if count>POINT:
#FFT
temp = []
xfft = np.linspace(0,POINT*10000,POINT)
if OFFSET:
yfft = np.fft.fft(y[-POINT:]-np.mean(y[-POINT:]))
else:
yfft = np.fft.fft(y[-POINT:])
line2.set_data(xfft, abs(yfft))
# 更新曲线数据
line1.set_data(x, y)
ax1.set_xlim(max(0, t - 5), t)
# 重新绘制图形
fig.canvas.draw()
fig.canvas.flush_events()
plt.pause(0.01) # 控制循环速率
4.结果展示
输入信号:400KHz正弦波,幅度1V,偏置1V
显示的结果为,去平均值后(无直流信号)