From c6a1e7c00cd2946cef7716b205026a907136778b Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Sun, 12 Jul 2026 18:41:28 +0800
Subject: [PATCH] Add ex1.servo-sg90
---
ex1.servo-sg90/Board/buzzer.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 191 insertions(+), 0 deletions(-)
diff --git a/ex1.servo-sg90/Board/buzzer.c b/ex1.servo-sg90/Board/buzzer.c
new file mode 100644
index 0000000..f39e80c
--- /dev/null
+++ b/ex1.servo-sg90/Board/buzzer.c
@@ -0,0 +1,191 @@
+/**********************************************************************
+* Copyright: (C)2024 LingYun IoT System Studio
+* Author: GuoWenxue<guowenxue@gmail.com>
+* Description: ISKBoard buzzer/beeper driver and music play
+*
+* ChangeLog:
+* Version Date Author Description
+* V1.0.0 2024.08.29 GuoWenxue Release initial version
+***********************************************************************/
+
+#include "tim.h"
+#include "buzzer.h"
+
+#define mdelay(ms) HAL_Delay(ms)
+#define ARRAY_SIZE(song) (sizeof(song)/sizeof(song[0]))
+
+/* 音符频率定义(Hz) */
+#define NOTE_C4 524
+#define NOTE_D4 588
+#define NOTE_E4 660
+#define NOTE_F4 698
+#define NOTE_G4 784
+#define NOTE_A4 880
+#define NOTE_B4 988
+#define NOTE_C5 1046
+#define NOTE_D5 1174
+#define NOTE_E5 1318
+#define NOTE_F5 1396
+#define NOTE_G5 1568
+#define NOTE_A5 1760
+#define NOTE_B5 1976
+#define NOTE_C6 2093
+#define REST 0
+
+#define BEAT 400 /* 一拍时长(ms),可自行调整节奏快慢 */
+
+/* 《小星星》简谱:
+ * 1 1 5 5 6 6 5 - 4 4 3 3 2 2 1
+ * 5 5 4 4 3 3 2 - 5 5 4 4 3 3 2
+ * 1 1 5 5 6 6 5 - 4 4 3 3 2 2 1
+ * (C=1, D=2, E=3, F=4, G=5, A=6, B=7)
+ */
+const Note_t twinkle[] =
+{
+ /* Twinkle twinkle little star */
+ {NOTE_C4, BEAT}, {NOTE_C4, BEAT}, {NOTE_G4, BEAT}, {NOTE_G4, BEAT},
+ {NOTE_A4, BEAT}, {NOTE_A4, BEAT}, {NOTE_G4, BEAT * 2},
+
+ /* How I wonder what you are */
+ {NOTE_F4, BEAT}, {NOTE_F4, BEAT}, {NOTE_E4, BEAT}, {NOTE_E4, BEAT},
+ {NOTE_D4, BEAT}, {NOTE_D4, BEAT}, {NOTE_C4, BEAT * 2},
+
+ /* Up above the world so high */
+ {NOTE_G4, BEAT}, {NOTE_G4, BEAT}, {NOTE_F4, BEAT}, {NOTE_F4, BEAT},
+ {NOTE_E4, BEAT}, {NOTE_E4, BEAT}, {NOTE_D4, BEAT * 2},
+
+ /* Like a diamond in the sky */
+ {NOTE_G4, BEAT}, {NOTE_G4, BEAT}, {NOTE_F4, BEAT}, {NOTE_F4, BEAT},
+ {NOTE_E4, BEAT}, {NOTE_E4, BEAT}, {NOTE_D4, BEAT * 2},
+
+ /* Twinkle twinkle little star (repeat) */
+ {NOTE_C4, BEAT}, {NOTE_C4, BEAT}, {NOTE_G4, BEAT}, {NOTE_G4, BEAT},
+ {NOTE_A4, BEAT}, {NOTE_A4, BEAT}, {NOTE_G4, BEAT * 2},
+
+ /* How I wonder what you are (repeat) */
+ {NOTE_F4, BEAT}, {NOTE_F4, BEAT}, {NOTE_E4, BEAT}, {NOTE_E4, BEAT},
+ {NOTE_D4, BEAT}, {NOTE_D4, BEAT}, {NOTE_C4, BEAT * 2},
+};
+const uint32_t twinkle_count = ARRAY_SIZE(twinkle);
+
+/* 《祝你生日快乐》(Happy Birthday to You)
+ * 该曲旋律/歌词经美国法院2015-2016年裁定确认为公有领域作品,可放心使用。
+ * 简谱: 5 5 6 5 1' 7 | 5 5 6 5 2' 1' | 5 5 5' 3' 1' 7 6 | 4' 4' 3' 1' 2' 1'
+ */
+const Note_t happy_birthday[] =
+{
+ /* Happy Birthday to you */
+ {NOTE_G4, BEAT / 2}, {NOTE_G4, BEAT / 2}, {NOTE_A4, BEAT}, {NOTE_G4, BEAT},
+ {NOTE_C5, BEAT}, {NOTE_B4, BEAT * 2},
+
+ /* Happy Birthday to you */
+ {NOTE_G4, BEAT / 2}, {NOTE_G4, BEAT / 2}, {NOTE_A4, BEAT}, {NOTE_G4, BEAT},
+ {NOTE_D5, BEAT}, {NOTE_C5, BEAT * 2},
+
+ /* Happy Birthday dear friend */
+ {NOTE_G4, BEAT / 2}, {NOTE_G4, BEAT / 2}, {NOTE_G5, BEAT}, {NOTE_E5, BEAT},
+ {NOTE_C5, BEAT}, {NOTE_B4, BEAT}, {NOTE_A4, BEAT * 2},
+
+ /* Happy Birthday to you */
+ {NOTE_F5, BEAT / 2}, {NOTE_F5, BEAT / 2}, {NOTE_E5, BEAT}, {NOTE_C5, BEAT},
+ {NOTE_D5, BEAT}, {NOTE_C5, BEAT * 2},
+
+ /* 结尾留白 */
+ {REST, BEAT * 2},
+};
+const uint32_t happy_birthday_count = ARRAY_SIZE(happy_birthday);
+
+/* 《Jingle Bells》(铃儿响叮当)
+ * 1857年James Lord Pierpont创作,早已进入公有领域。
+ * (下面是常见的简化版本,节奏为大致还原,供播放测试使用)
+ */
+const Note_t jingle_bells[] =
+{
+ /* Jingle bells, jingle bells, jingle all the way */
+ {NOTE_E4, BEAT}, {NOTE_E4, BEAT}, {NOTE_E4, BEAT * 2},
+ {NOTE_E4, BEAT}, {NOTE_E4, BEAT}, {NOTE_E4, BEAT * 2},
+ {NOTE_E4, BEAT}, {NOTE_G4, BEAT}, {NOTE_C4, BEAT}, {NOTE_D4, BEAT},
+ {NOTE_E4, BEAT * 4},
+
+ /* Oh what fun it is to ride in a one-horse open sleigh */
+ {NOTE_F4, BEAT}, {NOTE_F4, BEAT}, {NOTE_F4, BEAT}, {NOTE_F4, BEAT},
+ {NOTE_F4, BEAT}, {NOTE_E4, BEAT}, {NOTE_E4, BEAT}, {NOTE_E4, BEAT / 2}, {NOTE_E4, BEAT / 2},
+ {NOTE_E4, BEAT}, {NOTE_D4, BEAT}, {NOTE_D4, BEAT}, {NOTE_E4, BEAT},
+ {NOTE_D4, BEAT * 2}, {NOTE_G4, BEAT * 2},
+
+ /* 结尾留白 */
+ {REST, BEAT * 2},
+};
+const uint32_t jingle_bells_count = ARRAY_SIZE(jingle_bells);
+
+/*
+ *+----------------------------+
+ *| PWM buzzer API |
+ *+----------------------------+
+ */
+
+/**
+ * @brief 设置蜂鸣器发声频率(占空比固定50%)
+ */
+static inline void Buzzer_SetFreq(uint32_t freq)
+{
+ /* TIM1 初始化 PSC = 79,计数时钟 = 80MHz/80 = 1MHz */
+ uint32_t arr = 1000000U / freq - 1U;
+ __HAL_TIM_SET_AUTORELOAD(&htim1, arr);
+ __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_4, arr / 2U);
+ __HAL_TIM_SET_COUNTER(&htim1, 0);
+}
+
+/**
+ * @brief 让蜂鸣器响 $times 次,每次间隔 $interval 毫秒
+ */
+void beep_start(uint16_t times, uint16_t interval)
+{
+ Buzzer_SetFreq(2700);
+
+ while( times-- )
+ {
+ /* Start buzzer */
+ HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);
+
+ mdelay(interval);
+
+ /* Stop buzzer */
+ HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_4);
+
+ mdelay(interval);
+ }
+}
+
+/**
+ * @brief 播放单个音符
+ */
+static void Buzzer_PlayNote(uint32_t freq, uint32_t duration_ms)
+{
+ if (freq == 0)
+ {
+ HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_4);
+ mdelay(duration_ms);
+ return;
+ }
+
+ Buzzer_SetFreq(freq);
+
+ HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);
+ mdelay(duration_ms - 30);
+
+ HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_4);
+
+ mdelay(30);
+}
+
+/**
+ * @brief 播放歌曲
+ */
+void Play_Song(const Note_t *song, uint32_t note_count)
+{
+ for (uint32_t i = 0; i < note_count; i++)
+ {
+ Buzzer_PlayNote(song[i].freq, song[i].duration);
+ }
+}
--
Gitblit v1.10.0