找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1163|回复: 0
收起左侧

STM32单片机示波器(pyhton上位机)

[复制链接]
ID:771642 发表于 2023-5-30 16:59 | 显示全部楼层 |阅读模式
本设计以Python为上位机制作的STM32示波器,实现了波形显示、频率计算、波形保存等功能,代码均有完整中文注释,供大家参考(如果有条件,使用OLED显示屏当做上位机实现该设计,这样有效的减少了上位机界面刷新的延迟)

文件包括上位机 下位机 测试数据等

上位机程序:
  1. import serial
  2. import threading
  3. import time
  4. import matplotlib.pyplot as plt
  5. from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
  6. import tkinter as tk
  7. from tkinter import ttk
  8. from tkinter import filedialog
  9. from PIL import Image, ImageTk
  10. import numpy as np

  11. class Oscilloscope:
  12.     def __init__(self, master):
  13.         self.master = master                    # 定义 master 变量
  14.         self.master.title("简易示波器")          # 设置窗口标题
  15.         self.master.geometry("1400x600")         # 设置窗口大小
  16.         self.master.resizable(False, False)     # 设置窗口不可调整大小
  17.         self.master.protocol("WM_DELETE_WINDOW", self.close_window)  # 设置关闭窗口时调用的方法

  18.         self.ser = None                         # 定义 ser 变量,初始值为 None
  19.         self.baudrate = tk.StringVar(value="921600")                    # 定义波特率变量,初始值为 "921600"
  20.         self.port = tk.StringVar(value="COM5")                          # 定义端口变量,初始值为 "COM11"
  21.         self.size = tk.StringVar(value=50)
  22.         self.MAXvar = tk.StringVar()
  23.         self.MINvar = tk.StringVar()
  24.         self.Fvar = tk.StringVar()
  25.         self.Fsvar = tk.StringVar()
  26.         self.pause = tk.BooleanVar(value=False)                         # 定义暂停变量,初始值为 False
  27.         self.fig = plt.Figure(figsize=(6, 4), dpi=100)                  # 创建一个 Figure 对象
  28.         self.ax = self.fig.add_subplot(111)                             # 在 Figure 对象中添加一个子图
  29.         self.canvas = FigureCanvasTkAgg(self.fig, master=self.master)   # 创建一个画布对象
  30.         self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)  # 将画布添加到窗口中
  31.         self.toolbar = tk.Frame(master=self.master)                     # 创建一个工具栏对象
  32.         self.toolbar.pack(side=tk.TOP, fill=tk.X)                       # 将工具栏添加到窗口中
  33.         self.pause_button = ttk.Checkbutton(self.toolbar, text="暂停", variable=self.pause, command=self.pause_waveform, width=6)  # 创建一个暂停按钮
  34.         self.pause_button.pack(side=tk.LEFT, padx=5)                    # 将暂停按钮添加到工具栏中
  35.         self.save_button = ttk.Button(self.toolbar, text="保存图片", command=self.save_waveform, width=8)  # 创建一个保存按钮
  36.         self.save_button.pack(side=tk.LEFT, padx=5)                     # 将保存按钮添加到工具栏中
  37.         self.port_label = ttk.Label(self.toolbar, text="端口:", width=6)         # 创建一个端口标签
  38.         self.port_label.pack(side=tk.LEFT, padx=5)                      # 将端口标签添加到工具栏中
  39.         self.port_combobox = ttk.Combobox(self.toolbar, textvariable=self.port, values=["COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8","COM10"], width=6)  # 创建一个端口下拉框
  40.         self.port_combobox.pack(side=tk.LEFT, padx=5)                   # 将端口下拉框添加到工具栏中
  41.         self.baudrate_label = ttk.Label(self.toolbar, text="波特率:", width=6)    # 创建一个波特率标签
  42.         self.baudrate_label.pack(side=tk.LEFT, padx=5)                  # 将波特率标签添加到工具栏中
  43.         self.baudrate_combobox = ttk.Combobox(self.toolbar, textvariable=self.baudrate, values=["9600", "115200","921600"], width=6)  # 创建一个波特率下拉框
  44.         self.baudrate_combobox.pack(side=tk.LEFT, padx=5)               # 将波特率下拉框添加到工具栏中
  45.         self.baudrate_label = ttk.Label(self.toolbar, text="横轴长度:", width=8)    # 创建一个波特率标签
  46.         self.baudrate_label.pack(side=tk.LEFT, padx=5)                  # 将波特率标签添加到工具栏中
  47.         self.baudrate_combobox = ttk.Combobox(self.toolbar, textvariable=self.size, values=[50, 100, 200, 500, 1000], width=5)  # 创建一个横坐标尺寸下拉框
  48.         self.baudrate_combobox.pack(side=tk.LEFT, padx=5)               # 将波特率下拉框添加到工具栏中
  49.         self.connect_button = ttk.Button(self.toolbar, text="连接", command=self.connect, width=6)                           # 创建一个连接按钮
  50.         self.connect_button.pack(side=tk.LEFT, padx=5)                  # 将连接按钮添加到工具栏中
  51.         self.disconnect_button = ttk.Button(self.toolbar, text="断开连接", command=self.disconnect, width=8)             # 创建一个断开连接按钮
  52.         self.disconnect_button.pack(side=tk.LEFT, padx=5)
  53.         self.disconnect_button = ttk.Button(self.toolbar, text="清除图像", command=self.clear, width=8)              # 创建一个断开连接按钮
  54.         self.disconnect_button.pack(side=tk.LEFT, padx=5)                # 将断开连接按钮添加到工具栏中
  55. ······
复制代码
下位机主程序:
  1. /**********************************************************
  2.                                                                                         MCU接线说明
  3. 采样接口:PA6
  4. 正弦波:PA4
  5. 三角波:PA5
  6. 增加采样频率:KEY0
  7. 降低采样频率:KEY1

  8. 基于正点原子精英板 MCU STM32F1Z8T6
  9. 时间:2023年5月12日
  10. ***********************************************************/
  11. #include "led.h"
  12. #include "delay.h"
  13. #include "sys.h"
  14. #include "usart.h"
  15. #include "lcd.h"
  16. #include "adc.h"
  17. #include "dma.h"
  18. #include "timer.h"
  19. #include "table_fft.h"
  20. #include "stm32_dsp.h"
  21. #include "math.h"
  22. #include "key.h"
  23. #include "BEEP.h"
  24. #include "dac.h"
  25. #include "exti.h"

  26. #define NPT 1024 //采样次数
  27. #define PI2 6.28318530717959  //2*pi 用于正弦波生成


  28. void InitBufInArray(void);   //正弦波输出缓存
  29. void sinout(void);                                          //正弦波输出
  30. void GetPowerMag(void);      //FFT变换,输出频率
  31. void sendData(void);
  32. int long fftin [NPT];        //FFT输入 x[n]
  33. int long fftout[NPT];        //FFT输出 X[k]
  34. u32 FFT_Mag[NPT/2]={0};      //幅频特性
  35. u16 magout[NPT];                                                 //模拟正弦波输出缓存区

  36. u16 currentadc;              //实时采样数据
  37. u16 adcx[NPT];               //adc数值缓存
  38. u32 adcmax;                  //采样最大值和最小值
  39. u32 adcmin;
  40. u8 adc_flag=0;                                                   //采样结束标志
  41. u8 key_flag=0;                                                          //按键扫描标志
  42. u8 show_flag=1;                                                         //更新暂停标志
  43. u16 T=2000;                                                                         //定时器2重载值,不能小于PWM的Pluse值
  44. u16 pre=36;                                                                          //定时器2预分频值
  45. u32 fre;                                                                                   //采样频率 Hz
  46. u16 F;                                                                                         //波形频率

  47. u16 temp=0;                                                                         //幅值最大的频率成分
  48. u16 t=0;
  49. u16 key;                                                                                  //按键

  50. int main()
  51. {
  52.         u16 i;
  53.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  54.         MYDMA1_Config(DMA1_Channel1,(u32)&ADC1->DR,(u32)¤tadc,1);
  55.         uart_init(921600);
  56.         delay_init();
  57.         LED_Init();
  58.         EXTIX_Init();
  59.         Adc_Init();
  60.         InitBufInArray();
  61.         TIM4_Int_Init(1,35);                                //三角波和噪声频率控制,
  62.         TIM3_Int_Init(39,71);                                //72MHz/40/72=25kHz   25kHz/1024≈25Hz 正弦波频率约为24.5Hz
  63.         TIM2_PWM_Init(T-1,pre-1);                //最大频率72000000/1/2000=3.6KHz
  64.         Dac1_Init();
  65.         Dac2_Init();
  66.         
  67.         while(1)
  68.         {
  69.                 //等待采样完成
  70.                 while(adc_flag==0)
  71.                 {
  72.                         LED1=!LED1;
  73.                         sendData(); //发数据给上位机
  74.                         delay_ms(100);
  75.                
  76.                 }
复制代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表