STM32F103用CubeMX实现ADC欠采样用800Hz采样率捕获1kHz正弦波的保姆级教程当信号频率超过奈奎斯特采样定理的限制时传统方法会要求我们提升采样率。但通过欠采样技术我们能够以远低于信号频率的采样率捕获高频信号。本文将手把手教你如何在STM32F103上实现用800Hz采样率准确捕获1kHz正弦波。1. 硬件准备与环境搭建在开始之前我们需要准备以下硬件和软件环境STM32F103C8T6开发板蓝色药丸板即可USB转TTL串口模块用于数据传输信号发生器或能输出1kHz正弦波的设备STM32CubeMX v6.xKeil MDK-ARM或STM32CubeIDEVOFA或其它串口波形显示工具提示如果使用其它STM32F103系列开发板只需注意引脚兼容性。VOFA是一款免费的串口数据可视化工具支持多种协议。安装好开发环境后我们先计算几个关键参数采样间隔 1/800Hz 1.25ms 等效采样率 信号频率 × 每周期采样点数 1kHz × 4 4kHz2. CubeMX工程配置启动CubeMX并按照以下步骤配置2.1 时钟树设置选择外部晶振HSE作为时钟源配置系统时钟为72MHz设置APB2总线时钟为72MHzADC时钟源关键参数表参数值HCLK72MHzAPB136MHzAPB272MHzADC预分频6分频ADC时钟12MHz2.2 ADC配置启用ADC1选择Regular Conversion Mode设置Data Alignment为Right启用DMA Continuous Requests配置Number Of Conversion为1// 生成的ADC初始化代码片段 hadc1.Instance ADC1; hadc1.Init.ScanConvMode DISABLE; hadc1.Init.ContinuousConvMode DISABLE; hadc1.Init.DiscontinuousConvMode DISABLE; hadc1.Init.ExternalTrigConv ADC_EXTERNALTRIGCONV_T3_TRGO; hadc1.Init.DataAlign ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion 1;2.3 定时器配置TIM3启用TIM3设置时钟源为内部时钟配置为Trigger Output模式设置预分频器(PSC)为999设置自动重载值(ARR)为89定时器参数计算定时器频率 72MHz / (PSC1) 72,000Hz 定时周期 (ARR1) / 定时器频率 90 / 72,000 1.25ms 触发频率 1 / 1.25ms 800Hz2.4 DMA配置添加DMA通道ADC1设置模式为Circular数据宽度为Word内存地址递增// DMA配置示例 hdma_adc1.Instance DMA1_Channel1; hdma_adc1.Init.Direction DMA_PERIPH_TO_MEMORY; hdma_adc1.Init.PeriphInc DMA_PINC_DISABLE; hdma_adc1.Init.MemInc DMA_MINC_ENABLE; hdma_adc1.Init.PeriphDataAlignment DMA_PDATAALIGN_WORD; hdma_adc1.Init.MemDataAlignment DMA_MDATAALIGN_WORD; hdma_adc1.Init.Mode DMA_CIRCULAR;3. 代码实现与调试生成代码后我们需要添加一些用户代码来实现完整功能。3.1 主程序逻辑#define SAMPLE_SIZE 400 // 采集400个点约5个周期 uint32_t adcBuffer[SAMPLE_SIZE]; int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_DMA_Init(); MX_ADC1_Init(); MX_TIM3_Init(); HAL_ADC_Start_DMA(hadc1, adcBuffer, SAMPLE_SIZE); HAL_TIM_Base_Start(htim3); while (1) { // 数据通过DMA自动采集 // 可通过串口定期发送数据 } }3.2 串口发送数据添加串口发送函数将采集到的数据发送到上位机void sendDataToPC(uint32_t *data, uint16_t size) { for(int i0; isize; i) { uint16_t value data[i] 0xFFFF; // 取低16位 uint8_t buffer[2]; buffer[0] value 8; buffer[1] value 0xFF; HAL_UART_Transmit(huart1, buffer, 2, HAL_MAX_DELAY); HAL_Delay(1); // 防止发送过快导致丢包 } }3.3 VOFA配置打开VOFA选择串口模式设置正确的串口号和波特率选择FireWater协议添加波形显示控件设置Y轴范围为0-3.3V对应ADC值0-40954. 结果分析与优化当信号发生器输出1kHz正弦波时我们将在VOFA上看到类似下图的波形采样点分布示例 周期1点A(0°) → 周期2点B(90°) → 周期3点C(180°) → 周期4点D(270°) 周期5点A(0°) → 周期6点B(90°) → ...常见问题及解决方案波形不连续或错位检查定时器配置是否正确确保信号频率准确为1kHz调整采样点数使其为信号周期的整数倍ADC值不稳定添加RC低通滤波电路如1kΩ电阻100nF电容在代码中添加软件滤波如移动平均数据传输丢失降低串口波特率如改为115200增加发送间隔时间对于更精确的应用可以考虑以下优化使用定时器的主从模式实现更精确的触发添加硬件触发同步电路实现自动增益控制(AGC)适应不同幅值信号在实际项目中我发现最关键的三个参数是定时器触发间隔的精确性信号频率的稳定性采样点数与信号周期的匹配关系