实验目的
了解STM32时钟复用技术,并实现实现蜂鸣器奏乐
实验器材
操作系统:Windows 10 家庭中文版
软件:keil5(编译)、source insight4.0(写程序)、Proteus8.8(仿真运行)
仿真器件:STM32F401VE芯片、LED灯、电阻、电容
实验代码
rj_buzzer.c
#include "stm32f4xx.h"
#include "main.h"
#include "systick.h"
#define ZERO 3000//
#define R 10000 //F_CLOCK/(N+1)=10000
#define L1 (R/262)-1 //DO
#define half_L1 (R/277)-1 //#1低音DO#
#define L2 (R/294)-1
#define half_L2 (R/311)-1
#define L3 (R/330)-1
#define L4 (R/349)-1
#define half_L4 (R/370)-1
#define L5 (R/392)-1
#define half_L5 (R/410)-1
#define L6 (R/440)-1
#define half_L6 (R/466)-1
#define L7 (R/494)-1
#define M1 (R/523)-1 //中音DO
#define half_M1 ??R/554)-1 //#1 DO#
#define M2 (R/587)-1
#define half_M2 (R/622)-1
#define M3 (R/659)-1
#define M4 (R/698)-1
#define half_M4 (R/740)-1
#define M5 (R/784)-1
#define half_M5 (R/831)-1
#define M6 (R/880)-1
#define half_M6 (R/932)-1
#define M7 (R/988)-1
#define H1 (R/1046)-1 //高音DO
#define half_H1 ??R/1109)-1 //#1DO#
#define H2 (R/1175)-1
#define half_H2 (R/1245)-1
#define H3 (R/1318)-1
#define H4 (R/1397)-1
#define half_H4 (R/1480)-1
#define H5 (R/1568)-1
#define half_H5 (R/1661)-1
#define H6 (R/1760)-1
#define half_H6 (R/1865)-1
#define H7 (R/1967)-1
int flag=1;//标志
int x;
//音符数组
int tune[] =
{
H1,M7,H1,M3,M2,M3,M3,M5,
M2,M1,M2,M2,M7,M7,H1,H1,H1,M3,M5,M5,
H1,M7,H1,M6,M5,M6,M6,H1,
M5,H1,M5,M5,M3,M4,M6,M5,M5,M6,M3,M3,M2,
H1,M7,H1,M3,M2,M3,M3,M5,
M2,M1,M2,M2,M7,M7,H1,H1,H1,H2,H3,H3,
H2,H3,H1,H1,M6,M6,M6,M6,
M5,H1,M5,M5,M3,M4,M5,M6,M6,H1,H3,H2,
H1,H1,H1
};
//节拍数组
float duration[]=
{
1,1,1,1,0.5,0.5,0.5,1.5,
1,0.5,0.5,0.5,1.5,1,0.5,0.5,1,0.5,0.5,2,
1,1,1,1,0.5,0.5,0.5,1.5,
1,0.5,0.5,0.5,1.5,1,0.5,0.5,1,0.5,0.5,0.5,1.5,
1,1,1,1,0.5,0.5,0.5,1.5,
1,0.5,0.5,0.5,1.5,1,0.5,0.5,0.5,1,0.5,1,
1,0.5,0.5,1,0.5,0.5,1.5,0.5,
1,0.5,0.5,1.5,0.5,1,0.5,0.5,0.5,1.5,2,1,
2,2,2
};
int length = sizeof(tune)/sizeof(tune[0]);
void buzzer_init(int f)
{
/*时钟使能*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13, ENABLE);
//1
GPIO_InitTypeDef p;
p.GPIO_Pin = GPIO_Pin_8;
p.GPIO_Mode = GPIO_Mode_AF; //多路复用模式
p.GPIO_PuPd = GPIO_PuPd_NOPULL;
p.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOF,&p);
GPIO_PinAFConfig(GPIOF,GPIO_PinSource8,GPIO_AF_TIM13);
//2
/*配置GPIO引脚的功能,AF:复用功能*/
TIM_TimeBaseInitTypeDef t;
t.TIM_Prescaler = 8399; //预分频值 10000HZ=TIM13_CLK
t.TIM_CounterMode = TIM_CounterMode_Down;//递减模式
t.TIM_Period = f; //N值
t.TIM_RepetitionCounter = 0; //不需要重复计数
TIM_TimeBaseInit(TIM13, &t);
//3
//输出通道的配置
TIM_OCInitTypeDef t_oc;
t_oc.TIM_OCMode = TIM_OCMode_PWM2;
t_oc.TIM_OCPolarity = TIM_OCPolarity_High;
t_oc.TIM_OutputState = TIM_OutputState_Enable;
t_oc.TIM_Pulse = f*0.9;
TIM_OC1Init(TIM13, &t_oc);
TIM_OC1PreloadConfig(TIM13, TIM_OCPreload_Enable);//
//4
//使能定时器
TIM_ARRPreloadConfig(TIM13, ENABLE); //
TIM_Cmd(TIM13, ENABLE);
}
void music_fun()
{
for(x=0;x<length;x++)
{
if(flag==1)
{
flag=0;
}
if(tune[x]==ZERO)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13, DISABLE);
flag=1;
}
buzzer_init(tune[x]);
if(flag==1)
{
delay_ms((uint32_t)(1000*duration[x]));
flag = 0;
}
else
delay_ms((uint32_t)(400*duration[x]));
}
//关闭时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13, DISABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, DISABLE);
}
main.c
#include "main.h"
#include "rj_led.h"
#include "rj_int_key.h"
#include "systick.h"
#include "rj_buzzer.h"
extern uint8_t status;
int main(void)
{
while (1)
{
music_fun();
}
}
实验现象
演示视频:https://www.bilibili.com/video/BV1Pi4y1x7q1