一、无源蜂鸣器和有源蜂鸣器 * a3 c& n9 O: z" Z% u! k& W! J
有源蜂鸣器内含振荡源,只要一通电就发声,但发生频率固定,音色单一;无源蜂鸣器内部不含振荡源,内部结构相当于电磁场扬声器,可以通过给他输出一定频率的信号才能发声。 人耳能听到的频率范围在20Hz--20kHz之间,通过STM32的GPIO引脚快速切换高低电平输出就能实现无源蜂鸣器的发声,切换的频率不同,发出的音调就不一样。 ) o8 B2 z$ d8 v* g( L
: [8 G6 S0 q: b; M( N/ ^+ M; D
/ |/ x* b( B3 y% l+ |8 h7 p
二、音乐播放的实现 6 L9 l6 j x" Z' W& ^, i
一段音乐就是不同频率的声音按一定的时间节拍转换发出。所以音乐包含音调和节拍信息。 $ u, ^* z. W/ Z% z U# {. I
C调各音符频率如下: 音符 | 频率 Hz | 音符 | 频率 Hz | 低1 Do | 262 | 中1 Do | 523 | 低2 Re | 294 | 中2 Re | 587 | 低3 Mi | 330 | 中3 Mi | 659 | 低4 Fa | 349 | 中4 Fa | 698 | 低5 So | 392 | 中5 So | 784 | 低6 La | 440 | 中6 La | 880 | 低7 Si | 523 | 中7 Si | 988 | 6 X5 U& y/ q/ [# t, G
( I& ^, G6 l4 }+ o
如果要实现歌曲“红尘情歌”,要准备相应的数据。 歌谱如下: 
+ W# u2 u) \. z; n) u+ b
程序中首先准备音频数据表: // 低Si Do Re Mi Fa So La Si ¸高Do¸高Re¸高Mi¸高Fa¸高So 无 uc16 tone[] ={247,262,294,330,349,392,440,294,523, 587, 659, 698, 784, 1000}; u8 music[]={ 5,5,6,8,7,6,5,6,13,13,……};//音调 u8 time[] = { 2,4,2,2,2,2,2,8,4, 4, ……}; //节拍时间 9 j9 F9 h9 h, {, i q
依次从音调数组中取music,然后根据music的值在tone数组中得到该音的发声频率(tone[music]),调用sound函数控制蜂鸣器发声,声音的发声时间由time数组控制。 1 Z8 I& {1 M* E2 c7 c& `6 ~
; j/ D% f9 Q2 G; [8 _( t
. M/ ~3 z/ P% z- y. D0 {5 _三、项目创建与配置
- ~1 N. ?8 c; ^+ i* V9 V g0 b1、创建项目文件夹(设为pMusic) 2、通过Keil5创建新项目,保存在所创建的文件夹中(设项目名为pMusic),选择MCU芯片为"STM32F103ZE"(本程序使用的硬件为:STM32-PZ6806L开发板) 3、在pMusic项目文件夹中新建"CMSIS"、"Device"、"Public"、"Startup"、"User"和"Lib"文件夹。 ① 在"CMSIS"文件夹中复制"core_cm3.h"和"core_cm3.c"文件; ② 在" Device "文件夹中复制"stm32f10x.h"、"system_stm32f10x.h"和"system_stm32f10x.c"文件; ③ 在" Startup "文件夹中复制"startup_stm32f10x_hd.s"文件; ④在"Lib"文件夹中新建"inc"和"src"两个子文件夹,在"inc"文件夹中复制"misc.h"、"stm32f10x_gpio.h"和"stm32f10x_rcc.h"文件;在"src"文件夹中复制"misc.c"、"stm32f10x_gpio.c"和"stm32f10x_rcc.c"文件; 4、为项目添加"CMSIS"、"Device"、"Public"、"Startup"、"User"和"Lib"组,并将上述C程序文件和"startup_stm32f10x_hd.s"启动文件加入到相应组中。展开项目树如下: 3 }( w* c: l* j2 t# ~9 }; L

% D' Q' a7 e9 N+ e' ]+ S- ]
5、打开“项目配置”对话框,在"Output"选项卡中选择"Create HEX File",在"C/C++"选项卡中的"Include Paths"中添加如下包含路径:".\CMSIS;", ".\Device;", ".\Lib\inc;",".\Public;"。
% w! |7 z: \, u- x " v/ g3 B; U4 Q3 e! ?0 z
6、在"stm32f10x.h"中添加函数参数检查宏 ! g1 K2 Y5 c9 f9 {
- #ifdef USE_FULL_ASSERT
4 A2 H7 E0 J/ A f: s2 t+ Y+ c
7 { g y% w9 U- /** `. I) ]5 ?' F& U
# \8 g7 K, M% w. H. M4 z- * @brief 这个assert_param宏用于函数参数检查
: y" `1 E! O# f8 e1 b% H0 p. e
2 u1 X( [3 T8 I- c( M9 m) `- * @param expr:如果expr是 false,就调用 assert_failed函数报告源文件名和
: p9 E5 D. w+ r6 l6 b; G - 0 V$ F) A/ p& }) R* o5 C
- * 失败的行号,如果expr是 true ,就返回一个空值
, e* d0 Q" W7 K+ x. C" Y* ?: Q - ) a9 q7 ^" |1 s1 v# i& \1 M$ ?
- * @retval None2 q9 N7 V4 M$ E
- K8 [( H9 G: Y4 C, `* X, u* M
- */
! t8 q5 g- j) t! H" L% W! Q- {, V
. G- y" ^: R) E# q7 Z& Q/ g- #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)), @ A% Q& \2 Z3 y/ L
- , f- E: c2 Z5 K9 X5 f
- /* Exported functions ------------------------------------------------------- */
% n7 n q5 E' Y9 W* y" z; C; C$ ~ - : H" R9 n/ \2 K
- void assert_failed(uint8_t* file, uint32_t line);, |9 m+ H4 W6 W z5 B
- ( a" m% b, l I3 i' u( n
- #else
0 D h& w8 [3 `+ k! A - 6 h" z3 o$ B' ^ P
- #define assert_param(expr) ((void)0)9 ^/ ?3 D5 I: i: s7 X
5 S8 v5 x+ {4 a- #endif /* USE_FULL_ASSERT */
复制代码 - T0 ?2 S# \' ~/ i3 J! N% i
6 ]0 s8 n! z7 J/ c$ z
1 m8 }6 G5 T7 v: O$ W4 F7、新建一个文件(system.h),保存到"Public"文件夹中,内容为: - #ifndef __SYSTEM__H a& R- i" w8 ^9 F! g; e
% {' j' w5 B; p+ b, Y- #define __SYSTEM__H
; G, `8 ^9 F% _5 Z4 T- @ - * W# U! w7 H8 g G, {* r8 ^
- #include "stm32f10x.h"
5 o t- G. R1 ]; M' T- y8 p
/ i* ~: }" g6 l9 \- `- //定义位带地址宏
. E- B+ f7 o' Y: y* h - . a8 L5 R& z) c5 X/ g
- #define BITBAND(addr,bitnum) ((addr&0xF0000000) + 0x02000000 + ((addr&0x000FFFFF)<<5) + (bitnum<<2))
8 _' N' j" f* @$ O/ H/ r
6 h$ s: w. X; X; F# N- #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
& \7 A7 Z3 D$ f1 q5 ~0 u - % [% \4 E5 w7 b
- #define BIT_ADDR(addr,bitnum) MEM_ADDR(BITBAND(addr,bitnum))3 ]4 m! s5 C! s
+ f. z# K' c/ U( V+ g4 m- //IO口地址映射
; V. ?% N: D/ L0 B5 Q6 `, e - : z: D3 S" m m" I
- //数据输出寄存器地址. J' H8 t( ?, W7 s$ u
: Y5 H. G2 l3 f5 N( \, ]& Z$ L, x8 T+ C- #define GPIOA_ODR_Addr (GPIOA_BASE + 12)3 r+ M6 P! }0 U5 C3 d" z* ^ V
- 4 R6 d+ g9 l3 A" |& Y" H% U2 R
- #define GPIOB_ODR_Addr (GPIOB_BASE + 12). p% w- d* h# g* a. O/ O/ n
8 j' B4 W" G7 z9 Z5 P: s- #define GPIOC_ODR_Addr (GPIOC_BASE + 12)
! n. {5 u- c+ r; `( V - F7 U" k8 t# |, a9 V& {
- #define GPIOD_ODR_Addr (GPIOD_BASE + 12)
; O2 o( t" ^: \* M
" `; g* V% J6 U$ c7 s9 s7 O- e- #define GPIOE_ODR_Addr (GPIOE_BASE + 12)
' j8 N$ n; B* o- J. B
# r; q7 T: ~* G; h0 ?0 p3 q- #define GPIOF_ODR_Addr (GPIOF_BASE + 12)3 v" ^" P7 T' L2 k- M% J9 n
- ! c; ^3 d1 u/ f
- #define GPIOG_ODR_Addr (GPIOG_BASE + 12), s$ S; i0 j0 a: m. l+ b
- v$ p3 B! h$ O" F: \0 l; Z7 \
- //数据输入寄存器地址, P% v6 H8 G b1 q9 u, a
" F" ^* x' d- Q( Y! S# E/ P8 w- #define GPIOA_IDR_Addr (GPIOA_BASE + 12)* X! U1 t J: E" z1 e8 Q) u
- K+ S+ |2 x7 X- #define GPIOB_IDR_Addr (GPIOB_BASE + 12)7 X1 G5 E3 m! |
- V+ s/ r9 ?' Z- ^, q3 H1 M1 i
- #define GPIOC_IDR_Addr (GPIOC_BASE + 12)3 F5 w5 P0 l" S- B) W$ [" i# G
" L& W8 ^. t x! F( \5 Q( R% E1 y- #define GPIOD_IDR_Addr (GPIOD_BASE + 12)
: b1 | B4 T' @/ `( B3 D - 7 `' }9 s" J4 s% x) V$ ?/ A
- #define GPIOE_IDR_Addr (GPIOE_BASE + 12)
! B$ L: U+ O* ~8 K& [
! r+ G% x$ I4 U. X- #define GPIOF_IDR_Addr (GPIOF_BASE + 12)
& D3 ?. A' i5 L! S; J - L" i+ w% f% k4 K4 \, C/ K
- #define GPIOG_IDR_Addr (GPIOG_BASE + 12)
; k* \4 i( D5 g" ]" S# B - " W$ B$ P5 }7 v9 _
- #endif
复制代码
. `/ t+ N+ J; c, e7 y. x该文件定义了GPIO端口位带操作的宏。2 B5 y) y3 i+ M, [
7 }9 K- r7 W$ U3 m5 \. X+ u9 m4 V7 f; d! H9 j
8、新建文件"SysTick.h",保存到"Public"文件夹中,内容为:
1 {! ^5 ~1 C( j! ^) D% r4 H- #ifndef __SysTick__H# O* y; I4 S1 O( q
4 Y% b% e$ @( { ~. p/ ?- #define __SysTick__H" b3 _. \3 \# z0 g8 F' F$ y3 a. A7 c
* L$ P' |( D2 v D* q' D8 ~- #include "stm32f10x.h"+ V" F. Z8 A# E* r
- 2 d! r+ e- ], z- ?/ S* c( ?
- void SysTick_Init(u8 SYSCLK);0 \" j. e; w0 a5 i7 j8 w; E
- O3 K, c5 L1 U: k6 H- void delay_us(u32 nus);
/ V! a( h6 q6 A& E
- Z+ [- V) _- B- void delay_ms(u16 nms);5 J0 f" |, w( J9 j
- ; [. e3 A& x( G; s
- #endif
复制代码 7 W$ J- R6 N. t. i' g
6 v- t* x; z) _( g: ~3 W. j
新建文件"SysTick.c",保存到"Public"文件夹中,内容为:
' _4 \3 v& C" p5 O* g
+ U% e# i3 g$ l8 u: y, R- #include "SysTick.h"
( ]/ t$ C7 t R' f - . k* ^" i; R% N2 Z2 E% _' l% Y
- #include "misc.h"
9 Y0 ? A/ O2 E6 H0 V( x3 m
; ^; M( q. U( ~7 m- u8 fac_us = 0;
# v" Y0 r" J& ~& S
2 I+ R2 a5 Z+ v# V1 f ?3 j- u16 fac_ms = 0;$ y; a6 u5 Y6 [+ X' g
* X) N4 s- o0 A& D, x4 [ z1 n- void SysTick_Init(u8 SYSCLK)
+ B! B' J1 w# [ b" ^ - 7 Z) `7 {* Z4 x* N! [7 c. E
- {6 H4 p7 V$ [# d" I
- SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
3 v& Y; J& O- {* K: d; a ]2 E! W - / N9 `) `) k- a
- fac_us = SYSCLK / 8;
+ J: } _$ F( [+ C- ] - ! i" U& E% V% P* e
- fac_ms = (u16)fac_us*1000;
8 a; e8 p+ c% \& z4 p2 T9 C3 S" A4 ]* j
: M# n% ?. c6 |1 k9 Y7 F! f, ~+ K5 f- }- {$ @7 K4 S2 s
- 3 V. \, W( S1 B& @8 R
- % |% C1 b' n' f: N4 [7 C
2 @' @0 q. T$ j! H) F* r5 z- void delay_us(u32 nus)4 Y& {, K& }+ r* ~- e
- # M+ n P# W7 |- O
- {7 f0 X% b0 I4 [( t/ Q' K U
- u32 temp;
# q# N6 X- F6 p7 d3 ?% y( V, A) l - % h4 E' a$ B5 S" L8 u( K6 D. J
- SysTick->LOAD = nus * fac_us;
2 M2 f# a' R! h, P
R& G6 G/ S: w* [) K- SysTick->VAL = 0;
: `' J. m" z" V, `$ Y3 c
7 @- j; M+ v" H6 K- SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
/ R# h( A6 Z% F' N9 N+ @ - $ {% B) h! V+ p1 G0 v
- do{9 l, |: W5 x4 \ Z
- temp = SysTick->CTRL;6 y9 D/ \! p. V6 i5 w" m3 ~6 J; O
+ P; |8 b7 ]2 b" S+ P- }while((temp&0x01)&&(!(temp&(1<<16))));
' w4 x& f$ D9 E5 ~; N" Y
' c1 _) k9 D) I6 H: X; M& M- SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;! S R$ g! e( c3 ]
2 P0 f0 l U; Q7 v0 N9 c1 i- SysTick->VAL = 0; X4 Y. U @/ _
6 n6 \4 n T6 {2 I- L4 i! p- }
/ w. E3 _% V; R4 W1 v4 ]
8 \% q" m8 @ \/ Y6 R, z" K" _0 l- void delay_ms(u16 nms)
7 w% z Y% G3 S: P9 W+ w: b
1 K- v, I& x j1 a% q; {8 A- {+ N1 |6 `9 K; [
- u32 temp;: P; Y: z2 y3 U$ J3 E1 l% S
, k% h' |# n& z( S! ~, L4 B- SysTick->LOAD = nms * fac_ms;
1 E! x( j0 b$ E* J8 _9 M) M+ j - 3 ~; r, [- G! Z& R% x
- SysTick->VAL = 0;% U( b( U7 N5 D6 Q
- ) R# J5 W, M3 b" h; m8 C ~* g' n
- SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;9 K7 T W+ o# ~) K1 U+ L6 @1 A
; S7 F$ Y* y& H, }6 w+ r- do{
' ?/ m( q, G, P2 L: d4 @ - temp = SysTick->CTRL;
: I& J$ ? m0 l" H - 2 C& X; A8 a% z |' E
- }while((temp&0x01)&&(!(temp&(1<<16))));
3 E8 l) Z' h% ]6 }: ] X F I4 A! U - . b# g9 y% r- W$ [1 c J
- SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
) n) b. l m4 I2 C+ i - 6 \$ q9 J$ D% s0 L" u+ ]
- SysTick->VAL = 0;) L- G& v' G( J
- L3 }8 h, y- M+ q. ]. a+ l
- }
复制代码
& [8 l) Y+ f) r6 s1 d! n
) E0 i( T- W1 F; H" w7 L3 U9 p% f: [这两个文件实现了通过SysTick精准延时的函数,提供给后续的音频频率产生程序使用。
4 U/ l' Y4 x/ o, k; k将"SysTick.c"文件添加到项目的"Public"组中。
+ l0 p/ \ [- a: Q8 I
9、实现发声
" @7 s! O6 T# f
①开发板无源蜂鸣器的电路连接如下: 
从电路连接可以看出通过MCU的PB5(GPIOB_5)控制蜂鸣器的发声。
* ^5 m" h% u: v, F# E1 E. p
②在项目文件夹的"User"文件夹下新建"Beep"文件夹,在项目中新建"beep.h"文件,保存在"User/Beep"文件夹中,文件内容为:
9 Q% ^* s3 c4 Z. C& \
# D# v7 k5 z+ y6 m/ r6 S2 C+ k- #ifndef __BEEP__H8 j T8 D. x5 p5 l4 c$ N
( j! u6 K/ t- z; p9 @0 d/ m- #define __BEEP__H- s- C9 D9 G" T5 r
- % ^) r# q2 c; l) x4 I
- #include "system.h"
0 V# }3 s1 C4 N% I2 {3 } - 9 {7 Z* b+ w. p5 V
- #include "stm32f10x_gpio.h"7 H0 I6 B% X7 v$ a
- ?# r& _) i8 K: Z- C! R# H2 p- #include "stm32f10x_rcc.h"; Z' S, r/ [& j9 m0 p3 d
- & L! k0 a' N0 Y6 C0 ]0 V/ s5 t
- //定义GPIOB的位地址变量宏
9 }5 r; U. B8 m0 m- G- H - " \5 R) I6 P& d V- @7 ?
- #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n)
2 H" @$ C n' R" v( n6 @* g - " _! l7 \1 P( |- Y, Q6 S9 D
- #define PBeep PBout(5)
; n! n8 W2 U9 N @
/ ]0 n8 v: A$ c- #define BEEP_PORT GPIOB
# n4 Z$ Y8 ^3 R0 {6 E0 i - 9 V( s$ j0 u' X8 @4 M8 {
- #define BEEP_PIN GPIO_Pin_50 k. t+ ]: _- | ^7 |0 ` j
- 4 f9 V) {6 c# L- f" C7 ^# u
- #define BEEP_PORT_RCC RCC_APB2Periph_GPIOB- [3 R, ^- C! P- x
- ) b9 @- m/ N v% q
- void BEEP_Init(void);3 E+ _& [! h4 m5 w' _: q
- 4 C$ Z; G* a4 L
- void Sound(u16 frq);
: e |6 i5 ~& p f+ p
) i, R0 T# X& v0 j9 Z- void play(void);2 X+ y4 O2 b! O0 ]% Y
- + F u# Z: V8 C2 f+ U( F% [
- #endif
复制代码
2 C m f) n4 Y③在项目中新建"beep.c"文件,保存在"User/Beep"文件夹中,文件内容为: 8 z; i$ @) C! I% g O7 i
- #include "beep.h"
3 J$ q: B2 Z, m# ^ - : b9 r1 `5 w, M3 B& m; y9 m
- #include "systick.h"1 X2 I( J6 S8 m: g
9 D" S" |* ?8 A( d) x- void BEEP_Init(void)
8 v8 i I1 x' f2 v7 i# n+ \ - 4 b8 }; h! G- k' q. p- T
- {
$ g- m2 g1 K1 ~1 P4 K5 J' [" x4 o - GPIO_InitTypeDef GPIO_mode;" j- z4 p, q8 u) S. s% r% @; g" }
& l) r/ |7 j! I- l" {; t8 @% F- RCC_APB2PeriphClockCmd( BEEP_PORT_RCC, ENABLE ); //使能GPIOB时钟
& \, G" O" R1 F9 @5 ?# E- j - 4 S& e0 }- }8 D
- GPIO_mode.GPIO_Pin = BEEP_PIN;
# h4 z V4 G. b4 w) a - 2 K" t4 ~2 S/ R, X K# V
- GPIO_mode.GPIO_Speed = GPIO_Speed_50MHz;* C# e% [8 Q3 u/ K( v+ B
- 8 f/ n! [& ]0 a
- GPIO_mode.GPIO_Mode = GPIO_Mode_Out_PP;
1 | c, `0 E+ }" }- H- F - + h6 m7 \. d% L0 o/ P" [( a
- GPIO_Init(BEEP_PORT, &GPIO_mode); //设置GPIOB_5为推挽输出,50MHz速度$ r& ~8 P9 n1 h; ?" q
, s/ Z- Z' @0 Y$ z* |- }
* [# | N6 _4 C4 D: J
& M! v1 k" ~' G3 F4 Q0 h- & _! y% }" D" g- I5 e+ G6 x4 u8 a C
- $ A" X; d% t: g$ J) \
- void Sound(u16 frq)
/ I t. w# o6 k# Z5 n8 b - ) ~# U U0 q% C9 ?7 }
- {
- `# z; L- c; Q0 N - u32 n;+ a! m* K% B& E$ T8 _
- , P" B, f% G* O
- if(frq != 1000) //如果频率不为1000则按频率输出,否则只延时
d9 O" f3 g0 k# N7 H
2 T4 R3 ~. R. K" @, ~4 _. `2 v- {8 Z9 ]( P8 s# h
- n = 500000/((u32)frq);* x* d2 ?: h. X) F
- 6 P7 C# Y2 c: \2 l2 N: X
- PBeep = 0;
' O# ]) P7 ]1 n6 Y6 a8 c
7 t7 I0 i( s4 E% W7 F- delay_us(n);
$ u$ u. x" c/ F% r3 p
4 S! }+ N6 T3 H- Y+ n9 h0 G- PBeep = 1;
. {) |) [! @% G1 y; r5 I - 6 J) {* S1 `$ F' c7 W
- delay_us(n);
1 @; F7 \1 l) C, G - ' K8 `- f1 g5 a: L. ?: `
- }else
/ L0 l( p% k: S6 y8 u- J) Y
' a3 b( r+ N0 z/ D1 C7 Z# ~) A" C- delay_us(1000);
5 n; X& L* R- x* w8 w, z8 `
8 f( X) B, t2 O& g2 p/ N- }
( b7 v- |$ n2 I- S. G - * o9 g& ]0 U/ w* O& k7 m/ ?5 d
-
2 N4 Z! {+ t* ]4 b
! [6 w- |$ U0 r5 t/ l8 C; R3 G: I- void play(void)
4 n- u3 t4 o) z0 }9 l& }. }% @ - 6 Z7 O: s8 G5 i- I4 X
- {
- u2 z- Q6 C& J+ o/ C: r5 \5 Z - // 低7 1 2 3 4 5 6 7 高1 高2 高3 高4 高5 不发音( E. E' I# w3 v! L
- : t3 Z' c. R+ V. \& l7 M) Y# a, r6 H4 J, s
- uc16 tone[] = {247,262,294,330,349,392,440,494,523,587,659,698,784,1000};//音频数据表" f5 Z; V W( O8 p
- ; ]5 f& Q0 |# {8 G4 }! E
- //红尘情歌
# ^8 ^7 R, A" H0 j - # u$ v. `& ]: _$ ~/ x
- u8 music[]={ 5,5,6,8,7,6,5,6,13,13,//音调
3 W' O& L9 t( q9 }# u3 `8 V0 I
- s' o6 ]4 Y y/ P9 G9 O( f; V8 T) D) U- 5,5,6,8,7,6,5,3,13,13,, d; M$ C8 o* H+ x5 ^
- 6 B$ {6 f+ h7 c/ ~
- 2,2,3,5,3,5,6,3,2,1,( U: [) r5 `0 J0 g" |+ t
- 3 X% ]: ]8 T: O; B$ z
- 6,6,5,6,5,3,6,5,13,13,
2 ]6 E2 J+ S2 v - - H6 Q! ?0 W: J
-
9 e! D" \+ n" ^' P0 A - 3 |9 M$ R( ]8 o7 c" r2 y" T, |3 B+ e
- 5,5,6,8,7,6,5,6,13,13,& ~; X2 D: y: J/ I. z
- ' q: o/ t5 {& q9 i/ c% Y) [6 B
- 5,5,6,8,7,6,5,3,13,13,
$ E8 R, u- @3 r. N& _9 F
, Z' B3 ?9 `& Y- 2,2,3,5,3,5,6,3,2,1,' l: O; ?/ Q9 p% T8 N
- / `5 e7 c- X) r7 v% e, {. j, r
- 6,6,5,6,5,3,6,1, $ q( t0 u) O1 c" J
- 3 v- y* D" j- v
-
* P6 g" f' l' B
% S- b4 t" B5 V8 |3 t- 13,8,9,10,10,9,8,10,9,8,6,
* y6 A% G2 N% b8 @, U7 ^- v5 z, _
0 ~3 o4 L. D, S8 S$ U7 e" ?5 f+ T- 13,6,8,9,9,8,6,9,8,6,5,
/ p5 f$ B& {" o9 y5 k* \ - ' p! u3 l8 L( o3 @0 |( t# j, {, `2 H
- 13,2,3,5,5,3,5,5,6,8,7,6,7 I& j$ m' d0 g
- ! ]3 l! c/ {3 c4 M2 W
- 6,10,9,9,8,6,5,6,88 W8 D; }4 b" I0 J: x( _3 W
- ! w( Y. T( K6 E4 C
- };
6 g' P( I# X% y/ ?1 P
9 ?' K r. P& D. `3 t# D- u8 time[] = { 2,4,2,2,2,2,2,8,4, 4, //时间
. p$ U* v- x! h" r1 v; Z
1 C: H: D; h' \' b* s( ^% _+ n! l- 2,4,2,2,2,2,2,8,4, 4,
8 [ _7 a: \$ n - P: A: D" j2 `0 V; ]6 S
- 2,4,2,4,2,2,4,2,2,8,. T2 T4 U4 O [# w* M
/ w- s! |$ X8 T. D# x" O- 2,4,2,2,2,2,2,8,4 ,4,# b+ v( c+ B3 t9 W7 C8 K4 X
- * j2 p' g- _) M
- 2 G" O7 M4 }* P
- ( r `: O8 K5 p0 I" w) e
- 2,4,2,2,2,2,2,8,4, 4,
4 }& o3 D/ }- {: |+ E+ Y
8 x5 L' l3 P2 u6 q( i) O+ P- 2,4,2,2,2,2,2,8,4, 4,
1 x9 b2 `9 Y9 f6 ?& \+ O: k4 }
" i( g: v0 @* a! t- 2,4,2,4,2,2,4,2,2,8,
1 @9 Z! }2 ~1 T# ?3 R - ! V2 |( E5 z- C- \+ R
- 2,4,2,2,2,2,2,8,
2 U* w- t& G& d b" b
3 `' `+ B8 Q7 \) C" N3 [/ p0 s) x-
/ ~" Z; H6 u( g6 J - : R, u2 I3 Q# R* i( ] a
- 4, 2,2,2, 4, 2,2,2, 2,2,8,0 E6 w4 m$ `( m+ V) `7 a5 y
: x% e, p+ v% Q, G9 D5 R c o- 4, 2,2,2,4,2,2,2,2,2,8,
3 s' S( A h# S" F3 w: t - ; ~& E5 n* G$ A
- 4, 2,2,2,4,2,2,5,2,6,2,4,) `# c `' D! `5 P3 P+ X Y5 |0 Z
- ; q* q" p! a) v8 x' L
- 2,2 ,2,4,2,4,2,2,12
; X6 H* r0 [% r5 \9 r5 ^* O - 5 ^5 |* U8 v4 C
- };
0 l7 G) k; e: n y; J7 s' H) m5 |
1 @ r! [( n! c2 t3 l6 G Z- u32 yanshi;4 b3 X9 `9 R _9 W
, L3 N9 i, ^9 q* ~- h* K- x e- u16 i,e;
s. i" ], g4 ^" p# }) c7 G& ^ - % v* d! c! u: [1 E; {
- yanshi = 10;8 u9 z4 z- H4 e9 T3 i7 T0 w
- 7 k4 w# Y8 f! \% l& y0 c5 e( \
- for(i=0;i<sizeof(music)/sizeof(music[0]);i++){: p# p% b( [1 r) n; p7 @2 ]
- for(e=0;e<((u16)time[i])*tone[music[i]]/yanshi;e++){9 h! o# \& b& C' T% d
- Sound((u32)tone[music[i]]);1 l7 L* S- l1 Q2 I6 c5 K
- - _/ C4 a/ p8 G: F
- } ! b0 t) O5 H: E0 c
- : H/ p! Q2 e1 D# \" ~
- }
: a" u0 S: r" ^8 y - 6 L* X( M+ B7 k
- }
复制代码
' o/ f( a' o) e+ M/ ^" H程序中定义了端口使能和方式配置函数BEEP_Init,输出音频函数Sound和播放音乐函数play。+ c: J6 f& s+ l4 d+ W0 K
& @/ Q( M5 d- I1 `& Y0 s; f' a④ 将"beep.c"文件加入到项目的"User"组中;在"C/C++"选项卡中的"Include Paths"中添加包含路径:"\User\Beep;"。
% w. F2 h, ]; Z/ P, d
10、在项目中新建"main.c"文件,保存在"User "文件夹中,文件内容为: ; Q- K" U! Q5 ?0 H' U C
- #include "beep.h"
2 d! M' f8 ]5 A& W8 I( |. i1 e - 8 K* Y' F! e# `6 d, Z3 j
- #include "SysTick.h"% K# Z* {# f3 H1 ~! V0 ?7 K9 p
- # W1 \2 g7 \# O8 j" \- Z1 O5 n
- int main()0 m9 I. i8 \/ C2 p0 R; `& W
0 ]- M: s9 C* ?2 N- {6 l8 N* U3 w, p. n/ J `
- SysTick_Init(72);
8 }8 ^0 T+ \$ `5 R# C; z7 Y - . }3 g0 k5 q) l/ C& K
- BEEP_Init();
& ?6 o9 s* M9 a4 R3 i+ n, L& N
}! }( n" u9 B2 Q1 Z# [- while(1)) w+ `; P) Z/ u& R# w
- + d* I0 @& I" U
- {
: P$ G! I- r$ N' ? - play();' S1 d M# M8 U3 D: a1 ~4 [- q
9 ^ c! c* b. c) v+ R8 J- }
# n) O# k4 f4 F5 ]) `( @
* K# F/ m$ `+ N3 O- }
复制代码 4 t4 }1 p1 w# [: {* Z0 h! H
"main.c"文件中包含main函数反复调用play函数播放歌曲。 , |. ?& {( |: j+ b8 g1 F
|