在电子工程领域,示波器和信号发生器是实验室里最常用的两种仪器。前者用于观测电信号波形,后者用于产生测试信号。传统上这两类设备都是独立存在的专业仪器,价格从几千到数十万不等。而基于STM32的方案,可以用不到200元的成本实现两者的基础功能集成,特别适合学生实验、硬件调试和快速原型开发。
这个项目的核心价值在于:
我在实际项目中用它成功调试过步进电机驱动器、音频电路和传感器信号链,相比单独采购专业设备,这种一体化方案在早期开发阶段特别实用。
主控芯片选用STM32F103C8T6(蓝色pill开发板),选择依据:
信号调理电路关键部件:
重要提示:输入保护电路必不可少!实测中曾因误接24V电源烧毁ADC引脚,加入BAV99钳位二极管后,即使输入50V也能确保安全。
信号输入通道设计:
circuit复制Vin --[1MΩ]--+--[100kΩ]-- GND
|
[TL082]
|
ADC_IN
信号输出通道参数:
PCB布局注意事项:
ADC采样配置(以100kHz采样率为例):
c复制void ADC_Config(void) {
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_1Cycles5);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
定时器生成PWM波形示例(1kHz方波):
c复制void TIM_PWM_Init(uint16_t freq) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseStructure.TIM_Period = SystemCoreClock / freq - 1;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period / 2;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_Cmd(TIM3, ENABLE);
}
任意波形合成采用DDS(直接数字合成)技术:
math复制相位累加器:ϕ[n] = (ϕ[n-1] + Δϕ) mod 2^N
输出值:y[n] = WAVETABLE[ϕ[n]>>(N-M)]
其中:
正弦波表示例生成:
python复制# 预生成波形表
import numpy as np
wave_table = np.sin(np.linspace(0, 2*np.pi, 1024, endpoint=False))
wave_table = (wave_table * 2047 + 2048).astype(int)
通过实测发现三个关键优化点:
c复制DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
c复制NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
实际调试中遇到的典型问题及解决方案:
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| 波形失真 | 阻抗不匹配 | 输出端串联50Ω电阻 |
| ADC读数跳变 | 电源噪声 | 增加10μF钽电容 |
| 高频信号衰减 | 带宽不足 | 更换高速运放 |
| PWM输出不稳定 | 时钟配置错误 | 检查APB1分频系数 |
配合Python上位机实现:
python复制import serial
import matplotlib.pyplot as plt
ser = serial.Serial('COM3', 115200)
data = []
for _ in range(1000):
data.append(int(ser.readline()))
plt.plot(data)
plt.show()
典型实验案例:
在电机控制调试中的应用:
实测某无刷电机相电流波形:
code复制峰值:1.2A @ 15kHz
纹波:<50mA
这个项目最让我惊喜的是它的扩展性——通过修改固件,后来我们还实现了CAN总线分析、红外解码等附加功能。对于嵌入式开发者来说,这样一个基础平台能衍生出无数实用工具。