本设计以Python为上位机制作的STM32示波器,实现了波形显示、频率计算、波形保存等功能,代码均有完整中文注释,供大家参考(如果有条件,使用OLED显示屏当做上位机实现该设计,这样有效的减少了上位机界面刷新的延迟)
文件包括上位机 下位机 测试数据等
上位机程序:
- import serial
- import threading
- import time
- import matplotlib.pyplot as plt
- from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
- import tkinter as tk
- from tkinter import ttk
- from tkinter import filedialog
- from PIL import Image, ImageTk
- import numpy as np
- class Oscilloscope:
- def __init__(self, master):
- self.master = master # 定义 master 变量
- self.master.title("简易示波器") # 设置窗口标题
- self.master.geometry("1400x600") # 设置窗口大小
- self.master.resizable(False, False) # 设置窗口不可调整大小
- self.master.protocol("WM_DELETE_WINDOW", self.close_window) # 设置关闭窗口时调用的方法
- self.ser = None # 定义 ser 变量,初始值为 None
- self.baudrate = tk.StringVar(value="921600") # 定义波特率变量,初始值为 "921600"
- self.port = tk.StringVar(value="COM5") # 定义端口变量,初始值为 "COM11"
- self.size = tk.StringVar(value=50)
- self.MAXvar = tk.StringVar()
- self.MINvar = tk.StringVar()
- self.Fvar = tk.StringVar()
- self.Fsvar = tk.StringVar()
- self.pause = tk.BooleanVar(value=False) # 定义暂停变量,初始值为 False
- self.fig = plt.Figure(figsize=(6, 4), dpi=100) # 创建一个 Figure 对象
- self.ax = self.fig.add_subplot(111) # 在 Figure 对象中添加一个子图
- self.canvas = FigureCanvasTkAgg(self.fig, master=self.master) # 创建一个画布对象
- self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True) # 将画布添加到窗口中
- self.toolbar = tk.Frame(master=self.master) # 创建一个工具栏对象
- self.toolbar.pack(side=tk.TOP, fill=tk.X) # 将工具栏添加到窗口中
- self.pause_button = ttk.Checkbutton(self.toolbar, text="暂停", variable=self.pause, command=self.pause_waveform, width=6) # 创建一个暂停按钮
- self.pause_button.pack(side=tk.LEFT, padx=5) # 将暂停按钮添加到工具栏中
- self.save_button = ttk.Button(self.toolbar, text="保存图片", command=self.save_waveform, width=8) # 创建一个保存按钮
- self.save_button.pack(side=tk.LEFT, padx=5) # 将保存按钮添加到工具栏中
- self.port_label = ttk.Label(self.toolbar, text="端口:", width=6) # 创建一个端口标签
- self.port_label.pack(side=tk.LEFT, padx=5) # 将端口标签添加到工具栏中
- self.port_combobox = ttk.Combobox(self.toolbar, textvariable=self.port, values=["COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8","COM10"], width=6) # 创建一个端口下拉框
- self.port_combobox.pack(side=tk.LEFT, padx=5) # 将端口下拉框添加到工具栏中
- self.baudrate_label = ttk.Label(self.toolbar, text="波特率:", width=6) # 创建一个波特率标签
- self.baudrate_label.pack(side=tk.LEFT, padx=5) # 将波特率标签添加到工具栏中
- self.baudrate_combobox = ttk.Combobox(self.toolbar, textvariable=self.baudrate, values=["9600", "115200","921600"], width=6) # 创建一个波特率下拉框
- self.baudrate_combobox.pack(side=tk.LEFT, padx=5) # 将波特率下拉框添加到工具栏中
- self.baudrate_label = ttk.Label(self.toolbar, text="横轴长度:", width=8) # 创建一个波特率标签
- self.baudrate_label.pack(side=tk.LEFT, padx=5) # 将波特率标签添加到工具栏中
- self.baudrate_combobox = ttk.Combobox(self.toolbar, textvariable=self.size, values=[50, 100, 200, 500, 1000], width=5) # 创建一个横坐标尺寸下拉框
- self.baudrate_combobox.pack(side=tk.LEFT, padx=5) # 将波特率下拉框添加到工具栏中
- self.connect_button = ttk.Button(self.toolbar, text="连接", command=self.connect, width=6) # 创建一个连接按钮
- self.connect_button.pack(side=tk.LEFT, padx=5) # 将连接按钮添加到工具栏中
- self.disconnect_button = ttk.Button(self.toolbar, text="断开连接", command=self.disconnect, width=8) # 创建一个断开连接按钮
- self.disconnect_button.pack(side=tk.LEFT, padx=5)
- self.disconnect_button = ttk.Button(self.toolbar, text="清除图像", command=self.clear, width=8) # 创建一个断开连接按钮
- self.disconnect_button.pack(side=tk.LEFT, padx=5) # 将断开连接按钮添加到工具栏中
- ······
复制代码 下位机主程序:
- /**********************************************************
- MCU接线说明
- 采样接口:PA6
- 正弦波:PA4
- 三角波:PA5
- 增加采样频率:KEY0
- 降低采样频率:KEY1
- 基于正点原子精英板 MCU STM32F1Z8T6
- 时间:2023年5月12日
- ***********************************************************/
- #include "led.h"
- #include "delay.h"
- #include "sys.h"
- #include "usart.h"
- #include "lcd.h"
- #include "adc.h"
- #include "dma.h"
- #include "timer.h"
- #include "table_fft.h"
- #include "stm32_dsp.h"
- #include "math.h"
- #include "key.h"
- #include "BEEP.h"
- #include "dac.h"
- #include "exti.h"
- #define NPT 1024 //采样次数
- #define PI2 6.28318530717959 //2*pi 用于正弦波生成
- void InitBufInArray(void); //正弦波输出缓存
- void sinout(void); //正弦波输出
- void GetPowerMag(void); //FFT变换,输出频率
- void sendData(void);
- int long fftin [NPT]; //FFT输入 x[n]
- int long fftout[NPT]; //FFT输出 X[k]
- u32 FFT_Mag[NPT/2]={0}; //幅频特性
- u16 magout[NPT]; //模拟正弦波输出缓存区
- u16 currentadc; //实时采样数据
- u16 adcx[NPT]; //adc数值缓存
- u32 adcmax; //采样最大值和最小值
- u32 adcmin;
- u8 adc_flag=0; //采样结束标志
- u8 key_flag=0; //按键扫描标志
- u8 show_flag=1; //更新暂停标志
- u16 T=2000; //定时器2重载值,不能小于PWM的Pluse值
- u16 pre=36; //定时器2预分频值
- u32 fre; //采样频率 Hz
- u16 F; //波形频率
- u16 temp=0; //幅值最大的频率成分
- u16 t=0;
- u16 key; //按键
- int main()
- {
- u16 i;
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- MYDMA1_Config(DMA1_Channel1,(u32)&ADC1->DR,(u32)¤tadc,1);
- uart_init(921600);
- delay_init();
- LED_Init();
- EXTIX_Init();
- Adc_Init();
- InitBufInArray();
- TIM4_Int_Init(1,35); //三角波和噪声频率控制,
- TIM3_Int_Init(39,71); //72MHz/40/72=25kHz 25kHz/1024≈25Hz 正弦波频率约为24.5Hz
- TIM2_PWM_Init(T-1,pre-1); //最大频率72000000/1/2000=3.6KHz
- Dac1_Init();
- Dac2_Init();
-
- while(1)
- {
- //等待采样完成
- while(adc_flag==0)
- {
- LED1=!LED1;
- sendData(); //发数据给上位机
- delay_ms(100);
-
- }
复制代码 |