以下是使用STM32实现蜂鸣器音乐播放的详细代码案例。
一、准备工作:
-
硬件准备:
- STM32开发板(如STM32F103C8T6)
- 蜂鸣器模块
- 杜邦线若干
-
软件准备:
- STM32CubeIDE开发环境
- STM32Cube HAL库
- CMSIS库
二、连接蜂鸣器模块: 将蜂鸣器模块的正极连接到STM32开发板的任意一个IO口(如PA0),将负极连接到GND。
三、配置STM32开发环境:
-
创建新工程: 打开STM32CubeIDE,点击“New STM32 Project”创建一个新的工程。选择正确的芯片型号和工程路径,并设置工程名称。
-
配置GPIO: 在STM32CubeIDE的“Pinout & Configuration”视图中,选择一个未被使用的GPIO引脚(如PA0),将其配置为GPIO_Output。
-
配置时钟: 在“Clock Configuration”视图中,选择适当的时钟源和时钟频率。
四、编写代码:
- 引入相关库:
#include "main.h"
#include "stm32f1xx_hal.h"
- 定义音符频率:
#define NOTE_C 261
#define NOTE_D 294
#define NOTE_E 329
#define NOTE_F 349
#define NOTE_G 392
#define NOTE_A 440
#define NOTE_B 493
#define NOTE_R 0
- 定义曲谱:
int melody[] = {
// 欢乐颂
NOTE_G, NOTE_A, NOTE_B, NOTE_C, NOTE_D, NOTE_E, NOTE_D, NOTE_C,
NOTE_B, NOTE_A, NOTE_A, NOTE_C, NOTE_E, NOTE_D, NOTE_C,
NOTE_B, NOTE_B, NOTE_C, NOTE_D, NOTE_B, NOTE_A, NOTE_A,
NOTE_C, NOTE_D, NOTE_E, NOTE_C, NOTE_A, NOTE_G, NOTE_G,
// 难忘的一天
NOTE_A, NOTE_A, NOTE_A, NOTE_F, NOTE_D, NOTE_D, NOTE_E,
NOTE_D, NOTE_D, NOTE_E, NOTE_F, NOTE_G, NOTE_A, NOTE_A,
NOTE_A, NOTE_F, NOTE_D, NOTE_D, NOTE_E, NOTE_D, NOTE_D,
NOTE_E, NOTE_F, NOTE_G, NOTE_A, NOTE_G, NOTE_F, NOTE_E, NOTE_F,
NOTE_D, NOTE_G, NOTE_G, NOTE_F, NOTE_E, NOTE_D, NOTE_C,
// 小星星
NOTE_C, NOTE_C, NOTE_G, NOTE_G, NOTE_A, NOTE_A,
NOTE_G, NOTE_F, NOTE_F, NOTE_E, NOTE_E, NOTE_D, NOTE_D,
NOTE_C, NOTE_G, NOTE_G, NOTE_F, NOTE_F, NOTE_E, NOTE_E,
NOTE_D, NOTE_G, NOTE_G, NOTE_F, NOTE_F, NOTE_E, NOTE_E,
NOTE_D, NOTE_C, NOTE_C, NOTE_G, NOTE_G, NOTE_A, NOTE_A,
NOTE_G, NOTE_F, NOTE_F, NOTE_E, NOTE_E, NOTE_D, NOTE_D,
NOTE_C
};
- 配置定时器:
TIM_HandleTypeDef htim2;
void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 7199; // 10kHz 的计数频率
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 999; // 10Hz 的 PWM 频率
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 500; // 占空比为 50%
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
}
- 初始化蜂鸣器:
void Buzzer_Init(void)
{
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}
void Buzzer_Tone(uint16_t frequency)
{
if (frequency == NOTE_R) {
HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
} else {
__HAL_TIM_SET_PRESCALER(&htim2, 7199); // 10kHz 的计数频率
__HAL_TIM_SET_COUNTER(&htim2, 0);
__HAL_TIM_SET_AUTORELOAD(&htim2, 10000 / frequency); // 10kHz / frequency 的周期
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}
}
void Buzzer_Play(void)
{
for (int i = 0; i < sizeof(melody) / sizeof(int); i++)
{
Buzzer_Tone(melody[i]);
HAL_Delay(300); // 播放每个音符持续 300ms
Buzzer_Tone(NOTE_R); // 停止发声
HAL_Delay(100); // 音符间的间隔时间为 100ms
}
}
- 主函数:
int main(void) {
HAL_Init();
SystemClock_Config();
MX_TIM2_Init();
Buzzer_Init();
while (1)
{
Buzzer_Play();
HAL_Delay(1000); // 播放完整首歌曲后休息 1s
}
}
以上代码实现了使用STM32控制蜂鸣器播放音乐。通过配置定时器,可以控制蜂鸣器发出不同频率的声音,从而实现播放不同的音符。在主函数中,通过循环播放曲谱中的音符,可以实现播放完整的音乐曲目。
注意事项:
- 定时器的配置需要根据具体的硬件和需求进行调整。
- 曲谱中的音符频率可以根据需要自行修改。
- 所使用的定时器和GPIO引脚需要根据实际情况进行配置。
希望以上代码案例能够帮助到您。如有任何问题,欢迎随时向我提问。