7.1 实验内容
通过本实验主要学习以下内容:
• PWM输出功能实现;
• 定时器基本原理;
• 蜂鸣器驱动原理;
7.2 实验原理
7.2.1 蜂鸣器驱动原理
蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。比如台式电脑的主机开机会"滴"一声、洗衣机按下按键及洗衣完成都会有声响,以上这些声音都是通过蜂鸣器来发出的。蜂鸣器的驱动方式可分为:有源蜂鸣器(内有驱动线路)和无源蜂鸣器(使用外部驱动)。这里的“源”不是指电源。而是指震荡源。 也就是说,有源蜂鸣器内部带震荡源,所以只要一通电就会叫。而无源内部不带震荡源,所以如果用直流信号无法令其鸣叫。必须用2K~5K的方波去驱动它。
有源蜂鸣器不需要外部的激励源,只需要接入直流电源,即可自动发出声音(声音频率相对固定),它的工作发声原理是:直流电源输入经过振荡系统的放大取样电路在谐振装置作用下产生声音信号。
7.2.2 定时器基本原理
GD32F30X系列MCU的timer主要有以下五类,主要包括高级定时器/通用定时器L0/通用定时器L1/通用定时器L2/基本定时器。各个定时器支持的功能可在该表中查阅,其中黑点代表改类型的定时器支持该功能,X代表改类型的定时器不支持该功能。
定时器可支持主从模式,可实现多个定时器级联,相关定时器的级联信号说明如下表所示。以TIMER0为例,其触发信号可以选择TIMER4_TRGO/TIMER1_TRGO/TIMER2_TRGO/TIMER3_TRGO。
以TIMER1为例,其主要特性如下:
◼ 总通道数: 4;
◼ 计数器宽度: 16位;
◼ 时钟源可选:内部时钟,内部触发,外部输入,外部触发;
◼ 多种计数模式:向上计数,向下计数和中央计数;
◼ 正交编码器接口:被用来追踪运动和分辨旋转方向和位置;
◼ 霍尔传感器接口:用来做三相电机控制;
◼ 可编程的预分频器: 16位,运行时可以被改变;
◼ 每个通道可配置:输入捕获模式,输出比较模式,可编程的PWM模式,单脉冲模式;
◼ 自动重装载功能;
◼ 中断输出和DMA请求:更新事件,触发事件,比较/捕获事件;
◼ 多个定时器的菊链使得一个定时器可以同时启动多个定时器;
◼ 定时器的同步允许被选择的定时器在同一个时钟周期开始计数;
◼ 定时器主-从管理。
本例程主要使用TIMER1 PWM模式对蜂鸣器进行驱动,在此简单介绍PWM输出功能。
PWM输出有两种模式:PWM模式0和PWM模式1,其配置在CHxCOMCTL寄存器中,具体说明如下。
根据计数模式,PWM输出分为两种波形:
• EAPWM(边沿对齐 PWM)
EAPWM 的周期由 TIMERx_CAR 寄存器值决定,占空比由 TIMERx_CHxCV 寄存器值决定。下图显示了 EAPWM 的输出波形和中断。
• CAPWM(中央对齐PWM)
CAPWM 的周期由(2*TIMERx_CAR 寄存器值)决定,占空比由(2*TIMERx_CHxCV 寄存器值)决定。 下图显示了 CAPWM 的输出波形和中断。
7.3 硬件设计
蜂鸣器驱动电路如下图所示,在本例程中,通过BEEP_PWM(PA15)引脚驱动三极管实现蜂鸣器的驱动,当BEEP_PWM输出高电平时,三极管导通,蜂鸣器鸣叫;当BEEP_PWM输出低电平时,三极管截断,蜂鸣器停止鸣叫。
当我们通直流电到有源蜂鸣器的时候,它会发送预设的声音,通常是连续的蜂鸣声或间歇的蜂鸣声等。 工作电压不变,改变通断时间,获得不同的长音,如连续声,快短声,慢长声等。
7.4 代码解析
本例程实现通过调整PWM的周期占空比以及对应PWM输出的时间,实现不同音调的蜂鸣器播放,进而实现模拟音乐播放的效果,例程中模拟的是孤勇者的音乐。
7.4.1 主函数代码解析
主函数如下所示,主要包括串口/LED初始化,蜂鸣器PWM初始化,TIMER初始化(该timer仅实现基本定时的功能,通过该timer控制蜂鸣器PWM输出时间),以及启动蜂鸣器等。
C
int main(void)
{
uint16_t t=0;
driver_init();
bsp_uart_init(&BOARD_UART);
bsp_led_group_init();
bsp_led_on(&LED0);
bsp_led_off(&LED1);
bsp_beep_init(1000000,50);
TIMER_INT.timer_updata_callback=Music_switch;
bsp_timer_init(10000,5000);
buzzer_on();
printf("\r\n Bepp music play\r\n");
while(1)
{
if(int_flag==1)
{
int_flag=0;
t++;
bsp_led_toggle(&LED0);
printf("\r\n Bepp music play loop %d\r\n",t);
}
}
}
7.4.2 蜂鸣器PWM配置函数
蜂鸣器PWM配置函数如下所示,通过调用driver_timer_channel_init底层驱动函数实现对对应TIMER周期和占空比的配置。
C
void bsp_beep_init(uint32_t counter_frequency,uint16_t period)
{
driver_timer_channel_init(&PWM_BEEP,counter_frequency,period);
}
PWM_BEEP的定义如下,采用TIMER1的CH0通道进行输出,引脚为PA15,通过该定义可实现对蜂鸣器相关参数的一站式定义。
C
TIMER_CH_DEF(PWM_BEEP,TIMER1,0,TIMER_CH_PWM_HIGH,A,15,AF_PP,GPIO_TIMER1_PARTIAL_REMAP0);
7.4.3 基本定时器初始化函数
基本定时器初始化函数如下,启动了TIMER5作为中断功能,定时周期为10000个定时器时钟,其回调函数为Music_switch。
C
TIMER_INT.timer_updata_callback=Music_switch;
bsp_timer_init(10000,5000);
void bsp_timer_init(uint32_t counter_frequency,uint16_t period)
{
driver_timer_base_int_init(&TIMER_INT,counter_frequency,period);
nvic_irq_enable(TIMER5_IRQn,0,0);
}
TIMER_BASE_DEF(TIMER_INT,TIMER5);
Music_switch的定义如下,该函数在TIMER5的中断中调用,该函数实现的功能主要为配置修改TIMER5的周期以及蜂鸣器PWM输出的周期占空比,进而实现对不同音调的播放。
C
void Music_switch(void)
{
static uint16_t i=0;
buzzer_set(music[i],12);
i++;
bsp_timer_init(10000,music[i]*50);
i++;
if( i==(sizeof(music)/sizeof(music[0])) )
{
i=0;
bsp_led_toggle(&LED1);
int_flag=1;
}
}
音乐的相关数据定义在music数组中,其参数含义如下:M6代表蜂鸣器PWM的周期,下一个50代表该PWM输出的时间(对应TIEMR5的周期),以上两个数据一组,后面的数据类似。
C
uint16_t music[]=
{
// //这一路上走走停停 顺着少年漂流的痕迹
// M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,50,M3,50,M5,50,M3,50, M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,25,M3,25,M2,25,M1,25,L6,100,Z0,10,
// //迈出车站的前一刻 竟有些犹豫
// M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,50,M3,50,M5,50,M3,50, M2,50,M2,50,M3,25,M2,50,M1,50,M2,100,Z0,50,
// //不仅笑着这近乡情怯 仍无法避免
// M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,50,M3,50,M5,50,M3,50, M2,50,M2,50,M3,25,M2,50,M1,50,L6,100,Z0,10,
// //而长野的天 依旧那么暖 风吹起了从前
// M3,25,M2,25,M1,25,M2,25,M1,100, M3,25,M2,25,M1,25,M2,25,M1,50,M1,50, M5,25,M3,25,M2,25,M1,25,M2,25,M1,100,M1,150,Z0,30,
// //从前初识这世间 万般留恋 看着天边似在眼前 也甘愿赴汤蹈火去走它一遍
// M1,50,M2,50,M3,50,M1,50,M6,50,M5,25,M6,25,M6,50,M6,50, M1,25,M7,50,M6,25,M7,25,M7,100,Z0,5, M7,50,M6,25,M7,25,M7,50,M3,50,H1,25,H2,25,H1,25,M7,25,M6,50,M5,50, M6,50,M5,25,M6,25,M6,25,M5,25,M6,25,M5,25,M6,50,M5,25,M2,25,M2,25,M5,50,M5,50,M3,100,M3,100,Z0,25,
// //如今走过这世间 万般留恋 翻过岁月不同侧脸 措不及防闯入你的笑颜
// M1,50,M2,50,M3,50,M1,50,M6,50,M5,25,M6,25,M6,50,M6,50, M1,25,M7,50,M6,25,M7,25,M7,100,Z0,5, M7,50,M6,25,M7,25,M7,50,M3,50,H1,25,H2,25,H1,25,M7,25,M6,50,M5,50, M6,50,H3,25,H3,25,H3,50,M5,50,M6,50,H3,25,H3,25,H3,25,M5,50,M6,25,M6,100,M6,100,M6,100,Z0,25,
// //我曾难自拔与世界之大 也沉溺于其中梦话
// H1,50,H2,50,H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H2,25,H3,25,H3,50, H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,25,H3,50,H3,50,
// //不得真假 不做挣扎 不惧笑话
// H2,50,H1,25,M6,25,M6,25,H1,50, M6,25,H2,25,H1,25,M6,50,M6,25,H1,50,H1,50, H3,100,H3,25,H4,25,H3,50,H3,25,H2,50,H2,50,Z0,25,
// //我曾将青春翻涌成她 也曾指尖弹出盛夏 心之所动且就随缘去吧
// H1,50,H2,50,H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H2,50, H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H3,50,H3,50, H2,50,H1,25,M6,25,M6,25,H3,50,H3,50, H2,50,H1,25,M6,25,M6,25,H1,50,H1,50,H1,100,H1,100,Z0,10,
// //逆着光行走任风吹雨打吧
// M6,25,H3,50,H3,50,H2,50,H1,25,M6,25,M6,25,H3,50,H2,50,H1,25,M6,25,M6,25,H1,50,H1,50,H1,50,H1,100,Z0,10,
M6,50,M7,50,H1,50,H2,50,M7,50,H1,50,H1,100,Z0,10, //爱你孤身走暗巷
H1,50,M7,50,H1,50,H2,50,M7,50,H1,50,H1,100,Z0,10, //爱你不跪的模样
H1,50,H2,50,H3,50,H2,50,H3,50,H2,50,H3,100,H3,50,H3,50,H2,50,H3,100,H5,100,H3,100,Z0,10 //爱你对峙过绝望不肯哭一场
};
7.5 实验结果
将本例程烧录到红枫派开发板中,运行后将会通过蜂鸣器听到相关音乐,具体可听以下视频声音。
相关实验视频,请看飞书文档
红枫派开发板使用手册:GD32F303红枫派使用手册 - 飞书云文档 (feishu.cn)