标题:
STM32F103C8T6简易示波器程序
[打印本页]
作者:
fqs_lda
时间:
2025-1-2 18:27
标题:
STM32F103C8T6简易示波器程序
电压0-3.3V
bfe0c46d178e77a7f2c47f32cf0c53c.jpg
(99.86 KB, 下载次数: 0)
下载附件
2025-1-2 18:26 上传
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include <math.h>
#include <stdio.h>
#include "ad.h"
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
#define WAVE_SAMPLES 64 // 波形采样点数
#define WAVE_OFFSET 17 // 波形在Y轴上的偏移量
#define VOLTAGE_RANGE 3.3 // 电压范围
#define VOLTAGE_STEP 0.1 // 电压步长
#define VOLTAGE_TO_PIXEL_SCALE 14 // 电压到像素的缩放比例
int16_t wave_buffer[WAVE_SAMPLES]; // 波形缓冲区
uint16_t wave_index = 0; // 波形缓冲区索引
int16_t x,y;
double radian;
double voltage; //电压值
double phase_angle; // 相位角,范围是0到2π
double voltage_increment = VOLTAGE_STEP; // 电压增量
double sample_rate = (double)OLED_WIDTH / WAVE_SAMPLES; // 采样率
uint16_t ADValue;
#define NUM_PERIODS 10 // 要计算平均频率的周期数
double period_times[NUM_PERIODS]; // 存储周期时间间隔的数组
int period_index = 0; // 当前周期时间间隔的索引
void PWM_Init(void);
void Servo_SetAngle(float Angle);
void PWM_SetCompare2(uint16_t Compare);
void Timer3_init(uint16_t arr,uint16_t psc);
void OLED_DrawWave()
{
int16_t x_current;
int16_t y_current;
int16_t x_end = 0; // 波形结束X坐标(屏幕最左侧)
int16_t y_prev = WAVE_OFFSET; // 上一个点的Y坐标
// 绘制波形线
for (int i = 0; i < WAVE_SAMPLES; i++)
{
x_current= (OLED_WIDTH - 1) - (i * (OLED_WIDTH - 1) / (WAVE_SAMPLES - 1))/1; // 当前点的X坐标
y_current= wave_buffer[(wave_index + i) % WAVE_SAMPLES]; // 当前点的Y坐标(循环缓冲区)
// 如果当前点不是第一个点,则绘制线段
if (i > 0)
{
OLED_DrawLine(x_end, y_prev, x_current, y_current);
}
x_end = x_current; // 更新结束X坐标
y_prev = y_current; // 更新上一个点的Y坐标
}
}
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
}
int main(void)
{
uint8_t i;
double frequency_sum = 0.0;
OLED_Init();
AD_Config();
PWM_Init();
Timer3_init(10000,7200);
while(1)
{
i++;
PWM_SetCompare2(i);
ADValue = AD_GetValue();
voltage = (float)ADValue / 4095 * VOLTAGE_RANGE;
OLED_ClearArea(0, 0, OLED_WIDTH, OLED_HEIGHT);
OLED_ShowFloatNum(70,0,voltage,2,2,OLED_6X8);
// OLED_ShowFloatNum(0,0,average_frequency,2,5,OLED_6X8);
// 将新的电压值添加到波形缓冲区,并更新索引
wave_buffer[wave_index] = (int16_t)(voltage * VOLTAGE_TO_PIXEL_SCALE + WAVE_OFFSET);
wave_index = (wave_index +1) % WAVE_SAMPLES; // 循环缓冲区
OLED_DrawWave(); // 绘制波形
OLED_Update(); // 将数据更新到OLED
}
}
//int main(void)
//{
// OLED_Init();
// AD_Config();
// PWM_Init();
// while (1)
// {
// OLED_ClearArea(0,0,128,64);
//// // 将电压值线性映射到相位角上
//// phase_angle = voltage * (2 * 3.14 / 3.3); // 3.3是电压范围的最大值
//// for(x=0;x<128;x++)
//// {
//// radian=(double)x*(2*3.14/128)+phase_angle;
//// y=(int16_t)(voltage*10*sin(radian)+32);
//// OLED_DrawPoint(x, y);
//// // 确保y坐标在OLED屏幕范围内
//// if (y < 0) y = 0;
//// if (y >= 64) y = 64 - 1;
//// }
//// voltage+=0.1;
//// if(voltage>3.3)
//// {
//// voltage-=0.1;
//// }
//// if (phase_angle >= 2 * 3.14) {
//// phase_angle -= 2 * 3.14; }
//
// OLED_ShowFloatNum(20,0,voltage,1,2,OLED_8X16);
//
// ADValue = AD_GetValue();
// voltage = (float)ADValue / 4095 * 3.3;
// // 根据voltage值计算波形数据点
// for (int i = 0; i < WAVE_SAMPLES; i++)
// {
// double position = (double)i / (WAVE_SAMPLES - 1); // 当前位置(0到1之间)
// double normalized_voltage = voltage / VOLTAGE_RANGE; // 归一化电压值
// double wave_height = (sin(12 * 3.14 * position) + 1) / 2 * normalized_voltage * (OLED_HEIGHT - 2 * WAVE_OFFSET); // 计算波形高度
// wave_buffer[i] = (int16_t)(WAVE_OFFSET + wave_height+10); // 转换为整数并加上偏移量
// }
// // 绘制波形到OLED屏幕
// for (int i = 0; i < WAVE_SAMPLES - 1; i++)
// {
// OLED_DrawLine(i * sample_rate, wave_buffer[i], (i + 1) * sample_rate, wave_buffer[i + 1]);
// }
//// // 更新voltage值
//// voltage += voltage_increment;
//// if (voltage > VOLTAGE_RANGE)
//// {
//// voltage = VOLTAGE_RANGE;
//// voltage_increment = -VOLTAGE_STEP; // 开始减小voltage值
//// }
//// else if (voltage < 0.0)
//// {
//// voltage = 0.0;
//// voltage_increment = VOLTAGE_STEP; // 开始增大voltage值
//// }
// OLED_Update();//将数据更新到oled
// Delay_ms(500);
// }
//}
void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 4000-1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 72-1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1; //CCR
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_CtrlPWMOutputs(TIM2, ENABLE); //使能PWM波对外设的输出
TIM_SelectOutputTrigger(TIM2,TIM_TRGOSource_OC2Ref);//选择TIM2上升沿作为ADC触发源
TIM_Cmd(TIM2, ENABLE);
}
void Timer3_init(uint16_t arr,uint16_t psc)
{
TIM_TimeBaseInitTypeDef TIM3_TimeBaseInitStruct={0};
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
//TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x00);//使用外部时钟,关闭外部触发TIM预分频器,上升沿激活,关闭外部触发过滤器
TIM_InternalClockConfig(TIM3);//使用内部时钟
//f=72000/10000/7200=0.001
TIM3_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1 ;//时钟分频1
TIM3_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up ;//向上计数
TIM3_TimeBaseInitStruct.TIM_Period = arr;//负载重装值
TIM3_TimeBaseInitStruct.TIM_Prescaler = psc ;//预分频值
TIM3_TimeBaseInitStruct.TIM_RepetitionCounter= 0 ;//关闭重复计数(高级定时器才有)
TIM_TimeBaseInit(TIM3,&TIM3_TimeBaseInitStruct);
TIM_ClearFlag(TIM3,TIM_FLAG_Update);//清除更新中断标志位,避免初始化完就进入中断
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//使能中断
NVIC_InitTypeDef NVIC_TIM3_InitStruct={0};
NVIC_TIM3_InitStruct.NVIC_IRQChannel = TIM3_IRQn ;//中断通道
NVIC_TIM3_InitStruct.NVIC_IRQChannelCmd = ENABLE ;
NVIC_TIM3_InitStruct.NVIC_IRQChannelPreemptionPriority = 2 ;//抢占优先级
NVIC_TIM3_InitStruct.NVIC_IRQChannelSubPriority = 2 ;//响应优先级
NVIC_Init(&NVIC_TIM3_InitStruct);
TIM_Cmd(TIM3,ENABLE);
}
void PWM_SetCompare2(uint16_t Compare)
{
TIM_SetCompare2(TIM2, Compare);
}
void Servo_SetAngle(float Angle)
{
PWM_SetCompare2(Angle / 180 * 2000 + 500);
}
复制代码
原理图: 无
仿真: 无
代码:
32简易示波.7z
(189.13 KB, 下载次数: 0)
2025-1-2 22:28 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
蚂蚁科技
时间:
2025-1-3 21:39
看着很厉害的样子,有没有原理图?
作者:
长风007
时间:
2025-1-4 08:59
大将之才,可以完善一下的。
作者:
zhike
时间:
2025-1-20 11:46
STM32F103C6T6能用吗?没原理图?
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1