STM32F103C8T6驱动无源蜂鸣器播放《两只老虎》完整教程(附源码)
STM32F103C8T6驱动无源蜂鸣器播放《两只老虎》完整教程附源码蜂鸣器作为嵌入式开发中最基础的外设之一常被用于系统报警、状态提示等场景。但你是否想过通过精确控制PWM频率和节奏可以让这个简单的元件演奏出熟悉的旋律本文将带你用STM32的TIM定时器实现无源蜂鸣器播放《两只老虎》的完整过程。1. 硬件准备与原理分析1.1 无源蜂鸣器工作特性无源蜂鸣器与有源蜂鸣器的核心区别在于驱动方式有源蜂鸣器内置振荡电路只需提供直流电压即可发声无源蜂鸣器需要外部提供方波信号才能工作音乐播放场景必须使用无源蜂鸣器因为音高由驱动频率决定C4261HzD4294Hz等音长由信号持续时间控制可通过PWM精确调节波形特性1.2 STM32的PWM生成机制STM32F103C8T6通过TIM定时器产生PWM信号的关键配置参数参数作用计算公式ARR (Auto-reload)决定PWM周期频率 定时器时钟/(PSC1)/(ARR1)PSC (Prescaler)时钟预分频系数实际时钟 72MHz/(PSC1)CCR (Capture Compare)决定占空比占空比 CCR/(ARR1)提示音乐播放时通常固定50%占空比重点调节ARR值改变频率2. 音乐编程基础2.1 音阶频率对照表《两只老虎》主要使用中音区(C4-B4)的七个基本音阶音符频率(Hz)计算值(ARR) PSC71C4261.633830D4293.663412E4329.633040F4349.232870G4392.002558A4440.002279B4493.882032计算公式ARR (72000000 / (PSC1)) / frequency - 1 (72000000 / 72) / frequency - 1 1000000 / frequency - 12.2 节拍时间控制四四拍歌曲的典型节拍时长BPM120时节拍类型持续时间(ms)全音符2000二分音符1000四分音符500八分音符250《两只老虎》简谱对应的节拍序列C4(1) D4(1) E4(1) C4(1) | C4(1) D4(1) E4(1) C4(1) | E4(1) F4(1) G4(2) | E4(1) F4(1) G4(2) | G4(0.5) A4(0.5) G4(0.5) F4(0.5) E4(1) C4(1) | G4(0.5) A4(0.5) G4(0.5) F4(0.5) E4(1) C4(1) | C4(1) G3(1) C4(2) | C4(1) G3(1) C4(2) |3. 工程实现步骤3.1 硬件连接使用STM32F103C8T6最小系统板与无源蜂鸣器模块连接蜂鸣器 → PA0 (TIM2_CH1) 蜂鸣器- → GND注意无源蜂鸣器没有极性但需串联100Ω限流电阻3.2 代码实现3.2.1 PWM初始化配置// pwm.h #define BUZZER_TIM TIM2 #define BUZZER_CHANNEL TIM_CHANNEL_1 void PWM_Init(void); void PWM_SetFreq(uint16_t freq); void PWM_PlayNote(uint16_t freq, uint32_t duration);// pwm.c #include stm32f10x.h void PWM_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; TIM_TimeBaseInitTypeDef TIM_InitStruct; TIM_OCInitTypeDef TIM_OCInitStruct; // 1. 开启时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 2. 配置GPIO GPIO_InitStruct.GPIO_Pin GPIO_Pin_0; GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStruct); // 3. 配置定时器基础 TIM_InitStruct.TIM_Period 999; // 初始10kHz TIM_InitStruct.TIM_Prescaler 71; // 72MHz/721MHz TIM_InitStruct.TIM_ClockDivision TIM_CKD_DIV1; TIM_InitStruct.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(BUZZER_TIM, TIM_InitStruct); // 4. 配置PWM输出 TIM_OCInitStruct.TIM_OCMode TIM_OCMode_PWM1; TIM_OCInitStruct.TIM_OutputState TIM_OutputState_Enable; TIM_OCInitStruct.TIM_OCPolarity TIM_OCPolarity_High; TIM_OCInitStruct.TIM_Pulse 500; // 50%占空比 TIM_OC1Init(BUZZER_TIM, TIM_OCInitStruct); TIM_Cmd(BUZZER_TIM, ENABLE); } void PWM_SetFreq(uint16_t freq) { uint16_t arr (uint16_t)(1000000 / freq) - 1; TIM_SetAutoreload(BUZZER_TIM, arr); TIM_SetCompare1(BUZZER_TIM, arr / 2); // 保持50%占空比 }3.2.2 音乐播放逻辑// music.h typedef struct { uint16_t freq; uint16_t duration; } Note; #define TEMPO 120 // BPM #define QUARTER_NOTE (60000 / TEMPO) extern const Note song[]; extern const uint16_t song_length;// music.c #include music.h const Note song[] { {262, QUARTER_NOTE}, // C4 {294, QUARTER_NOTE}, // D4 {330, QUARTER_NOTE}, // E4 {262, QUARTER_NOTE}, // C4 // ... 完整乐谱 }; const uint16_t song_length sizeof(song)/sizeof(Note);3.2.3 主程序// main.c #include stm32f10x.h #include pwm.h #include music.h #include delay.h int main(void) { Delay_Init(); PWM_Init(); while(1) { for(int i0; isong_length; i) { PWM_SetFreq(song[i].freq); Delay_ms(song[i].duration); } PWM_SetFreq(0); // 停止发声 Delay_ms(2000); // 间隔2秒 } }4. 进阶优化技巧4.1 节拍精度提升使用SysTick定时器替代Delay_ms实现更精确的节奏控制void SysTick_Handler(void) { static uint32_t counter 0; if(counter note_duration) { counter 0; play_next_note(); } }4.2 多任务处理在RTOS环境中创建独立播放任务void buzzer_task(void *params) { while(1) { play_song(two_tigers); vTaskDelay(pdMS_TO_TICKS(5000)); } } xTaskCreate(buzzer_task, Buzzer, 128, NULL, 2, NULL);4.3 音效增强通过调制PWM占空比实现音色变化void PWM_SetEnvelope(uint16_t freq, uint16_t duration) { // 淡入效果 for(int i1; i10; i) { TIM_SetCompare1(BUZZER_TIM, (ARR/i)); Delay_ms(duration/20); } // 淡出效果 for(int i10; i1; i--) { TIM_SetCompare1(BUZZER_TIM, (ARR/i)); Delay_ms(duration/20); } }
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2544341.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!