目录
蜂鸣器说明
无论哪种蜂鸣器都能播放音乐,只是播放出来的音乐好不好听的问题。无源蜂鸣器播放出来的音乐要比有源蜂鸣器播放出来的音乐好听。
无源蜂鸣器:内部无震荡电路,需要提供震荡信号才能发声。
有源蜂鸣器:内部有震荡电路,给电就能发声。
配置信号引脚
蜂鸣器采用无源蜂鸣器,自主搭建电路。
配置引脚号
配置引脚速度(一定要配置!!!一定要配置!!!一定要配置!!!否则蜂鸣器无法发声)
配置引脚的模式
引脚初始化
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);//初始化引脚
GPIO_InitTypeDef FMQ;
//PA1 -> TIM5_CH2
FMQ.GPIO_Pin=GPIO_Pin_1;
FMQ.GPIO_Mode=GPIO_Mode_AF_PP;
FMQ.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&FMQ);
使能引脚时钟
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能PA时钟
配置定时器
根据对应的引脚定时器配置对应的定时器。
配置第一次时钟分频
配置计数模式
配置重载值
配置预分频系数
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
//PA1 -> TIM5_CH2
//定时器5配置
DSQ_5.TIM_ClockDivision=TIM_CKD_DIV1;//第一次时钟分频,不分频
DSQ_5.TIM_CounterMode=TIM_CounterMode_Up;//计数模式,向上计数模式
DSQ_5.TIM_Period=1000-1;//重载值
DSQ_5.TIM_Prescaler=72-1;//预分频系数,不分频
TIM_TimeBaseInit(TIM5,&DSQ_5);
使能定时器时钟
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);//使能定时器5时钟
使能定时器
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
TIM_Cmd(TIM5,ENABLE);//使能定时器5
配置PWM
配置PWM模式。模式1:计数值<CCR时,通道1为有效电平。模式2:计数值>CCR时,通道1为有效电平。
比较输出使能
配置输出比较极性。0:高电平有效。1:低电平有效。
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
/*
CHx->TIM_OCxInit
CH几就对应OC几
TIMx_->TIMx
TIMx_就对应定时器几
*/
//PA1 -> TIM5_CH2 -> TIM5、TIM_OC2Init
TIM_OCInitTypeDef PWM;
PWM.TIM_OCMode=TIM_OCMode_PWM2;//PWM模式2
PWM.TIM_OutputState=TIM_OutputState_Enable;//比较输出使能
PWM.TIM_OCPolarity=TIM_OCPolarity_High;//输出比较极性
TIM_OC2Init(TIM5,&PWM);//初始化PWM
使能PWM
void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
/*
CHx->TIM_OCxInit
CH几就对应OC几
TIMx_->TIMx
TIMx_就对应定时器几
*/
//PA1 -> TIM5_CH2 -> TIM5、TIM_OC2PreloadConfig
TIM_OC2PreloadConfig(TIM5,TIM_OCPreload_Enable);//使能PWM
配置定时器2
根据对应的引脚定时器配置对应的定时器。
配置第一次时钟分频
配置计数模式
配置重载值
配置预分频系数
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
//定时器2配置
DSQ_2.TIM_ClockDivision=TIM_CKD_DIV1;//第一次时钟分频,不分频
DSQ_2.TIM_CounterMode=TIM_CounterMode_Up;//计数模式,向上计数模式
DSQ_2.TIM_Period=1000000/1000-1;//重载值,1ms中断一次
DSQ_2.TIM_Prescaler=72-1;//预分频系数 主频1MHz
TIM_TimeBaseInit(TIM2,&DSQ_2);//定时器1初始化
使能定时器2时钟
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能定时器2时钟
使能定时器
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
TIM_Cmd(TIM2,ENABLE);//使能定时器2
中断优先级分组
/*
zu_bie:
NVIC_PriorityGroup_0
NVIC_PriorityGroup_1
NVIC_PriorityGroup_2
NVIC_PriorityGroup_3
NVIC_PriorityGroup_4
*/
void NVIC_PriorityGroupConfig(zu_bie);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
配置定时器2中断
配置中断源
配置抢占优先级
配置子优先级
定时器3中断源使能
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);//初始化中断
NVIC_InitTypeDef DSQ_2_ZD;//定时器2中断
DSQ_2_ZD.NVIC_IRQChannel=TIM2_IRQn;
DSQ_2_ZD.NVIC_IRQChannelCmd=ENABLE;
DSQ_2_ZD.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级
DSQ_2_ZD.NVIC_IRQChannelSubPriority=2;//响应优先级
NVIC_Init(&DSQ_2_ZD);
定时器2中断使能
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//定时器2计数值更新、溢出,使能
重写定时器2中断服务函数
注意:中断服务函数的函数已经固定,重新定义相同名字的函数即可,在定义好的函数里写中断的操作,哪个串口发生中断就得重定义哪个串口中断的函数
void TIM2_IRQHandler(){//定时2中断服务函数
static u16 i=0;
i++;
if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET){
if(i==400){
TIM5->ARR=1000000/262;
TIM5->CCR2=TIM5->ARR/2;
}
else if(i==800){
TIM5->ARR=1000000/294;
TIM5->CCR2=TIM5->ARR/2;
}
else if(i==1200){
TIM5->ARR=1000000/330;
TIM5->CCR2=TIM5->ARR/2;
}
else if(i==1600){
TIM5->ARR=1000000/700;
TIM5->CCR2=TIM5->ARR/2;
}
else if(i==2000){
TIM5->ARR=1000000/990;
TIM5->CCR2=TIM5->ARR/2;
i=0;
}
}
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中断标志位
}
清空定时器中断标志位
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中断标志位
例程
例程说明
利用定时器控制蜂鸣器播放的频率,利用定时器中断控制蜂鸣器的播放时间。
main.h
#ifndef _MAIN_H_
#define _MAIN_H_
#include "stm32f10x.h" // Device header
#include <string.h>
#include <stdio.h>
#include "delay.h"
#include "DSQ.h"
#include "usart.h"
#include "FengMingQi.h"
#endif
main.c
#include "main.h"
int main() {
delay_init();
DSQ_2_Init();
FengMingQi_YinYue_Init();
DSQ_5_Init();//蜂鸣器频率初始化
uart_init(115200);//串口初始化
printf("程序开始运行!!!\n");
while(1);
}
void TIM2_IRQHandler(){//定时2中断服务函数
static u16 i=0;
i++;
if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET){
if(i==400){
TIM5->ARR=1000000/262;
TIM5->CCR2=TIM5->ARR/2;
}
else if(i==800){
TIM5->ARR=1000000/294;
TIM5->CCR2=TIM5->ARR/2;
}
else if(i==1200){
TIM5->ARR=1000000/330;
TIM5->CCR2=TIM5->ARR/2;
}
else if(i==1600){
TIM5->ARR=1000000/700;
TIM5->CCR2=TIM5->ARR/2;
}
else if(i==2000){
TIM5->ARR=1000000/990;
TIM5->CCR2=TIM5->ARR/2;
i=0;
}
}
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中断标志位
}
DSQ.h
#ifndef __DSQ_H_
#define __DSQ_H_
#include "stdio.h"
#include "delay.h"
void DSQ_2_Init();
void DSQ_3_Init();
void DSQ_5_Init();
#endif
DSQ.c
#include "DSQ.h"
void DSQ_2_Init(){
TIM_TimeBaseInitTypeDef DSQ_2;//定时器2
NVIC_InitTypeDef DSQ_2_ZD;//定时器2中断
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能定时器2时钟
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
DSQ_2.TIM_ClockDivision=TIM_CKD_DIV1;//第一次时钟分频,不分频
DSQ_2.TIM_CounterMode=TIM_CounterMode_Up;//计数模式,向上计数模式
DSQ_2.TIM_Period=1000000/1000-1;//重载值,1ms中断一次
DSQ_2.TIM_Prescaler=72-1;//预分频系数 主频1MHz
TIM_TimeBaseInit(TIM2,&DSQ_2);//定时器1初始化
TIM_Cmd(TIM2,ENABLE);//使能定时器2
DSQ_2_ZD.NVIC_IRQChannel=TIM2_IRQn;
DSQ_2_ZD.NVIC_IRQChannelCmd=ENABLE;
DSQ_2_ZD.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级
DSQ_2_ZD.NVIC_IRQChannelSubPriority=2;//响应优先级
NVIC_Init(&DSQ_2_ZD);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//定时器2计数值更新、溢出,使能
}
void DSQ_3_Init(){
TIM_TimeBaseInitTypeDef DSQ_3;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能定时器3时钟
DSQ_3.TIM_ClockDivision=TIM_CKD_DIV1;//第一次时钟分频,不分频
DSQ_3.TIM_CounterMode=TIM_CounterMode_Up;//计数模式,向上计数模式
DSQ_3.TIM_Period=900-1;//重载值,
DSQ_3.TIM_Prescaler=0;//预分频系数
TIM_TimeBaseInit(TIM3,&DSQ_3);//定时器3初始化
//TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//定时器3计数值更新、溢出,使能
TIM_Cmd(TIM3,ENABLE);//使能定时器3
}
void DSQ_5_Init(){
TIM_TimeBaseInitTypeDef DSQ_5;//定时器5
TIM_OCInitTypeDef PWM;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);//使能定时器5时钟
//PA1 -> TIM5_CH2
//定时器5配置
DSQ_5.TIM_ClockDivision=TIM_CKD_DIV1;//第一次时钟分频,不分频
DSQ_5.TIM_CounterMode=TIM_CounterMode_Up;//计数模式,向上计数模式
DSQ_5.TIM_Period=1000-1;//重载值
DSQ_5.TIM_Prescaler=72-1;//预分频系数,不分频
TIM_TimeBaseInit(TIM5,&DSQ_5);
TIM_Cmd(TIM5,ENABLE);//使能定时器5
PWM.TIM_OCMode=TIM_OCMode_PWM2;//PWM模式2
PWM.TIM_OutputState=TIM_OutputState_Enable;//比较输出使能
PWM.TIM_OCPolarity=TIM_OCPolarity_High;//输出比较极性
TIM_OC2Init(TIM5,&PWM);//初始化PWM
TIM_OC2PreloadConfig(TIM5,TIM_OCPreload_Enable);//使能PWM
}
FengMingQi.h
#ifndef __FENGMINGQI_H_
#define __FENGMINGQI_H_
#include "stdio.h"
#include "sys.h"
#include "delay.h"
void FengMingQi_Init();
void FengMingQi_NO();
void FengMingQi_OFF();
void FengMingQi_NO_OFF(u8 flag);
void FengMingQi_YinYue_Init();
#endif
FengMingQi.c
#include "FengMingQi.h"
void FengMingQi_Init(){
GPIO_InitTypeDef FMQ;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
FMQ.GPIO_Pin=GPIO_Pin_0;
FMQ.GPIO_Mode=GPIO_Mode_Out_PP;
FMQ.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&FMQ);
GPIO_WriteBit(GPIOC,GPIO_Pin_0,0);
}
void FengMingQi_NO(){
GPIO_WriteBit(GPIOC,GPIO_Pin_0,1);
}
void FengMingQi_OFF(){
GPIO_WriteBit(GPIOC,GPIO_Pin_0,0);
}
void FengMingQi_NO_OFF(u8 flag){
GPIO_WriteBit(GPIOC,GPIO_Pin_0,flag);
}
void FengMingQi_YinYue_Init(){
GPIO_InitTypeDef FMQ;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//PA1 -> TIM5_CH2
FMQ.GPIO_Pin=GPIO_Pin_1;
FMQ.GPIO_Mode=GPIO_Mode_AF_PP;
FMQ.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&FMQ);
}