源碼下載鏈接[點(diǎn)擊跳轉(zhuǎn)]https://download.csdn.net/download/Coin_Collecter/88641632
1.什么是PWM輸出
? ? ? ?PWM,全稱Pulse Width Modulation,即脈寬調(diào)制技術(shù),是一種通過改變信號(hào)的占空比來控制電路的技術(shù)。在PWM信號(hào)中,周期是固定的,而占空比則可以根據(jù)需要進(jìn)行調(diào)整。通過改變占空比,可以控制電路輸出的電壓、電流等物理量的大小,從而實(shí)現(xiàn)對(duì)電路的控制。PWM頻率是指一秒鐘內(nèi)從高電平時(shí)間在到低電平時(shí)間,再從低電平跳到高電平的瞬間次數(shù),也就是一秒鐘內(nèi)有多少個(gè)PWM的周期。PWM周期是指一秒鐘內(nèi)從高電平時(shí)間在到低電平時(shí)間。PWM占空比是指一個(gè)周期內(nèi)高電平時(shí)間和總時(shí)間的比值。
? ? ? ? PWM的基本產(chǎn)生如下圖,即面積等效法,當(dāng)b的占空比為百分之百的時(shí)候,a輸出為高電平,而當(dāng)b在一個(gè)周期占空比為其他數(shù)值的時(shí)候,根據(jù)定積分產(chǎn)生的正弦波面積則不同,經(jīng)過多個(gè)周期不同占空比的時(shí)候,就會(huì)產(chǎn)生不同的面積波形,即產(chǎn)生了一個(gè)模擬信號(hào)。
??????? PWM在生活中有很多應(yīng)用,例如通過PWM輸出控制LED亮度,當(dāng)頻率太小的時(shí)候,一個(gè)周期時(shí)間太長肉眼就能看到LED亮滅的過程,而當(dāng)頻率足夠高的時(shí)候,LED的燈光的亮滅速度趕不上開關(guān)速度(LED燈還沒完全亮就又熄滅了)由于視覺暫留作用人眼不感覺電燈在閃爍,而是感覺燈的亮度減小了,從而達(dá)到了控制LED亮度的效果。
2.如何讓蜂鳴器發(fā)出不同頻率的聲音
2.1設(shè)置預(yù)分頻
void TIMx_BEEP_Config(void){
//......省略部分代碼
TIM_TimeBaseStructure.TIM_Period = 1;//當(dāng)定時(shí)器從0計(jì)數(shù)到255,即為256次,為一個(gè)定時(shí)周期
TIM_TimeBaseStructure.TIM_Prescaler = 72-1;//設(shè)置預(yù)分頻
TIM_TimeBaseStructure.TIM_ClockDivision = 0;//設(shè)置時(shí)鐘分頻系數(shù):不分頻
TIM_OCInitStructure.TIM_Pulse = 0;//占空比0
//......省略部分代碼
}
? ? ? ? 由代碼可見預(yù)分頻值為71,則為72分頻(多少分頻都可以,72分配只是為了方便后面計(jì)算),由于STM32的默認(rèn)系統(tǒng)時(shí)鐘頻率為72MHz,分頻后則為1MHz。此時(shí)定時(shí)器會(huì)在一秒內(nèi)計(jì)數(shù)1M次,且由?知道,可以通過改變周期T來得到任意頻率f。
??????? 通過固件庫函數(shù)TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);修改自動(dòng)重裝載寄存器周期的值即可得到任意頻率的PWM輸出。
??????? 通過TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);來修改比較寄存器中的比較值,改變PWM輸出的占空比。
2.2音調(diào)頻率對(duì)照?qǐng)D:
? ? ? ? 在有了音調(diào)頻率對(duì)照?qǐng)D后只需要通過調(diào)整PWM輸出頻率即可控制蜂鳴器發(fā)出不同的音調(diào),實(shí)現(xiàn)通過蜂鳴器播放音樂。
??????? 由上述可知,分頻后頻率為1MHz,且,頻率已知,因此可以算出所需的T的值。例如低音1的。文章來源:http://www.zghlxwxcb.cn/news/detail-781654.html
2.3定義一個(gè)修改占空比和寄存器周期值的函數(shù)
定義一個(gè)set_beep(uint16_t f)函數(shù),變量f為音調(diào)頻率,通過該函數(shù)即可實(shí)現(xiàn)讓蜂鳴器發(fā)出任意頻率的聲音。文章來源地址http://www.zghlxwxcb.cn/news/detail-781654.html
void set_beep(uint16_t f){
if(f==0){
TIM_SetAutoreload(TIM1,1);
TIM_SetCompare1(TIM1,0);
}else{
TIM_SetAutoreload(TIM1,(1000000/f));
TIM_SetCompare1(TIM1,(1000000/f)/15);
}
}
3.孤勇者樂譜
?4.實(shí)例代碼
main.c
#include "stm32f10x.h"
#include "Beep.h"
#include "SysTick.h"http://里面寫了一個(gè)延時(shí)函數(shù),不重要,因此不上傳該部分的代碼
#define L1 262-1//低調(diào) do 的頻率
#define L2 294-1//低調(diào) re 的頻率
#define L3 330-1//低調(diào) mi 的頻率
#define L4 350-1//低調(diào) fa 的頻率
#define L5 392-1//低調(diào) sol 的頻率
#define L6 440-1//低調(diào) la 的頻率
#define L7 494-1//低調(diào) si 的頻率
#define M1 524-1//中調(diào) do 的頻率
#define M2 588-1//中調(diào) re 的頻率
#define M3 660-1//中調(diào) mi 的頻率
#define M4 700-1//中調(diào) fa 的頻率
#define M5 784-1//中調(diào) sol 的頻率
#define M6 880-1//中調(diào) la 的頻率
#define M7 988-1//中調(diào) si 的頻率
#define H1 1048-1//高調(diào) do 的頻率
#define H2 1176-1//高調(diào) re 的頻率
#define H3 1320-1//高調(diào) mi 的頻率
#define H4 1480-1//高調(diào) fa 的頻率
#define H5 1640-1//高調(diào) sol 的頻率
#define H6 1760-1//高調(diào) la 的頻率
#define H7 1976-1//高調(diào) si 的頻率
#define S 0//不發(fā)音
int16_t music[]=
{
M3,M3,S,S,M1,M2,M1,M3,M3,S, //都是勇敢的
M1,M2,M1,M2,M3,L6,M1,L6,M1,L6,M1,M2,M1,L7,L7,S,S, //你額頭的傷口你的不同你犯的錯(cuò)
M3,M3,S,S,M1,M2,M1,M3,M3,S, //都不必隱藏
M1,M2,M1,M2,M3,L6,M1,L6,M1,L6,M1,M3,M2,L7,L7,S,S, //你破舊的玩偶你的面具你的自我
L6,M1,M6,M6,M6,M5,M6,M6,M5,M6,M5,M6,M5,M3,M3,M3,S,S, //他們說要帶著光馴服每一頭怪獸
L6,M1,M6,M6,M6,M5,M6,M5,M7,M7,M7,M6,M7,M7,M6,M3,M3,S,S, //他們說要縫好你的傷沒人愛小丑
M3,M5,M3,M2,M3,M2,M3,M2,S, //為何孤獨(dú)不可光榮
M3,M5,M3,M5,M3,M2,M3,M2,M3,M2,S, //人只有不完美值得歌頌
M1,M2,M3,L6,M1,M3,M2,M3,M2,M1,M1,L6,L6,S,S,//誰說污泥滿身的不算英雄
M6,M7,H1,H2,M7,H1,H1,S, //愛你孤身走暗巷
H1,M7,H1,H2,M7,H1,H1,S, //愛你不跪的模樣
H1,H2,H3,H2,H3,H2,H3,H3,H2,H3,H5,H3,S, //愛你對(duì)峙過絕望不肯哭一場(chǎng)
M6,M7,H1,H2,M7,H1,H1,H1,M7,H1,H2,M7,H1,H1,S, //愛你破爛的衣裳卻敢堵命運(yùn)的槍
H1,H2,H3,H2,H3,H2,H3,H3,H2,H3,H5,H3,S, //愛你和我那么像缺口一樣
H5,H3, //去嗎
H5,H3,S, //配嗎
H5,H3,H5,H6,H3,H5,S, //這襤褸的披風(fēng)
H5,H3,//戰(zhàn)嗎
H5,H3,S, //戰(zhàn)啊
H5,H3,H5,H6,H3,H5,H5,H5,H3,H2,H2,H2,H1,H3,H3,H2,H2,H2,H1,H1,M6,M6,S,S, //以最卑微的夢(mèng)致那黑夜中的嗚咽與怒吼
H5,H5,H3,H2,H2,H2,H1,H3,H3,H2,H2,H2,H1,H1,M6,M6,S,S, //誰說站在光里才算英雄
};
int main(void)
{
uint16_t i;
TIMx_BEEP_Config();
while(1)
{
for(i=0;i<sizeof(music)/sizeof(music[0]);i++)
{
set_beep(music[i]);
delay_ms(250);
}
}
}
Beep.c
#include "Beep.h"
//不同型號(hào)的單片機(jī)蜂鳴器所對(duì)應(yīng)的引腳和定時(shí)器都有所不同,需要根據(jù)實(shí)際情況修改
void TIMx_BEEP_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = 1;
TIM_TimeBaseStructure.TIM_Prescaler = 72-1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1,ENABLE);
TIM_Cmd(TIM1, ENABLE);
}
void set_beep(uint16_t f)
{
if(f==0){
TIM_SetAutoreload(TIM1,1);
TIM_SetCompare1(TIM1,0);
}else{
TIM_SetAutoreload(TIM1,(1000000/f));
TIM_SetCompare1(TIM1,(1000000/f)/15);
}
}
Beep.h?
#include "stm32f10x.h"
void TIMx_BEEP_Config(void);
void set_beep(uint16_t f);
5.演示視頻
到了這里,關(guān)于STM32通過PWM輸出使蜂鳴器實(shí)現(xiàn)播放音樂功能的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!