????????波形發生器對我的錢包不怎么友好,手里面有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