龙芯1c库是把龙芯1c的常用外设的常用功能封装为一个库,可用于裸机编程和实时系统,类似于STM32库。Git地址:http://git.oschina.NET/caogos/OpenLoongsonLib1c

无源蜂鸣器唱歌的原理

基本原理

一般说来,单片机演奏音乐基本都是单音频率,它不包含相应幅度的谐波频率,也就是说不能象电子琴那样能奏出多种音色的声音。因此单片机奏乐只需弄清楚两个概念即可,也就是“音调”和“节拍”。音调表示一个音符唱多高的频率,节拍表示一个音符唱多长的时间。

音调

音调简介

一个音调对应一个频率。即do re mi fa so la xi。乐谱中有高音,中音和低音,每个都有do re mi fa so la xi。即总共3*7=21个频率。

// do re mi fa so la xi的低音频率(单位hz)
#define BUZZER_LOW_DO_1         (262)
#define BUZZER_LOW_RE_2         (294)
#define BUZZER_LOW_MI_3         (330)
#define BUZZER_LOW_FA_4         (349)
#define BUZZER_LOW_SO_5         (392)
#define BUZZER_LOW_LA_6         (440)
#define BUZZER_LOW_XI_7         (494)
// 中音
#define BUZZER_MIDDLE_DO_1      (523)
#define BUZZER_MIDDLE_RE_2      (587)
#define BUZZER_MIDDLE_MI_3      (659)
#define BUZZER_MIDDLE_FA_4      (698)
#define BUZZER_MIDDLE_SO_5      (784)
#define BUZZER_MIDDLE_LA_6      (880)
#define BUZZER_MIDDLE_XI_7      (988)
// 高音
#define BUZZER_HIGH_DO_1        (1047)
#define BUZZER_HIGH_RE_2        (1175)
#define BUZZER_HIGH_MI_3        (1319)
#define BUZZER_HIGH_FA_4        (1397)
#define BUZZER_HIGH_SO_5        (1568)
#define BUZZER_HIGH_LA_6        (1760)
#define BUZZER_HIGH_XI_7        (1976)

识别乐谱中的高低音

5351中的1是高音,音符1的上方有个小圆点;
615中的1也是高音;
其它的都是中音。
和高音相反,低音是在音符的底下有个小圆点。

无源蜂鸣器和有缘蜂鸣器的区别

注意,这里的“源”不是指电源。而是指震荡源。
无源蜂鸣器的特点是:
1 无源内部不带震荡源,所以如果用直流信号无法令其鸣叫。必须用2K~5K的方波去驱动它
2 声音频率可控,可以做出“多来米发索拉西”的效果。
3 在一些特例中,可以和LED复用一个控制口
有源蜂鸣器的特点是:
1 有源蜂鸣器内部带震荡源,所以只要一通电就会叫
2 程序控制方便,单片机一个高低电平就可以让其发出声音,而无源蜂鸣器却做不到。

音调的软件实现

经过前面介绍,已经知道一个音调对应一个频率,给无源蜂鸣器不同频率的方波可以唱出do re mi fa so la xi。
通常,使用硬件PWM产生占空比为50%的不同频率的方波来实现。
龙芯1c库中已经有现成的PWM接口可供使用,接口中PWM周期的时间单位为ns,即PWM周期T = 1000000000 / freq。另外,目前(2017年7月)龙芯1c库中浮点功能还未完善,所以需要把占空比(浮点数)手动换算为高低电平的时间长度,占空比为50%,即周期T / 2就是一个PWM波形内高低电平的时间长度。虽然,我坚信使用浮点功能早晚会调通的,龙芯1C库中的PWM接口用占空比来表示也更符合人们的习惯,但这里还是需要稍微变通一下。

// 播放指定音高
void buzzer_sound(unsigned int freq)
{buzzer_pwm.period_ns = 1000000000 / freq;buzzer_pwm.low_ns = buzzer_pwm.period_ns / 2;pwm_init(&buzzer_pwm);return ;
}

节拍

节拍简介

节拍表示一个音符唱多长的时间,即一个频率的PWM波形的持续时间。

识别乐谱中的节拍

参考百度文库的《简谱中常用的音乐记号》

在一张乐谱中,我们经常会看到这样的表达式,如1=C (4/4) 、1=G(3/4) ……  等等,这里1=C (4/4),1=G(3/4) 表示乐谱的曲调,和我们前面所谈的音调有很大的关联,4/4、3/4  就是用来表示节拍的。以3/4 为例加以说明,它表示乐谱中以四分音符为节拍,每一小结有三拍。

其中1 、2 为一拍,3、4、5为一拍,6为一拍共三拍。1 、2的时长为四分音符的一半,即为八分音符长,3、4的时长为八分音符的一半,即为十六分音符长,5的时长为四分音符的一半,即为八分音符长,6的时长为四分音符长。
一般说来,如果乐曲没有特殊说明,一拍的时长大约为400—500ms。

节拍的软件实现

根据前面介绍已经知道,节拍就是频率持续的时间。并且一拍的时间为四五百ms,这里选择一拍为400ms,那么十六分音符长为400ms / 16 = 25ms,毫秒级的延时用“龙芯1c库”中的函数delay_ms(n)实现是没问题的。

// 测试无源蜂鸣器--依次播放do re mi fa so la xi
void buzzer_test(void)
{buzzer_init();buzzer_sound(BUZZER_LOW_DO_1);delay_ms(BUZZER_DELAY_ONE_NOTE);buzzer_sound(BUZZER_LOW_RE_2);delay_ms(BUZZER_DELAY_ONE_NOTE);buzzer_sound(BUZZER_LOW_MI_3);delay_ms(BUZZER_DELAY_ONE_NOTE);buzzer_sound(BUZZER_LOW_FA_4);delay_ms(BUZZER_DELAY_ONE_NOTE);buzzer_sound(BUZZER_LOW_SO_5);delay_ms(BUZZER_DELAY_ONE_NOTE);buzzer_sound(BUZZER_LOW_LA_6);delay_ms(BUZZER_DELAY_ONE_NOTE);buzzer_sound(BUZZER_LOW_XI_7);delay_ms(BUZZER_DELAY_ONE_NOTE);buzzer_stop();}

歌曲简谱

歌曲《送别》的简谱

将简谱转换为音调和节拍的数组

// 一拍的时间,单位ms
#define BUZZER_DELAY_ONE_NOTE   (400)// 简谱中一个音符的结构
typedef struct
{unsigned int freq;          // 音调(频率),单位hzunsigned int time_ms;       // 节拍(一个音符持续的时间),单位ms
}buzzer_note_t;
// <<送别>>的简谱
buzzer_note_t song[] = {// 长亭外{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1}, {BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2}, {BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*2},// 古道边{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*2},// 芳草碧连{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE/2},// 天{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE*3},{0,                  BUZZER_DELAY_ONE_NOTE*1},// 晚风拂柳{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*(1+1/2)},{BUZZER_MIDDLE_XI_7, BUZZER_DELAY_ONE_NOTE/2},// 笛声残{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*2},// 夕阳山外{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_FA_4, BUZZER_DELAY_ONE_NOTE*(1+1/2)},{BUZZER_LOW_XI_7,    BUZZER_DELAY_ONE_NOTE/2},// 山{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE*3},{0,                  BUZZER_DELAY_ONE_NOTE*1},// 天之涯{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*1},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*2},// 地之角{BUZZER_MIDDLE_XI_7, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_XI_7, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*2},// 知交半零{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_XI_7, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_XI_7, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE/2},// 落{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE*3},{0,                  BUZZER_DELAY_ONE_NOTE*1},// 一瓢浊酒{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*(1+1/2)},{BUZZER_MIDDLE_XI_7, BUZZER_DELAY_ONE_NOTE/2},// 尽余欢{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*2},// 今宵别梦{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_FA_4, BUZZER_DELAY_ONE_NOTE*(1+1/2)},{BUZZER_LOW_XI_7,    BUZZER_DELAY_ONE_NOTE/2},// 寒{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE*3},{0,                  BUZZER_DELAY_ONE_NOTE*1},// 长亭外{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*2},// 古道边{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*2},// 芳草碧连{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE/2},// 天{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE*3},{0,                  BUZZER_DELAY_ONE_NOTE*1},// 晚风拂柳{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*(1+1/2)},{BUZZER_MIDDLE_XI_7, BUZZER_DELAY_ONE_NOTE/2},// 笛声残{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*2},// 夕阳山外{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_FA_4, BUZZER_DELAY_ONE_NOTE*(1+1/2)},{BUZZER_LOW_XI_7,    BUZZER_DELAY_ONE_NOTE/2},// 山{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE*3},{0,                  BUZZER_DELAY_ONE_NOTE*1},// 结束符{0, 0}
};


如果想唱其它的歌,只需根据歌曲的简谱重新生成这个数组就行。

实现唱歌

根据前面的介绍,已经知道,使用pwm_init()控制音调的频率,使用delay_ms()控制音符的时长。再加上已经将一首歌的简谱转换为了音调和节拍的数组,那么唱歌就变成了顺序执行音调和节拍的数组。

// 播放指定音高
void buzzer_sound(unsigned int freq)
{buzzer_pwm.period_ns = 1000000000 / freq;buzzer_pwm.low_ns = buzzer_pwm.period_ns / 2;pwm_init(&buzzer_pwm);return ;
}// 停止播放
void buzzer_stop(void)
{pwm_disable(&buzzer_pwm);gpio_init(buzzer_gpio, gpio_mode_output);gpio_set(buzzer_gpio, gpio_level_high);return ;
}/** 休止符* @time_ms 休止符时间*/
void buzzer_quiet(unsigned int time_ms)
{pwm_disable(&buzzer_pwm);delay_ms(time_ms);pwm_enable(&buzzer_pwm);return ;
}// 无源蜂鸣器唱歌
void buzzer_play(void)
{int i = 0;buzzer_init();while (1){// 判断是否结束if (0 == song[i].time_ms)break;if (0 == song[i].freq){buzzer_quiet(song[i].time_ms);}else{buzzer_sound(song[i].freq);delay_ms(song[i].time_ms);            }i++;}buzzer_stop();return ;
}

实物图

无源蜂鸣器模块
VCC ---------------- 3.3V
GND ---------------- GND
I/O ---------------- GPIO47

源码清单

pwm

之前(2017年7月)裸机编程时,浮点运算还有点问题,为了避免使用浮点运算,修改了“龙芯1c库”中的pwm的部分代码。

目前(2017年9月)硬浮点功能已调通,可以直接使用浮点数,不用再进行如下修改。

pwm_init()函数的对比照,左边为蜂鸣器唱歌源码,右边为龙芯1c库中的源码。注意,等浮点运算全部调通之后,不需要这样修改,并且龙芯1c库中使用占空比这种方式更符合平常的使用习惯。

Buzzer.h

// 无源蜂鸣器唱歌的头文件#ifndef __OPENLOONGSON_BUZZER_H
#define __OPENLOONGSON_BUZZER_H// 无源蜂鸣器初始化
void buzzer_init(void);// 停止播放
void buzzer_stop(void);// 无源蜂鸣器唱歌
void buzzer_play(void);// 测试无源蜂鸣器--依次播放do re mi fa so la xi
void buzzer_test(void);#endif

Buzzer.c

// 无源蜂鸣器唱歌的源文件#include "../lib/public.h"
#include "../lib/pwm.h"
#include "../lib/gpio.h"
#include "../lib/delay.h"// do re mi fa so la xi的低音频率(单位hz)
#define BUZZER_LOW_DO_1         (262)
#define BUZZER_LOW_RE_2         (294)
#define BUZZER_LOW_MI_3         (330)
#define BUZZER_LOW_FA_4         (349)
#define BUZZER_LOW_SO_5         (392)
#define BUZZER_LOW_LA_6         (440)
#define BUZZER_LOW_XI_7         (494)
// 中音
#define BUZZER_MIDDLE_DO_1      (523)
#define BUZZER_MIDDLE_RE_2      (587)
#define BUZZER_MIDDLE_MI_3      (659)
#define BUZZER_MIDDLE_FA_4      (698)
#define BUZZER_MIDDLE_SO_5      (784)
#define BUZZER_MIDDLE_LA_6      (880)
#define BUZZER_MIDDLE_XI_7      (988)
// 高音
#define BUZZER_HIGH_DO_1        (1047)
#define BUZZER_HIGH_RE_2        (1175)
#define BUZZER_HIGH_MI_3        (1319)
#define BUZZER_HIGH_FA_4        (1397)
#define BUZZER_HIGH_SO_5        (1568)
#define BUZZER_HIGH_LA_6        (1760)
#define BUZZER_HIGH_XI_7        (1976)// 一拍的时间,单位ms
#define BUZZER_DELAY_ONE_NOTE   (400)// 简谱中一个音符的结构
typedef struct
{unsigned int freq;          // 音调(频率),单位hzunsigned int time_ms;       // 节拍(一个音符持续的时间),单位ms
}buzzer_note_t;
// <<送别>>的简谱
buzzer_note_t song[] = {// 长亭外{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1}, {BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2}, {BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*2},// 古道边{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*2},// 芳草碧连{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE/2},// 天{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE*3},{0,                  BUZZER_DELAY_ONE_NOTE*1},// 晚风拂柳{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*(1+1/2)},{BUZZER_MIDDLE_XI_7, BUZZER_DELAY_ONE_NOTE/2},// 笛声残{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*2},// 夕阳山外{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_FA_4, BUZZER_DELAY_ONE_NOTE*(1+1/2)},{BUZZER_LOW_XI_7,    BUZZER_DELAY_ONE_NOTE/2},// 山{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE*3},{0,                  BUZZER_DELAY_ONE_NOTE*1},// 天之涯{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*1},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*2},// 地之角{BUZZER_MIDDLE_XI_7, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_XI_7, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*2},// 知交半零{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_XI_7, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_XI_7, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE/2},// 落{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE*3},{0,                  BUZZER_DELAY_ONE_NOTE*1},// 一瓢浊酒{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*(1+1/2)},{BUZZER_MIDDLE_XI_7, BUZZER_DELAY_ONE_NOTE/2},// 尽余欢{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*2},// 今宵别梦{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_FA_4, BUZZER_DELAY_ONE_NOTE*(1+1/2)},{BUZZER_LOW_XI_7,    BUZZER_DELAY_ONE_NOTE/2},// 寒{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE*3},{0,                  BUZZER_DELAY_ONE_NOTE*1},// 长亭外{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*2},// 古道边{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*2},// 芳草碧连{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE/2},// 天{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE*3},{0,                  BUZZER_DELAY_ONE_NOTE*1},// 晚风拂柳{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*(1+1/2)},{BUZZER_MIDDLE_XI_7, BUZZER_DELAY_ONE_NOTE/2},// 笛声残{BUZZER_MIDDLE_LA_6, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_HIGH_DO_1,   BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*2},// 夕阳山外{BUZZER_MIDDLE_SO_5, BUZZER_DELAY_ONE_NOTE*1},{BUZZER_MIDDLE_RE_2, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_MI_3, BUZZER_DELAY_ONE_NOTE/2},{BUZZER_MIDDLE_FA_4, BUZZER_DELAY_ONE_NOTE*(1+1/2)},{BUZZER_LOW_XI_7,    BUZZER_DELAY_ONE_NOTE/2},// 山{BUZZER_MIDDLE_DO_1, BUZZER_DELAY_ONE_NOTE*3},{0,                  BUZZER_DELAY_ONE_NOTE*1},// 结束符{0, 0}
};unsigned int buzzer_gpio = LS1C_PWM3_GPIO47;
pwm_info_t buzzer_pwm;// 无源蜂鸣器初始化
void buzzer_init(void)
{buzzer_pwm.gpio = buzzer_gpio;buzzer_pwm.mode = PWM_MODE_NORMAL;
}// 播放指定音高
void buzzer_sound(unsigned int freq)
{buzzer_pwm.period_ns = 1000000000 / freq;buzzer_pwm.low_ns = buzzer_pwm.period_ns / 2;pwm_init(&buzzer_pwm);return ;
}// 停止播放
void buzzer_stop(void)
{pwm_disable(&buzzer_pwm);gpio_init(buzzer_gpio, gpio_mode_output);gpio_set(buzzer_gpio, gpio_level_high);return ;
}/** 休止符* @time_ms 休止符时间*/
void buzzer_quiet(unsigned int time_ms)
{pwm_disable(&buzzer_pwm);delay_ms(time_ms);pwm_enable(&buzzer_pwm);return ;
}// 测试无源蜂鸣器--依次播放do re mi fa so la xi
void buzzer_test(void)
{buzzer_init();buzzer_sound(BUZZER_LOW_DO_1);delay_ms(BUZZER_DELAY_ONE_NOTE);buzzer_sound(BUZZER_LOW_RE_2);delay_ms(BUZZER_DELAY_ONE_NOTE);buzzer_sound(BUZZER_LOW_MI_3);delay_ms(BUZZER_DELAY_ONE_NOTE);buzzer_sound(BUZZER_LOW_FA_4);delay_ms(BUZZER_DELAY_ONE_NOTE);buzzer_sound(BUZZER_LOW_SO_5);delay_ms(BUZZER_DELAY_ONE_NOTE);buzzer_sound(BUZZER_LOW_LA_6);delay_ms(BUZZER_DELAY_ONE_NOTE);buzzer_sound(BUZZER_LOW_XI_7);delay_ms(BUZZER_DELAY_ONE_NOTE);buzzer_stop();}// 无源蜂鸣器唱歌
void buzzer_play(void)
{int i = 0;buzzer_init();while (1){// 判断是否结束if (0 == song[i].time_ms)break;if (0 == song[i].freq){buzzer_quiet(song[i].time_ms);}else{buzzer_sound(song[i].freq);delay_ms(song[i].time_ms);            }i++;}buzzer_stop();return ;
}

main.c

#include "../lib/public.h"
#include "../lib/gpio.h"
#include "../lib/delay.h"
#include "../example/test_gpio.h"
#include "../example/test_delay.h"
#include "../example/test_simulate_i2c.h"
#include "../example/test_timer.h"
#include "buzzer.h"// pmon提供的打印接口
struct callvectors *callvec;int main(int argc, char **argv, char **env, struct callvectors *cv)
{callvec = cv;// 测试无源蜂鸣器--依次播放do re mi fa so la xi
//    buzzer_test();while (1){// 无源蜂鸣器唱歌buzzer_play();// 延时一会delay_s(5);}return(0);
}

完整的代码请移步到http://pan.baidu.com/s/1dEA19GP

感谢耐心阅读!

用龙芯1c库实现无源蜂鸣器唱歌《送别》相关推荐

  1. 【龙芯1c库】封装模拟I2C接口和使用示例

    龙芯1c库是把龙芯1c的常用外设的常用功能封装为一个库,类似于STM32库.Git地址:https://gitee.com/caogos/OpenLoongsonLib1c I2C接口是常用的接口之一 ...

  2. 【龙芯1c库】封装硬件pwm接口和使用示例

    龙芯1c库是把龙芯1c的常用外设的常用功能封装为一个库,类似于STM32库.Git地址:https://gitee.com/caogos/OpenLoongsonLib1c 本文通过"龙芯1 ...

  3. 【龙芯1c库】封装硬件定时器接口和使用示例

    龙芯1c库是把龙芯1c的常用外设的常用功能封装为一个库,类似于STM32库.完整源码请移步到https://gitee.com/caogos/OpenLoongsonLib1c 龙芯1c库中硬件定时器 ...

  4. 【龙芯1c库】移植硬浮点FPU

    龙芯1c库是把龙芯1c的常用外设的常用功能封装为一个库,类似于STM32库.完整源码请移步到https://gitee.com/caogos/OpenLoongsonLib1c 龙芯1C上有硬浮点协处 ...

  5. 【龙芯1c库】封装CAN接口和使用示例

    can使用还是比较广泛的,之前有网友在龙芯1b和龙芯1c上已经测试过了在裸机编程中使用CAN接口,这里把他们分享的程序贴上来,供大家参考. 龙芯1b上的测试程序在https://gitee.com/c ...

  6. 在龙芯1C单片机上使用ESP8266 wifi透传模块

    龙芯1C既可以运行linux,也可以当作单片机用.当用作linux时,可以通过USB wifi模块RTL8192C,RTL8188ETV等,当作单片机用时,可以像STM32那样使用串口透传wifi模块 ...

  7. Buildroot 龙芯1C支持指南

    本文转载自:https://github.com/pengphei/smartloong-sphinx/blob/master/source/cn/loongson1c_buildroot_guide ...

  8. 串口例程 龙芯1c_Buildroot 龙芯1C支持指南

    Buildroot 龙芯1C支持指南 引子:从龙芯1C预订拿到板子已经很长一段时间了,因为各种事情,一直让它呆在角落的冷宫里.昨天,愤而出去骑行,有导航出错,入的一片幽静山林,正能量爆棚,一下午休息, ...

  9. 龙芯处理器可以适配鸿蒙os吗,SylixOS龙芯1C适配总结

    1.龙芯1C简介 1.1龙芯1C简介 龙芯 1C300(以下简称 1C)芯片是基于 LS232 处理器核的高性价比单芯片系统,可应用于指纹生物识别.物联传感等领域.1C 包含浮点处理单元,可以有效增强 ...

最新文章

  1. 前沿科技山雨欲来,四大领域存创新机会
  2. 程序的内存模型—内存四区—堆区
  3. CSDN编程挑战——《交替字符串》
  4. spark总结——转载
  5. PS 色调——老照片效果
  6. NULL、nil、Nil、NSNull的区别
  7. C++ 实现无向图的最小生成树Prim算法(附完整代码)
  8. 第 4-2 课:反射和动态代理 + 面试题
  9. 机器学习是如何改善企业生产力的?(内附机器智能版图)
  10. insert into select from 部分字段插入_MySQL的故障分析,Insert 加锁与死锁分析-爱可生
  11. ios 微信分享重新编码链接_微信民众号IOS端复制链接失足,安卓端分享链接翻开只能进入首页等题目的处理...
  12. android下在屏幕适配小总结
  13. java 取模运算_JAVA算术运算符_四则与取模
  14. python3的字符串操作
  15. access orcad 数据库_OrCAD Capture CIS使用MySQL数据库
  16. H5微信分享 自定义图标和内容(以及二次分享图片丢失的解决办法)
  17. 网络基础2---->网络数据传输(局域网)
  18. 思维导图 基础篇(11)应用-文章分析-框架法
  19. “蚂蚁呀嘿” 刷屏的背后:算法工程师带你理性解构神曲
  20. 想学文字生成图片?3招告诉你描述文字生成图片怎么做

热门文章

  1. 压缩感知的实现——图像重建(含matlab代码)
  2. 求n以内的所有素数(质数)个数
  3. 7 张简单图片帮你弄懂企业级架构
  4. 苏州IT/互联网交流群
  5. A* 算法的实际应用-路径规划(附Python实现代码)
  6. 2012-11-1小光棍节【就在今天,我们进行了这学期的第一次考试】下面写下今天的考试心得~!
  7. JWT的初步了解以及session、cookie机制
  8. 一、ECMAScript 6/7/8简介
  9. 无线通信基础知识6:射频器件的基本参数2
  10. 云师大商学院计算机,高考倒计时,云师大商学院为考生加油!