波形发生器对我的钱包不怎么友好,手里面有stm32f103c8t6,于是就想,放在哪儿吃灰也是吃灰,不如做个正弦波发生器。
方案
dac没怎么用过,所以打算使用输出模拟正弦波。
我们决定采用以下方案:
1.使用TIM2_CH3(PA2)输出PWM
2.使用TIM4产生中断来更新占空比
3.系统时钟72MHz
代码
以下为完整的项目代码实现:
#include "stm32f10x.h"
#include "math.h"#define PI 3.14159265f
#define SAMPLE_POINTS 256 // 正弦波采样点数
#define PWM_FREQ 10000 // PWM频率10kHz
#define SINE_FREQ 1000 // 正弦波频率1kHzuint16_t sineWave[SAMPLE_POINTS]; // 正弦波采样值
uint8_t waveIndex = 0; // 当前采样点索引// 生成正弦波查找表
void generateSineTable(void) {for(int i = 0; i < SAMPLE_POINTS; i++) {float radian = 2 * PI * i / SAMPLE_POINTS;float value = 0.5f * (1 + sinf(radian)); // 值域[0,1]sineWave[i] = (uint16_t)(value * 999); // 映射到0-999(TIM2->ARR=999)}
}// TIM4初始化(中断触发占空比更新)
void TIM4_Init(void) {RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;TIM_TimeBaseStruct.TIM_Period = (72000000 / (SINE_FREQ * SAMPLE_POINTS)) - 1; // 中断频率 = 正弦波频率×采样点数TIM_TimeBaseStruct.TIM_Prescaler = 0; // 72MHz/1 = 72MHzTIM_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStruct);TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);TIM_Cmd(TIM4, ENABLE);
}// TIM2 PWM初始化(PA2输出)
void TIM2_PWM_Init(void) {RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// PA2配置为复用推挽输出GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);// 时基配置(PWM频率)TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;TIM_TimeBaseStruct.TIM_Period = 999; // ARR值(0-999对应占空比0-100%)TIM_TimeBaseStruct.TIM_Prescaler = 7200 - 1; // 72MHz/7200 = 10kHzTIM_TimeBaseStruct.TIM_ClockDivision = 0;TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStruct);// PWM通道3配置(PA2对应TIM2_CH3)TIM_OCInitTypeDef TIM_OCStruct;TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCStruct.TIM_OutputState = TIM_OutputState_Enable;TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OCStruct.TIM_Pulse = 0; // 初始占空比TIM_OC3Init(TIM2, &TIM_OCStruct);TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);TIM_ARRPreloadConfig(TIM2, ENABLE);TIM_Cmd(TIM2, ENABLE);
}// TIM4中断服务程序(更新占空比)
void TIM4_IRQHandler(void) {if (TIM_GetITStatus(TIM4, TIM_IT_Update) == SET) {TIM_SetCompare3(TIM2, sineWave[waveIndex]); // 更新PA2占空比waveIndex = (waveIndex + 1) % SAMPLE_POINTS;TIM_ClearITPendingBit(TIM4, TIM_IT_Update);}
}int main(void) {// 系统时钟初始化SystemInit();// 关键修复:禁用JTAG释放PA15/PB3/PB4RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);// 生成正弦波表generateSineTable();// 初始化TIM2(PWM)和TIM4(中断)TIM2_PWM_Init();TIM4_Init();// 配置NVICNVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel = TIM4_IRQn;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStruct);while(1) {// 主循环无需操作}
}
RC滤波电路
PA2 → 10kΩ电阻 → 示波器
↓
100nF电容
↓
GND