stm32f103c8t6 标准库 测量 正弦波 幅值并在OLED上显示出来 示例代码
时间: 2025-06-18 08:40:34 浏览: 15
<think>好的,我现在需要帮助用户找到使用STM32F103C8T6标准库测量正弦波幅值并在OLED上显示的示例代码。首先,我得回顾一下用户之前的问题和提供的引用内容。用户引用了三个资料,其中提到了测频计、示波器项目,以及使用PWM和DAC生成波形。用户现在的需求是测量正弦波幅值并显示在OLED上,所以需要结合ADC采集和OLED显示。
首先,STM32F103C8T6没有内置DAC,但用户可能需要用ADC来采集外部正弦波信号。根据引用[2],他们之前用PWM生成方波,但现在需要测量外部输入的模拟信号。所以应该配置ADC来读取输入电压。
接下来,标准库的使用是关键。用户需要标准库的代码,而不是HAL库。因此,我需要确保提供的代码是基于标准库的函数,比如使用ADC1的初始化、通道配置等。
然后是幅值的计算。正弦波的幅值可以通过ADC采集的峰值来判断。需要连续采样一段时间,找到最大值和最小值,然后计算峰峰值,再转换为电压值。例如,假设ADC的参考电压是3.3V,12位ADC的分辨率是4096,所以每个LSB对应3.3/4096伏特。
另外,OLED显示部分需要用到SSD1306或其他驱动的库函数。用户可能需要初始化OLED,并编写显示函数来输出幅值信息。需要确保代码中包含正确的OLED驱动函数,比如显示字符串和数值的函数。
需要考虑的硬件连接包括:将正弦波信号连接到ADC的某个通道(比如PA1),确保信号在0-3.3V范围内,可能需要使用运放电路进行调理。同时,OLED的I2C或SPI接口连接到对应的引脚,如PB6和PB7作为I2C的SCL和SDA。
可能的代码结构包括:初始化ADC和OLED,进入主循环,进行ADC采样,处理数据计算幅值,然后更新OLED显示。需要注意ADC的采样速率是否足够,尤其是对于较高频率的正弦波,可能需要定时器触发采样或DMA传输,但用户的需求可能只是低频测量,所以简单的轮询方式可能足够。
需要验证代码的正确性,比如检查ADC配置是否正确,采样值是否准确,以及OLED显示是否正常。用户可能需要根据实际硬件调整引脚和参数,比如ADC通道、I2C地址等。
最后,用户可能需要了解如何将代码下载到单片机,并连接电路进行测试。此外,幅值测量的精度和范围也是需要考虑的因素,可能需要校准或软件滤波来提高准确性。</think>根据您对STM32F103C8T6测量正弦波幅值的需求,提供标准库实现方案如下:
### 一、硬件连接
1. 正弦波输入:PA1(ADC1通道1)
2. OLED显示:I2C接口(PB6-SCL,PB7-SDA)
3. ADC参考电压:3.3V
### 二、代码实现
```c
#include "stm32f10x.h"
#include "ssd1306.h"
#define ADC_CHANNEL ADC_Channel_1
#define SAMPLE_COUNT 200
void ADC_Config(void) {
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
// PA1模拟输入配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// ADC基本配置
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, 1, ADC_SampleTime_239Cycles5);
ADC_Cmd(ADC1, ENABLE);
// ADC校准
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
float CalculateAmplitude(void) {
uint16_t adc_buffer[SAMPLE_COUNT];
uint16_t max_val = 0, min_val = 4095;
// 采集波形数据
for(int i=0; i<SAMPLE_COUNT; i++){
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
adc_buffer[i] = ADC_GetConversionValue(ADC1);
if(adc_buffer[i] > max_val) max_val = adc_buffer[i];
if(adc_buffer[i] < min_val) min_val = adc_buffer[i];
}
// 计算峰峰值(mV)
float vpp = (max_val - min_val) * 3300.0f / 4096.0f;
return vpp / 2.0f; // 转换为幅值
}
int main(void) {
SystemInit();
ADC_Config();
OLED_Init();
while(1) {
float amplitude = CalculateAmplitude();
OLED_Clear();
OLED_ShowString(0,0,"Amplitude:",16);
OLED_ShowNum(0,2, (uint32_t)amplitude, 4, 16);
OLED_ShowString(72,2,"mV",16);
Delay_ms(500);
}
}
```
### 三、关键实现原理
1. **ADC配置**:使用单次转换模式,239.5周期采样时间提高精度[^2]
2. **幅值计算**:通过采集200个采样点找出最大值和最小值,计算峰峰值后取半得到幅值
3. **电压转换**:根据公式$V_{in} = \frac{ADC_{value} \times 3300}{4096}$ 转换为毫伏值
4. **显示优化**:采用500ms刷新间隔避免OLED闪烁[^3]
### 四、注意事项
1. 输入信号需通过运放调理至0-3.3V范围
2. 测量频率范围受限于ADC采样率(最高1MHz信号需1MSPS采样率)
3. 建议在信号输入端增加低通滤波电路
4. 校准时可输入已知幅值信号调整计算系数
阅读全文
相关推荐













