STM32F1与STM32CubeIDE编程实例-PWM驱动蜂鸣器生产旋律

PWM驱动蜂鸣器生产旋律

蜂鸣器或蜂鸣器是一种音频信号装置, 可以是机械的、机电的或压电的(简称压电)。其主要功能是将信号从音频转换为声音。 一般通过直流电压供电,用于定时器、报警器、打印机、报警器、电脑等。根据不同的设计,它可以产生不同的声音,如闹钟、音乐、铃声和警笛。

在这里插入图片描述

蜂鸣器又分为有源蜂鸣器和无源蜂鸣器。本次实例使用无源蜂鸣器,如上图所示。

1、蜂鸣器配置

开发环境搭建、系统时钟配置、调试配置及串口配置,请参考:

本次实例通过定时器的PWM功能驱动蜂鸣器。通过指定PWM输出时间长短和调整PWM输出频率,生成不同的声音(旋律)。配置如下:

在这里插入图片描述

在这里插入图片描述

在前面的文章中,对定时器的PWM功能做也详细的介绍,请参考:

2、蜂鸣器驱动实现

1)基本定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/\*
\* buzzer.h
\*
\* Created on: May 3, 2022
\* Author: jenson
\*/

#ifndef \_\_BUZZER\_H\_\_
#define \_\_BUZZER\_H\_\_

#include <stm32f1xx\_hal.h>
#include "main.h"

typedef struct {
uint16\_t id;
TIM_HandleTypeDef\* TIMx;
GPIO_TypeDef\* GPIOx;
uint16\_t GPIO_Pinx;
uint16\_t TIMx_Channel;
}buzzer\_t;

void buzzer\_init(buzzer\_t\* buzzer);
void buzzer\_play\_tone(buzzer\_t\* buzzer);
void buzzer\_set\_frequency(buzzer\_t\* buzzer,uint32\_t freq);

#endif /\* \_\_BUZZER\_H\_\_ \*/


2)蜂鸣器初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/\*
\* buzzer.c
\*
\* Created on: May 3, 2022
\* Author: jenson
\*/
#include "buzzer.h"
#include "tone\_melody.h"
#define CPU\_FREQ 72000000
#define PRESCALER 72

void buzzer\_init(buzzer\_t \*buzzer) {
HAL\_TIM\_PWM\_Start(buzzer->TIMx, buzzer->TIMx_Channel);
}

3)定时器PWM输出时间长短和频率更新

1
2
3
4
5
6
7
8
9
10
11
12
13
void buzzer\_set\_frequency(buzzer\_t \*buzzer, uint32\_t new_freq) {
uint64\_t temp_freq = new_freq;
if (new_freq == 0)
temp_freq = 1;

uint64\_t new_value = (uint64\_t) CPU_FREQ / PRESCALER / temp_freq;

// 更新
buzzer->TIMx->Instance->ARR = (uint32\_t) new_value;
buzzer->TIMx->Instance->CCR4 = (uint32\_t) new_value / 2;

}

4)PWM生成旋律

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void buzzer_play_tone(buzzer_t *buzzer) {
int melody_count = sizeof(melody_sizes) / sizeof(uint32_t);

for (int melody_index = 0; melody_index < melody_count; melody_index++) {
for (int note_index = 0; note_index < melody_sizes[melody_index];
note_index++) {
buzzer_set_frequency(buzzer, melody[melody_index][note_index]);
HAL_Delay(
note_durations[melody_index][note_index]
* melody_slow_factor[melody_index]);
}
}
}

5)旋律定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#ifndef MELODY\_H\_
#define MELODY\_H\_

#define NOTE\_B0 31
#define NOTE\_C1 33
#define NOTE\_CS1 35
#define NOTE\_D1 37
#define NOTE\_DS1 39
#define NOTE\_E1 41
#define NOTE\_F1 44
#define NOTE\_FS1 46
#define NOTE\_G1 49
#define NOTE\_GS1 52
#define NOTE\_A1 55
#define NOTE\_AS1 58
#define NOTE\_B1 62
#define NOTE\_C2 65
#define NOTE\_CS2 69
#define NOTE\_D2 73
#define NOTE\_DS2 78
#define NOTE\_E2 82
#define NOTE\_F2 87
#define NOTE\_FS2 93
#define NOTE\_G2 98
#define NOTE\_GS2 104
#define NOTE\_A2 110
#define NOTE\_AS2 117
#define NOTE\_B2 123
#define NOTE\_C3 131
#define NOTE\_CS3 139
#define NOTE\_D3 147
#define NOTE\_DS3 156
#define NOTE\_E3 165
#define NOTE\_F3 175
#define NOTE\_FS3 185
#define NOTE\_G3 196
#define NOTE\_GS3 208
#define NOTE\_A3 220
#define NOTE\_AS3 233
#define NOTE\_B3 247
#define NOTE\_C4 262
#define NOTE\_CS4 277
#define NOTE\_D4 294
#define NOTE\_DS4 311
#define NOTE\_E4 330
#define NOTE\_F4 349
#define NOTE\_FS4 370
#define NOTE\_G4 392
#define NOTE\_GS4 415
#define NOTE\_A4 440
#define NOTE\_AS4 466
#define NOTE\_B4 494
#define NOTE\_C5 523
#define NOTE\_CS5 554
#define NOTE\_D5 587
#define NOTE\_DS5 622
#define NOTE\_E5 659
#define NOTE\_F5 698
#define NOTE\_FS5 740
#define NOTE\_G5 784
#define NOTE\_GS5 831
#define NOTE\_A5 880
#define NOTE\_AS5 932
#define NOTE\_B5 988
#define NOTE\_C6 1047
#define NOTE\_CS6 1109
#define NOTE\_D6 1175
#define NOTE\_DS6 1245
#define NOTE\_E6 1319
#define NOTE\_F6 1397
#define NOTE\_FS6 1480
#define NOTE\_G6 1568
#define NOTE\_GS6 1661
#define NOTE\_A6 1760
#define NOTE\_AS6 1865
#define NOTE\_B6 1976
#define NOTE\_C7 2093
#define NOTE\_CS7 2217
#define NOTE\_D7 2349
#define NOTE\_DS7 2489
#define NOTE\_E7 2637
#define NOTE\_F7 2794
#define NOTE\_FS7 2960
#define NOTE\_G7 3136
#define NOTE\_GS7 3322
#define NOTE\_A7 3520
#define NOTE\_AS7 3729
#define NOTE\_B7 3951
#define NOTE\_C8 4186
#define NOTE\_CS8 4435
#define NOTE\_D8 4699
#define NOTE\_DS8 4978

const uint32\_t mario_melody[] = {
NOTE_E7, NOTE_E7, 0, NOTE_E7,
0, NOTE_C7, NOTE_E7, 0,
NOTE_G7, 0, 0, 0,
NOTE_G6, 0, 0, 0,

NOTE_C7, 0, 0, NOTE_G6,
0, 0, NOTE_E6, 0,
0, NOTE_A6, 0, NOTE_B6,
0, NOTE_AS6, NOTE_A6, 0,

NOTE_G6, NOTE_E7, NOTE_G7,
NOTE_A7, 0, NOTE_F7, NOTE_G7,
0, NOTE_E7, 0, NOTE_C7,
NOTE_D7, NOTE_B6, 0, 0,

NOTE_C7, 0, 0, NOTE_G6,
0, 0, NOTE_E6, 0,
0, NOTE_A6, 0, NOTE_B6,
0, NOTE_AS6, NOTE_A6, 0,

NOTE_G6, NOTE_E7, NOTE_G7,
NOTE_A7, 0, NOTE_F7, NOTE_G7,
0, NOTE_E7, 0, NOTE_C7,
NOTE_D7, NOTE_B6, 0, 0
};

const uint32\_t second_melody[] = {
NOTE_D4, NOTE_G4, NOTE_FS4, NOTE_A4,
NOTE_G4, NOTE_C5, NOTE_AS4, NOTE_A4,
NOTE_FS4, NOTE_G4, NOTE_A4, NOTE_FS4, NOTE_DS4, NOTE_D4,
NOTE_C4, NOTE_D4,0,

NOTE_D4, NOTE_G4, NOTE_FS4, NOTE_A4,
NOTE_G4, NOTE_C5, NOTE_D5, NOTE_C5, NOTE_AS4, NOTE_C5, NOTE_AS4, NOTE_A4, //29 //8
NOTE_FS4, NOTE_G4, NOTE_A4, NOTE_FS4, NOTE_DS4, NOTE_D4,
NOTE_C4, NOTE_D4,0,

NOTE_D4, NOTE_FS4, NOTE_G4, NOTE_A4, NOTE_DS5, NOTE_D5,
NOTE_C5, NOTE_AS4, NOTE_A4, NOTE_C5,
NOTE_C4, NOTE_D4, NOTE_DS4, NOTE_FS4, NOTE_D5, NOTE_C5,
NOTE_AS4, NOTE_A4, NOTE_C5, NOTE_AS4, //58

NOTE_D4, NOTE_FS4, NOTE_G4, NOTE_A4, NOTE_DS5, NOTE_D5,
NOTE_C5, NOTE_D5, NOTE_C5, NOTE_AS4, NOTE_C5, NOTE_AS4, NOTE_A4, NOTE_C5, NOTE_G4,
NOTE_A4, 0, NOTE_AS4, NOTE_A4, 0, NOTE_G4,
NOTE_G4, NOTE_A4, NOTE_G4, NOTE_FS4, 0,

NOTE_C4, NOTE_D4, NOTE_G4, NOTE_FS4, NOTE_DS4,
NOTE_C4, NOTE_D4, 0,
NOTE_C4, NOTE_D4, NOTE_G4, NOTE_FS4, NOTE_DS4,
NOTE_C4, NOTE_D4
};

const uint32\_t mario_duration[] = {
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,

12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,

9, 9, 9,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,

12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,

9, 9, 9,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
};

const uint32\_t second_duration[] = {
8,4,8,4,
4,4,4,12,
4,4,4,4,4,4,
4,16,4,

8,4,8,4,
4,2,1,1,2,1,1,12,
4,4,4,4,4,4,
4,16,4,

4,4,4,4,4,4,
4,4,4,12,
4,4,4,4,4,4,
4,4,4,12,

4,4,4,4,4,4,
2,1,1,2,1,1,4,8,4,
2,6,4,2,6,4,
2,1,1,16,4,

4,8,4,4,4,
4,16,4,
4,8,4,4,4,
4,20,
};

const uint32\_t\* melody[] ={mario_melody, second_melody};
const uint32\_t\* note_durations[] = {mario_duration, second_duration};
const uint16\_t melody_slow_factor[] ={15, 30};

const uint32\_t melody_sizes[] ={sizeof(mario_melody)/sizeof(uint32\_t),
sizeof(second_duration)/sizeof(uint32\_t)};
#endif /\* MELODY\_H\_ \*/


6)主程序

main.c文件中添加如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/\* Private includes ----------------------------------------------------------\*/
/\* USER CODE BEGIN Includes \*/
#include <stdio.h>
#include "buzzer/buzzer.h"
/\* USER CODE END Includes \*/

int main(void) {
/\* USER CODE BEGIN 1 \*/

/\* USER CODE END 1 \*/

/\* MCU Configuration--------------------------------------------------------\*/

/\* Reset of all peripherals, Initializes the Flash interface and the Systick. \*/
HAL\_Init();

/\* USER CODE BEGIN Init \*/

/\* USER CODE END Init \*/

/\* Configure the system clock \*/
SystemClock\_Config();

/\* USER CODE BEGIN SysInit \*/

/\* USER CODE END SysInit \*/

/\* Initialize all configured peripherals \*/
MX\_GPIO\_Init();
MX\_TIM2\_Init();
MX\_USART1\_UART\_Init();
/\* USER CODE BEGIN 2 \*/
buzzer.TIMx = &htim2;
buzzer.TIMx_Channel = TIM_CHANNEL_3;
buzzer\_init(&buzzer);
printf("\*\*\*\*STM32CubeIDE:Buzzer PWM\*\*\*\r\n");

/\* USER CODE END 2 \*/

/\* Infinite loop \*/
/\* USER CODE BEGIN WHILE \*/
while (1) {
/\* USER CODE END WHILE \*/

/\* USER CODE BEGIN 3 \*/
// 循环播放旋律
buzzer\_play\_tone(&buzzer);
}
/\* USER CODE END 3 \*/
}

将蜂鸣器的正极引脚连接到定时2,PWM输出引脚PA2,编译代码,下载到芯片,即可驱动蜂鸣器。

文章来源: https://iotsmart.blog.csdn.net/article/details/125557152