🎬 秋野酱:《个人主页》
🔥 个人专栏:《Java专栏》《Python专栏》
⛺️心若有所向往,何惧道阻且长
文章目录
- 需求
- 原来的驱动
- 移植操作
- 替换初始化
- 更新Play函数
- 完整代码
需求
通过控制PB9来播放音乐,PB9对应的定时器通道:Timer1 CH1
原来的驱动
#ifndef __BUZZER_H__
#define __BUZZER_H__
#include "config.h"
// 初始化蜂鸣器
void Buzzer_init();
// 按照指定频率播放
void Buzzer_play(u16 hz_val);
// 按照指定的音调播放 1,2,3,4,..7
void Buzzer_beep(u8 hz_val_index);
// 停止播放
void Buzzer_stop();
#endif
#include "Buzzer.h"
#include "GPIO.h"
#include "PWM.h"
// C D E F G A B C`
//u16 hz[] = {523, 587, 659, 698, 784, 880, 988, 1047};
// C D E F G A B C`
u16 hz[] = { 1047, 1175, 1319, 1397, 1568, 1760, 1976, 2093 };
static void GPIO_config(void) {
GPIO_InitTypeDef GPIO_InitStructure; //结构定义
GPIO_InitStructure.Pin = GPIO_Pin_0; //指定要初始化的IO,
GPIO_InitStructure.Mode = GPIO_OUT_PP; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(GPIO_P0, &GPIO_InitStructure);//初始化
}
void Buzzer_init(){
GPIO_config();
}
void Buzzer_beep(u8 hz_val_index){ // 1,2,3,4 ... 7
u16 hz_val = hz[hz_val_index - 1];
Buzzer_play(hz_val);
}
void Buzzer_play(u16 hz_val){
u16 Period = MAIN_Fosc / hz_val;
PWMx_InitDefine PWMx_InitStructure;
// 总配置
// (MAIN_Fosc / 1000 - 1) 周期计数值
PWMx_InitStructure.PWM_Period = Period - 1; //周期时间, 0~65535
PWMx_InitStructure.PWM_DeadTime = 0; //死区发生器设置, 0~255
PWMx_InitStructure.PWM_EnoSelect = ENO5P; //输出通道选择, ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8P
PWMx_InitStructure.PWM_PS_SW = PWM5_SW_P00;//切换端口
// 具体PWM端口配置
// pwm5
PWMx_InitStructure.PWM5_Mode = CCMRn_PWM_MODE1; //模式, CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2
PWMx_InitStructure.PWM5_Duty = Period / 2; //PWM4占空比时间, 0~Period 声音的大小、响度
// pwm5
PWMx_InitStructure.PWM_CC5Enable = ENABLE; //开启PWM6P输入捕获/比较输出, ENABLE,DISABLE
// PWM启动配置
PWMx_InitStructure.PWM_MainOutEnable= ENABLE; //主输出使能, ENABLE,DISABLE
PWMx_InitStructure.PWM_CEN_Enable = ENABLE; //使能计数器, ENABLE,DISABLE
PWM_Configuration(PWMB, &PWMx_InitStructure); //初始化PWM, PWMA,PWMB
}
void Buzzer_stop(){
PWMx_InitDefine PWMx_InitStructure;
PWMx_InitStructure.PWM_MainOutEnable= DISABLE; //主输出使能, ENABLE,DISABLE
PWMx_InitStructure.PWM_CEN_Enable = DISABLE; //使能计数器, ENABLE,DISABLE
PWM_Configuration(PWMB, &PWMx_InitStructure); //初始化PWM, PWMA,PWMB
}
#include "config.h"
#include "delay.h"
#include "GPIO.h"
#include "Buzzer.h"
// 两只老虎
// 音符
u8 code notes[] = {
1, 2, 3, 1, 1, 2, 3, 1, 3, 4, 5, 3, 4, 5,
5, 6, 5, 4, 3, 1, 5, 6, 5, 4, 3, 1, 1, 5, 1, 1, 5, 1,
};
// 延时时长
u8 code durations[] = {
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 8,
3, 1, 3, 1, 4, 4, 3, 1, 3, 1, 4, 4, 4, 4, 8, 4, 4, 8,
};
int main() {
u8 i = 0;
u8 len = 0;
u16 delay = 0;
Buzzer_init();
len = sizeof(notes) / sizeof(u8);
while(1) {
for(i = 0; i < len; i++){
Buzzer_beep(notes[i]);
delay = durations[i] * 100;
// 声响延时
delay_X_ms(delay);
// stop
Buzzer_stop();
delay_ms(20);
}
// stop
Buzzer_stop();
delay_ms(250);
delay_ms(250);
delay_ms(250);
delay_ms(250);
}
}
移植操作
替换初始化
void timer_gpio_config(uint32_t gpio_rcu, uint32_t gpio_port, uint32_t gpio_pin, uint32_t gpio_af){
rcu_periph_clock_enable(gpio_rcu);
/* 设置gpio模式 */
gpio_mode_set(gpio_port, GPIO_MODE_AF, GPIO_PUPD_NONE, gpio_pin);
gpio_output_options_set(gpio_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, gpio_pin);
gpio_af_set(gpio_port, gpio_af, gpio_pin);
}
void timer_init_config(uint32_t timer_periph, uint16_t t_prescaler, uint32_t t_period) {
/*初始化参数 */
timer_parameter_struct initpara;
/* initialize TIMER init parameter struct */
timer_struct_para_init(&initpara);
/* 根据需要配置值 分频系数 (可以实现更低的timer频率) */
initpara.prescaler = t_prescaler - 1;
/* 1个周期的计数(period Max: 65535) Freq >= 2564 */
initpara.period = t_period - 1;
/* initialize TIMER counter */
timer_init(timer_periph, &initpara);
/* enable a TIMER */
timer_enable(timer_periph);
}
void timer_channel_config(uint32_t timer_periph, uint16_t channel) {
/* TIMER 通道输出配置 */
timer_oc_parameter_struct ocpara;
/* initialize TIMER channel output parameter struct */
timer_channel_output_struct_para_init(&ocpara);
ocpara.outputstate = (uint16_t)TIMER_CCX_ENABLE;
/* 配置输出参数 configure TIMER channel output function */
timer_channel_output_config(timer_periph, channel, &ocpara);
/* 配置通道输出输出比较模式 configure TIMER channel output compare mode */
timer_channel_output_mode_config(timer_periph, channel, TIMER_OC_MODE_PWM0);
}
#define TIMER_RCU RCU_TIMER1
#define TIMER_PERIPH TIMER1
#define TIMER_CHANNEL TIMER_CH_1
#define PRESCALER 10
void Buzzer_init() {
// PB9 Timer1_CH1 AF2
// GPIO ----------------------------------------
timer_gpio_config(RCU_GPIOB, GPIOB, GPIO_PIN_9, GPIO_AF_1);
// TIMER----------------------------------------
rcu_periph_clock_enable(TIMER_RCU);
timer_deinit(TIMER_PERIPH);
/* 升级频率*/
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
// 通道配置 -------------------------------------
timer_channel_config(TIMER_PERIPH, TIMER_CHANNEL);
}
将原有的初始化逻辑修改为新的pwm更新
更新Play函数
// C D E F G A B C`
u16 hz[] = { 1047, 1175, 1319, 1397, 1568, 1760, 1976, 2093 };
void Buzzer_beep(u8 hz_val_index) { // 1,2,3,4 ... 7
u16 hz_val = hz[hz_val_index - 1];
Buzzer_play(hz_val);
}
void Buzzer_play(u16 hz_val) {
// 根据系统主频和分频系数,计算周期
uint16_t period = SystemCoreClock / (hz_val * PRESCALER);
// 设置分频系数和周期计数值
timer_init_config(TIMER_PERIPH, PRESCALER, period);
// 设置输出脉冲值,范围是[0, 周期计数值)
timer_channel_output_pulse_value_config(TIMER_PERIPH, TIMER_CHANNEL, (uint32_t)(period * 0.5f));
}
void Buzzer_stop() {
timer_disable(TIMER_PERIPH);
}
● 分频问题需要解决
● 分频根据hz值来设定
完整代码
#ifndef __BSP_BUZZER_H__
#define __BSP_BUZZER_H__
#include "gd32f4xx.h"
#ifndef u32
#define u32 uint32_t
#endif
#ifndef u16
#define u16 uint16_t
#endif
#ifndef u8
#define u8 uint8_t
#endif
// 初始化蜂鸣器
void Buzzer_init();
// 按照指定频率播放
void Buzzer_play(u16 hz_val);
// 按照指定的音调播放 1,2,3,4,..7
void Buzzer_beep(u8 hz_val_index);
// 停止播放
void Buzzer_stop();
#endif
#include "bsp_buzzer.h"
// C D E F G A B C`
//u16 hz[] = {523, 587, 659, 698, 784, 880, 988, 1047};
// C D E F G A B C`
u16 hz[] = { 1047, 1175, 1319, 1397, 1568, 1760, 1976, 2093 };
// >= 2564
void timer_gpio_config(uint32_t gpio_rcu, uint32_t gpio_port, uint32_t gpio_pin, uint32_t gpio_af){
rcu_periph_clock_enable(gpio_rcu);
/* 设置gpio模式 */
gpio_mode_set(gpio_port, GPIO_MODE_AF, GPIO_PUPD_NONE, gpio_pin);
gpio_output_options_set(gpio_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, gpio_pin);
gpio_af_set(gpio_port, gpio_af, gpio_pin);
}
void timer_init_config(uint32_t timer_periph, uint16_t t_prescaler, uint32_t t_period) {
/*初始化参数 */
timer_parameter_struct initpara;
/* initialize TIMER init parameter struct */
timer_struct_para_init(&initpara);
/* 根据需要配置值 分频系数 (可以实现更低的timer频率) */
initpara.prescaler = t_prescaler - 1;
/* 1个周期的计数(period Max: 65535) Freq >= 2564 */
initpara.period = t_period - 1;
/* initialize TIMER counter */
timer_init(timer_periph, &initpara);
/* enable a TIMER */
timer_enable(timer_periph);
}
void timer_channel_config(uint32_t timer_periph, uint16_t channel) {
/* TIMER 通道输出配置 */
timer_oc_parameter_struct ocpara;
/* initialize TIMER channel output parameter struct */
timer_channel_output_struct_para_init(&ocpara);
ocpara.outputstate = (uint16_t)TIMER_CCX_ENABLE;
/* 配置输出参数 configure TIMER channel output function */
timer_channel_output_config(timer_periph, channel, &ocpara);
/* 配置通道输出输出比较模式 configure TIMER channel output compare mode */
timer_channel_output_mode_config(timer_periph, channel, TIMER_OC_MODE_PWM0);
}
#define TIMER_RCU RCU_TIMER1
#define TIMER_PERIPH TIMER1
#define TIMER_CHANNEL TIMER_CH_1
#define PRESCALER 10
void Buzzer_init() {
// PB9 Timer1_CH1 AF2
// GPIO ----------------------------------------
timer_gpio_config(RCU_GPIOB, GPIOB, GPIO_PIN_9, GPIO_AF_1);
// TIMER----------------------------------------
rcu_periph_clock_enable(TIMER_RCU);
timer_deinit(TIMER_PERIPH);
/* 升级频率*/
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
// 通道配置 -------------------------------------
timer_channel_config(TIMER_PERIPH, TIMER_CHANNEL);
}
void Buzzer_beep(u8 hz_val_index) { // 1,2,3,4 ... 7
u16 hz_val = hz[hz_val_index - 1];
Buzzer_play(hz_val);
}
void Buzzer_play(u16 hz_val) {
// 根据系统主频和分频系数,计算周期
uint16_t period = SystemCoreClock / (hz_val * PRESCALER);
// 设置分频系数和周期计数值
timer_init_config(TIMER_PERIPH, PRESCALER, period);
// 设置输出脉冲值,范围是[0, 周期计数值)
timer_channel_output_pulse_value_config(TIMER_PERIPH, TIMER_CHANNEL, (uint32_t)(period * 0.5f));
}
void Buzzer_stop() {
timer_disable(TIMER_PERIPH);
}