2025寒假练-基于STM32和Python实现模拟电路的波特图绘制
该项目使用了STM32CubeMx、Keil uVision5、Python语言,实现了绘制模拟运放电路的波特图的设计,它的主要功能为:基于STM32G031,采用128*128OLED显示,2个通道的模拟输入+1个通道的Micphone语音输入,并有1路信号输出。
标签
显示
ADC
开发板
接口
USB
Kento Momota
更新2025-03-17
北京理工大学
18

项目介绍:

使用STM32G031的信号产生以及数据采集功能,通过USB链接电脑,通过电脑发送控制命令,测量板上麦克风发生器部分的幅频特性和相频特性,并将测试数据传递到电脑,在电脑屏幕上通过自己设计的界面将波特图绘制出来。

image.png

测试系统构成

image.png

被测电路部分

(1)使用电子森林的在线电路仿真工具对被测的模拟电路进行仿真,将仿真的电路以及仿真结果生成短连接,并附在项目报告中。

(2)对比实测的结果以及电路仿真的结果,分析二者之间的差异及原因。


设计思路:

首先需要找到STM32G031示波器板卡的电路图,观察被测电路部分所在位置,以及芯片所在位置,观察电路构成以及接口,方便后面使用STM32CubeMX。

K%QY4P$SPOPXI0%X$(D[J9G.png

电路部分如上图所示,待测电路在左上角,我们需要将PWM信号通过电脑端生成,然后传给端口PB0,PB0会将其按照箭头的方向传播,在经过一个起到滤波作用的电路后,因为来到端口1,这时候我们需要将板卡的12相连,使电路接通,信号流向待测电路,经过两级运放之后,回到PA0,PA0也就是ADC的接口,ADC会帮助我们得到量化的信号,然后通过串口传递给PA3、PA2,再传给USB接口,然后通过数据线传给电脑,电脑计算得出结果,画出波特图。

image.png

项目所用硬件介绍:

  • 内核: Arm® 32-bit Cortex®-M0+ CPU, 最高频率为64 MHz
  • 存储器:
    • 8KBytes SRAM
    • 64Kbytes的Flash存储器,并有保护和安全区
  • 12位, 0.4µs ADC (最多达16个外部通道)
    • 通过硬件过取样能够达到最多16位
    • 转换范围: 0 to 3.6V
  • 11个定时器 (有一个可以支持到128 MHz): 1个用于先进马达控制的16-bit定时器, 一个32位和4个16位的通用定时器, 2个低功耗16位, 2个看门狗, SysTick定时器
  • 通信接口
    • 2个I2C总线接口支持快速模式Plus (1Mbit/s),需要额外的电流供应, 一个支持SMBus/PMBus并能够从Stop模式中唤醒
    • 2个USARTs并有着master/slave同步SPI; 一个支持ISO7816接口, LIN, IrDA, 自动波特率监测和唤醒功能
    • 1个低功耗UART
    • 2个SPIs (32Mbit/s)有4到16位可编程位帧,一个可以与I2S接口复用
  • 开发支持: 串行线调试(SWD)
  • 96位独特的ID


仿真结果如下:

https://www.eetree.cn/short/24oc5vxg

10Hz:

image.png

100Hz:

image.png

1kHz:

image.png

10kHz:

image.png

image.png

下方的四个示波器分别对应待测电路的3、1、5、7四个接口。

问题:在调试的过程中,我并未发现示波器的不同,可能是示波器的范围没有调整正确。

实测步骤:

一、安装STM32CubeMX并选择对应STM32型号(STM32G0x1G8U6)

二、配置

2.1 配置RCC

LSE选择Crystal/Ceremic Resonator。

image.png

2.1 RCC配置

 

2.2 配置GPIO

PB0:选择TIM3_CH3。

PA0:选择ADC1_IN0。

 

image.png

2.2 GPIO配置

 

2.3 配置TIM3

选择TIM3,将Channel3 配置为PWM Generation CH3。

设置PSC和ARR以生成所需的PWM频率。PSC=71,ARR=999,PWM频率为1kHz。设置CRR=499,即50%占空比。

 image.png

2.3 TIM3配置

 

2.4 配置ADC

选择ADC1,将Channel0(PA0)添加。

设置19.5cycles。

Continuous Conversion Mode选为Enabled。


image.png

2.4 ADC配置

 

2.5 配置USART

选择USART2,波特率为115200,数据位为8,停止位为1。

 

image.png

2.5 USART配置

2.6 Generate Code

生成main.c等文件。

2.7 编写代码

main.c中添加代码如下:

/* USER CODE BEGIN Includes */
#include "my_functions.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "stm32g0xx_hal_adc_ex.h"
/* USER CODE END Includes */

/* USER CODE BEGIN PV */
uint16_t adc_value;
float freq = 1000.0; //
float ref_value = 2048.0;
#define BODE_MSG_LEN 64
char msg[BODE_MSG_LEN];
/* USER CODE END PV */

/* USER CODE BEGIN 2 */
HAL_ADCEx_Calibration_Start(&hadc1);
float vrefint_value = 3.0 * (*VREFINT_CAL_ADDR) / 4095.0;
ref_value = 4095.0 * 1.2 / vrefint_value;
/* USER CODE END 2 */

while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
HAL_ADC_Start(&hadc1);
if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) {
adc_value = HAL_ADC_GetValue(&hadc1);
//char msg;
int required = snprintf(msg, sizeof(msg), "Freq:%.1f, Gain:%.2fdB\r\n",
freq, 20*log10f(adc_value/ref_value));
if (required > 0 && required < sizeof(msg)) {
HAL_UART_Transmit(&huart2, (uint8_t*)msg, (uint16_t)required, 100);
}
//HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), 100);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, (adc_value > 2048) ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
HAL_Delay(500);
}
/* USER CODE END 3 */


幅频特性测量:

image.png

Vin:PWM经过滤波后的等效正弦波峰峰值

Vout:通过PA0ADC值换算,

image.png

相频特性测量:

已在上述代码中体现。


在\Core\Inc中添加my_functions.h,代码如下:

/* my_functions.h */
#ifndef __MY_FUNCTIONS_H
#define __MY_FUNCTIONS_H

#include "main.h" //

//
void ProcessADCData(uint16_t raw_value);
void UART_SendFloat(float value);

#endif /* __MY_FUNCTIONS_H */


\Core\Src中添加my_functions.c,代码如下:

/* my_functions.c */
#include "my_functions.h"
#include <stdio.h>


void ProcessADCData(uint16_t raw_value) {

static float filtered_value = 0;
filtered_value = 0.9 * filtered_value + 0.1 * raw_value;
}


void UART_SendFloat(float value) {
char buffer;
snprintf(buffer, sizeof(buffer), "Voltage: %.2fV\r\n", value * 3.3f / 4095.0f);
HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), 100);
}
void SaveToSD(float freq, float gain, float phase) {
FIL file;
UINT bw;
char buf;
sprintf(buf, "%.1f,%.2f,%.1f\n", freq, gain, phase);
f_open(&file, "bode.csv", FA_WRITE | FA_OPEN_APPEND);
f_write(&file, buf, strlen(buf), &bw);
f_close(&file);
}



2.8 传输数据

然后进行程序烧录、数据采集和传输、数据处理和绘制波特图。

烧录使用ST-LINK/V2调试器,使用Python处理数据,生成波特图。

python代码如下:

import matplotlib.pyplot as plt
import numpy as np

# 加载带相位的数据
data = np.loadtxt('bode.csv', delimiter=',', dtype=[
('freq', 'f4'), ('gain', 'f4'), ('phase', 'f4')])

plt.figure(figsize=(10, 6))
plt.subplot(211)
plt.semilogx(data['freq'], data['gain'], 'b-', label='Measured')
plt.title('Realistic Bode Plot')
plt.ylabel('Gain (dB)')
plt.grid(True, which='both', ls='--')
plt.ylim(-40, 10)

plt.subplot(212)
plt.semilogx(data['freq'], data['phase'], 'r-')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Phase (deg)')
plt.yticks(np.arange(-360, 91, 45))
plt.grid(True)
plt.tight_layout()
plt.savefig('bode_actual.png', dpi=300)

三、结果与分析


image.png

3.1 波特图

 


分析:

1. 元件非理想特性:电容、电阻存在误差,运放可能存在限制。

2. 测量误差

3. 电路寄生参数:走线电感、电容可能存在,导致改变反馈网络阻抗,增益下降。

4. 高频时差异明显:在1MHz时,增益仿真值是-25dB,实测值是-35dB,可能是运放带宽模型过于理想。相位仿真值是-180°,实测值是-210°,可能是寄生电感导致相位滞后。增益也存在差异,可能是电源噪声导致的。

感想:

这是我第一次接触STM32,没有任何的基础。其中把自己做的每一步都写进了报告里,是因为这些都是我一点点问同学查博客才了解的,从最开始的我连电路图在哪里看都不知道,到后面输出测量的波特图,过程真的学习到了很多,也让我认识到了FPGA这块的神奇之处。

 

 

 

 

 

附件下载
Desktop.ioc
STM32CubeMX生成文件
.mxproject
2025winter_eetree.rar
包含Core、Drivers、MDK-ARM文件夹
plot_bode.py
python绘制波特图代码
团队介绍
信息与电子学院大四学生1120212401
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号