漂亮网站首页 html,廊坊网站建设技术外包,影视传媒广告公司网站模板,wordpress只能打开首页1. 硬件准备
STM32开发板#xff1a;STM32F407系列蜂鸣器#xff1a;常见的蜂鸣器分为两类#xff1a;有源蜂鸣器和无源蜂鸣器。若使用有源蜂鸣器#xff0c;只需提供电源和控制信号即可#xff1b;若使用无源蜂鸣器#xff0c;则需要控制频率。外接电源#xff08;可选…1. 硬件准备
STM32开发板STM32F407系列蜂鸣器常见的蜂鸣器分为两类有源蜂鸣器和无源蜂鸣器。若使用有源蜂鸣器只需提供电源和控制信号即可若使用无源蜂鸣器则需要控制频率。外接电源可选确保为蜂鸣器提供足够的电源。
以下是蜂鸣器的原理图 2. 选择控制方式
对于音乐播放主要使用PWM脉宽调制信号来控制蜂鸣器的发声频率。通过改变PWM的占空比和频率可以模拟不同的音调和音量。
3. GPIO配置
将蜂鸣器连接到STM32的某一个GPIO口比如PA8或PB5。该GPIO口配置为输出模式。
4. 定时器配置
要通过PWM信号控制蜂鸣器的频率我们通常使用STM32的定时器模块来产生PWM信号。
选择定时器选择一个适合的定时器比如TIM2或TIM3。配置定时器设置定时器的计数频率计算所需的PWM频率比如440Hz对应音乐中的A4音符。
5. 计算音符频率 6. PWM输出控制
通过定时器配置的PWM输出控制蜂鸣器的发声。需要设置
PWM周期对应音符的频率。PWM占空比设置蜂鸣器的响度通常为50%即高电平和低电平的时间相等。
7. 编写代码
1编写一个延时函数
/* 延时函数 */
void delay_ms(uint32_t n)
{while(n--){SysTick-CTRL 0; /* 关闭系统定时器才能对系统定时器进行配置 */SysTick-LOAD 168000-1; /* 设置定时器重载值168MHz 时钟频率下每毫秒的计数值168000 - 1 表示定时器计数到 167999 之后产生中断这相当于 1 毫秒168 MHz 时钟*/SysTick-VAL 0; /* 清空当前计数值还有清空COUNTFLAG标志位 */SysTick-CTRL 5; /* 启动定时器使用处理器时钟频率168 MHz并使能定时器5 是控制寄存器的值低 2 位分别设置时钟源和使能定时器*//* 等待计时器计数完毕。通过检查 COUNTFLAG 标志位CTRL寄存器的 16 位*/while ((SysTick-CTRL 0x10000)0);//等待COUNTFLAG标志位置1就是计数完毕}SysTick-CTRL 0; /* 关闭系统定时器 释放资源 */}
2初始化GPIO和定时器 void led_init(void)
{/* 打开端口E F的硬件时钟就是对硬件供电默认状态下所有时钟都是关闭 */RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOF,ENABLE);GPIO_InitStructure.GPIO_PinGPIO_Pin_8;//指定9引脚GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF;//引脚工作在复用功能模式GPIO_InitStructure.GPIO_SpeedGPIO_Speed_100MHz;//速度越高响应时间越短但是功耗就越高电磁干扰也越高GPIO_InitStructure.GPIO_OTypeGPIO_OType_PP;//如果外部没有上拉电阻就配置推挽输出模式GPIO_InitStructure.GPIO_PuPdGPIO_PuPd_NOPULL;//不需要使能上下拉电阻GPIO_Init(GPIOF,GPIO_InitStructure);GPIO_InitStructure.GPIO_PinGPIO_Pin_13;//指定13 14号引脚GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF;//引脚工作在输出模式GPIO_InitStructure.GPIO_SpeedGPIO_Speed_100MHz;//速度越高响应时间越短但是功耗就越高电磁干扰也越高GPIO_InitStructure.GPIO_OTypeGPIO_OType_PP;//如果外部没有上拉电阻就配置推挽输出模式GPIO_InitStructure.GPIO_PuPdGPIO_PuPd_NOPULL;//不需要使能上下拉电阻GPIO_Init(GPIOE,GPIO_InitStructure); GPIO_InitStructure.GPIO_PinGPIO_Pin_14;//指定13 14号引脚GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF;//引脚工作在输出模式GPIO_InitStructure.GPIO_SpeedGPIO_Speed_100MHz;//速度越高响应时间越短但是功耗就越高电磁干扰也越高GPIO_InitStructure.GPIO_OTypeGPIO_OType_PP;//如果外部没有上拉电阻就配置推挽输出模式GPIO_InitStructure.GPIO_PuPdGPIO_PuPd_NOPULL;//不需要使能上下拉电阻GPIO_Init(GPIOE,GPIO_InitStructure);
}
void tim13_init(void)
{/* 打开TIM13的硬件时钟对TIM13供电 */RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13,ENABLE); /* 配置TIM13分频值、计数值、时间更新中断 */TIM_TimeBaseStructure.TIM_Period 10000/100-1; //输出频率为100Hz 计数值0~99 当完成100个计数就输出一个脉冲TIM_TimeBaseStructure.TIM_Prescaler 8400-1;//进行8400的分频84MHz/(8400-11)//TIM_TimeBaseStructure.TIM_ClockDivision TIM_CKD_DIV2;//不会生效TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up;//向上计数TIM_TimeBaseInit(TIM13, TIM_TimeBaseStructure);/* 配置TIM13的通道1 */TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable;//使能脉冲输出TIM_OCInitStructure.TIM_Pulse 0;//比较值0蜂鸣器为关闭状态TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_High;//有效状态为高电平TIM_OC1Init(TIM13, TIM_OCInitStructure);/* 使能TIM13工作 */TIM_Cmd(TIM13, ENABLE);
}
3播放音符
接下来可以通过控制定时器的TIM_Period值来控制音符的频率。
void tim13_set_freq(uint32_t freq)
{/* 关闭TIM13 */TIM_Cmd(TIM13, DISABLE);/*定时器的基本配置用于配置定时器的输出脉冲的频率为 freq Hz */TIM_TimeBaseStructure.TIM_Period (400000/freq)-1; //设置定时脉冲的频率TIM_TimeBaseStructure.TIM_Prescaler 210-1; //第一次分频简称为预分频TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up;tim13_cnt TIM_TimeBaseStructure.TIM_Period;TIM_TimeBaseInit(TIM13, TIM_TimeBaseStructure);/* 使能TIM13 */TIM_Cmd(TIM13, ENABLE);
}void tim13_set_duty(uint32_t duty)
{uint32_t cmp0;cmp (tim13_cnt1) * duty/100;TIM_SetCompare1(TIM13,cmp);
}
8. 实现音乐播放
通过将每个音符的频率和时长传入依次播放不同的音符。可以使用延时函数来控制每个音符的播放时长。 源代码
#include stm32f4xx.h#define PEout(n) (*(uint32_t *)(0x42000000(GPIOE_BASE0x14-0x40000000)*32n*4))
#define PFout(n) (*(uint32_t *)(0x42000000(GPIOF_BASE0x14-0x40000000)*32n*4))GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;static uint32_t tim13_cnt0;/* 毫秒延时函数 */
void delay_ms(uint32_t n)
{while(n--){SysTick-CTRL 0; /* 关闭系统定时器才能对系统定时器进行配置 */SysTick-LOAD 168000-1; /* 设置定时器重载值168MHz 时钟频率下每毫秒的计数值168000 - 1 表示定时器计数到 167999 之后产生中断这相当于 1 毫秒168 MHz 时钟*/SysTick-VAL 0; /* 清空当前计数值还有清空COUNTFLAG标志位 */SysTick-CTRL 5; /* 启动定时器使用处理器时钟频率168 MHz并使能定时器5 是控制寄存器的值低 2 位分别设置时钟源和使能定时器*//* 等待计时器计数完毕。通过检查 COUNTFLAG 标志位CTRL寄存器的 16 位*/while ((SysTick-CTRL 0x10000)0);//等待COUNTFLAG标志位置1就是计数完毕}SysTick-CTRL 0; /* 关闭系统定时器 释放资源 */}void delay_us(uint32_t n)
{SysTick-CTRL 0; // 关闭系统定时器才能对系统定时器进行配置SysTick-LOAD 168*n-1; // Count from 167 to 0 (168 cycles)SysTick-VAL 0; // Clear current value as well as count flag清空当前计数值还有清空COUNTFLAG标志位SysTick-CTRL 5; // Enable SysTick timer with processor clock使用处理器时钟频率168MHz并使能系统定时器while ((SysTick-CTRL 0x10000)0);// Wait until count flag is set等待COUNTFLAG标志位置1就是计数完毕SysTick-CTRL 0; // Disable SysTick关闭系统定时器 }void led_init(void)
{/* 打开端口E F的硬件时钟就是对硬件供电默认状态下所有时钟都是关闭 */RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOF,ENABLE);GPIO_InitStructure.GPIO_PinGPIO_Pin_8;//指定9引脚GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF;//引脚工作在复用功能模式GPIO_InitStructure.GPIO_SpeedGPIO_Speed_100MHz;//速度越高响应时间越短但是功耗就越高电磁干扰也越高GPIO_InitStructure.GPIO_OTypeGPIO_OType_PP;//如果外部没有上拉电阻就配置推挽输出模式GPIO_InitStructure.GPIO_PuPdGPIO_PuPd_NOPULL;//不需要使能上下拉电阻GPIO_Init(GPIOF,GPIO_InitStructure);GPIO_InitStructure.GPIO_PinGPIO_Pin_13;//指定13 14号引脚GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF;//引脚工作在输出模式GPIO_InitStructure.GPIO_SpeedGPIO_Speed_100MHz;//速度越高响应时间越短但是功耗就越高电磁干扰也越高GPIO_InitStructure.GPIO_OTypeGPIO_OType_PP;//如果外部没有上拉电阻就配置推挽输出模式GPIO_InitStructure.GPIO_PuPdGPIO_PuPd_NOPULL;//不需要使能上下拉电阻GPIO_Init(GPIOE,GPIO_InitStructure); GPIO_InitStructure.GPIO_PinGPIO_Pin_14;//指定13 14号引脚GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF;//引脚工作在输出模式GPIO_InitStructure.GPIO_SpeedGPIO_Speed_100MHz;//速度越高响应时间越短但是功耗就越高电磁干扰也越高GPIO_InitStructure.GPIO_OTypeGPIO_OType_PP;//如果外部没有上拉电阻就配置推挽输出模式GPIO_InitStructure.GPIO_PuPdGPIO_PuPd_NOPULL;//不需要使能上下拉电阻GPIO_Init(GPIOE,GPIO_InitStructure);
}void tim13_init(void)
{/* 打开TIM13的硬件时钟对TIM13供电 */RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13,ENABLE); /* 配置TIM13分频值、计数值、时间更新中断 */TIM_TimeBaseStructure.TIM_Period 10000/100-1; //输出频率为100Hz 计数值0~99 当完成100个计数就输出一个脉冲TIM_TimeBaseStructure.TIM_Prescaler 8400-1;//进行8400的分频84MHz/(8400-11)//TIM_TimeBaseStructure.TIM_ClockDivision TIM_CKD_DIV2;//不会生效TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up;//向上计数TIM_TimeBaseInit(TIM13, TIM_TimeBaseStructure);/* 配置TIM13的通道1 */TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable;//使能脉冲输出TIM_OCInitStructure.TIM_Pulse 0;//比较值0蜂鸣器为关闭状态TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_High;//有效状态为高电平TIM_OC1Init(TIM13, TIM_OCInitStructure);/* 使能TIM13工作 */TIM_Cmd(TIM13, ENABLE);
}void tim13_set_freq(uint32_t freq)
{/* 关闭TIM13 */TIM_Cmd(TIM13, DISABLE);/*定时器的基本配置用于配置定时器的输出脉冲的频率为 freq Hz */TIM_TimeBaseStructure.TIM_Period (400000/freq)-1; //设置定时脉冲的频率TIM_TimeBaseStructure.TIM_Prescaler 210-1; //第一次分频简称为预分频TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up;tim13_cnt TIM_TimeBaseStructure.TIM_Period;TIM_TimeBaseInit(TIM13, TIM_TimeBaseStructure);/* 使能TIM13 */TIM_Cmd(TIM13, ENABLE);
}void tim13_set_duty(uint32_t duty)
{uint32_t cmp0;cmp (tim13_cnt1) * duty/100;TIM_SetCompare1(TIM13,cmp);
}/* 主函数 */
int main(void)
{ led_init();/* PF8连接到TIM13 */GPIO_PinAFConfig(GPIOF, GPIO_PinSource8, GPIO_AF_TIM13);tim13_init();while(1){/* 设置频率为523Hz占空比15% */tim13_set_freq(523);tim13_set_duty(15);delay_ms(500); // 延时500ms确保每个音符的持续时间/* 设置频率为587Hz占空比15% */tim13_set_freq(587);tim13_set_duty(15);delay_ms(500);/* 设置频率为659Hz占空比15% */tim13_set_freq(659);tim13_set_duty(15);delay_ms(500);/* 设置频率为698Hz占空比15% */tim13_set_freq(698);tim13_set_duty(15);delay_ms(500);/* 设置频率为784Hz占空比15% */tim13_set_freq(784);tim13_set_duty(15);delay_ms(500);/* 设置频率为880Hz占空比15% */tim13_set_freq(880);tim13_set_duty(15);delay_ms(500);/* 设置频率为988Hz占空比15% */tim13_set_freq(988);tim13_set_duty(15);delay_ms(500);}
} 可以在STM32上使用定时器和PWM信号控制蜂鸣器实现简单的音乐播放。可以根据需要添加更多音符生成完整的曲谱甚至实现更复杂的音效和音量控制。