IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STC89C52单片机蜂鸣器介绍以及《卡农》歌曲代码示例 -> 正文阅读

[嵌入式]STC89C52单片机蜂鸣器介绍以及《卡农》歌曲代码示例

目录

蜂鸣器介绍

驱动电路

三极管驱动

集成电路驱动

音乐的相关知识

音符与计时器重装载值对应表

将乐谱转换为宏定义的音调谱

实际代码演示:


蜂鸣器介绍

蜂鸣器是一种将电信号转换为声音信号的器件,常用来产生设备的按键音、报警音等提示信号

蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器

有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定

无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音

这里显然我们单片机上面的蜂鸣器是无源蜂鸣器,需要我们手动编写代码为其配置振荡脉冲的频率,而使其发出不同的音调。

驱动电路

三极管驱动

左图为高电平导通,右图为低电平导通

集成电路驱动

我们单片机上的ULN2003D驱动芯片的OUT1~~OUT4是用来驱动电机的,自然OUT5是用来驱动蜂鸣器的(BEEP),最后OUT6,7没有接线(之所以这样都是为了节约引脚口而考虑)

音乐的相关知识

我了解的也不多,所以可能有错的请大家见谅:

一个曲子简单的是由音调节拍决定的,音调是什么1,2,3,4,5,6,7这些数字,然后节拍是什么4分音符,8分音符。也就是音调持续的时间长短。

那么如何在蜂鸣器上模拟出各种各样的音调呢,首先是要知道不同音调有不同的频率,所以我们只要设法精确的将频率的信号输入到蜂鸣器就行

观察规律我们发现:每个音符满足12平分率

(前面一个音符的频率)*2^(1/12)=(后面一个音符的频率)

或者说(后面一个音符的频率)/{2^(1/12)}=(前面一个音符的频率)

?那么频率的公式为f=1/T,我们可以发现相邻音调之间就差那么十几赫兹,所以要求的精度还是比较高的,所以我们用定时器来计时,得到精确的频率脉冲。

之前学过波的相关知识,一个波形要有波峰和波谷才算一个完整的周期,所以我们在音符频率对应的周期内要将蜂鸣器的电压翻转2次。为了使定时器方便编码(不能说计时一半还没溢出就进行中断,来进行翻转),我们在以一个音调周期一半为一个单位进行计时并中断来翻转蜂鸣器,然后就实现了一个周期翻转2次的目的。

音符与计时器重装载值对应表

将低音L1为示例:T=1/f=1/262=0.0038167938931298,Tx1000000=3,816.793893129771

T/2=1,908.396946564885,取整1908,重装载值=65536-T/2=63628

?有了这个表以后就可以先将音符宏定义(例如高音用H开头,低音用L开头),然后创建一个数组将音符与对应的重装载值对应即可;

将乐谱转换为宏定义的音调谱

以天空之城简谱的节选为例,简单说明一下谱子里面包含的信息:

?下面我来写天空之城的第一行的音符,我以一个一分音符为时间基准,那么一节有4拍就是四个四分音符16

(将空音符定义为P,高音用H开头,低音用L开头,中央音符用M开头)

//第一小节
	P,	4,
	P,	4,
	P,	4,
	M6,	2,
	M7,	2,
//第二小节	
	H1,	4+2,
	M7,	2,
	H1,	4,
	H3,	4,
//第三小节	
	M7,	4+4+4,
	M3,	2,
	M3,	2,

这样一来将乐谱建立一个数组,那么音调与节拍就交替存在了

注意:还有一点就是,那个不同音调之间要有停顿感,为了实现这一目的所以在实际操作的时候,每个音符演奏以后,要将定时器延时5~10ms再进行下一个音符的演奏

实际代码演示:

音乐《卡农》片段

主函数:

#include <REGX52.H>
#include "Delay.h"
#include "Timer0.h"

//蜂鸣器端口定义
sbit Buzzer=P2^5;

//播放速度,将一个四分音符的时长设置为600(ms),并以四分音符的时长为基准
#define SPEED	600

//音符与索引对应表,P:休止符,L:低音,M:中音,H:高音,下划线:升半音符号#
#define P	0
#define L1	1
#define L1_	2
#define L2	3
#define L2_	4
#define L3	5
#define L4	6
#define L4_	7
#define L5	8
#define L5_	9
#define L6	10
#define L6_	11
#define L7	12
#define M1	13
#define M1_	14
#define M2	15
#define M2_	16
#define M3	17
#define M4	18
#define M4_	19
#define M5	20
#define M5_	21
#define M6	22
#define M6_	23
#define M7	24
#define H1	25
#define H1_	26
#define H2	27
#define H2_	28
#define H3	29
#define H4	30
#define H4_	31
#define H5	32
#define H5_	33
#define H6	34
#define H6_	35
#define H7	36

//索引与频率对照表
unsigned int FreqTable[]={
	0,
	63628,63731,63835,63928,64021,64103,64185,64260,64331,64400,64463,64528,
	64580,64633,64684,64732,64777,64820,64860,64898,64934,64968,65000,65030,
	65058,65085,65110,65134,65157,65178,65198,65217,65235,65252,65268,65283,
};

//乐谱
unsigned char code Music[]={//乐谱较长加上关键字code将其储存在ROM(flash)
	//音符,时值,
	//1
	H5,2,
	H3,1,
	H4,1,
	H5,2,
	H3,1,
	H4,1,
	H5,1,
	M7,1,
	M6,1,
	M7,1,
	H1,1,
	H2,1,
	H3,1,
	H4,1,
	
	//2
	H3,2,
	H1,1,
	H2,1,
	H3,2,
	M3,1,
	M4,1,
	M5,1,
	M6,1,
	M5,1,
	M4,1,
	M5,1,
	H1,1,
	M7,1,
	H1,1,
	
	//3
	M6,2,
	H1,1,
	M7,1,
	M6,2,
	M5,1,
	M4,1,
	M5,1,
	M4,1,
	M3,1,
	M4,1,
	M5,1,
	M6,1,
	M7,1,
	H1,1,
	
	//4
	M6,2,
	H1,1,
	M7,1,
	H1,2,
	M7,1,
	H1,1,
	M7,1,
	M6,1,
	M7,1,
	H1,1,
	H2,1,
	H3,1,
	H4,1,
	H5,1,
	
	//5
	H5,2,
	H3,1,
	H4,1,
	H5,2,
	H3,1,
	H4,1,
	H5,1,
	M7,1,
	M6,1,
	M7,1,
	H1,1,
	H2,1,
	H3,1,
	H4,1,
	
	//6
	H3,2,
	H1,1,
	H2,1,
	H3,2,
	M3,1,
	M4,1,
	M5,1,
	M6,1,
	M5,1,
	M4,1,
	M5,1,
	H1,1,
	M7,1,
	H1,1,
			
	0xFF	//终止标志
};

unsigned char FreqSelect,MusicSelect;//MusicSelect为乐谱数组下标,FreqSelect音调宏定义

void main()
{
	Timer0Init();
	while(1)
	{
		if(Music[MusicSelect]!=0xFF)	//如果不是停止标志位
		{
			FreqSelect=Music[MusicSelect];	//选择音符对应的频率
			MusicSelect++;

			Delay(SPEED/4*Music[MusicSelect]);	//选择音符对应的时长
			MusicSelect++;

			TR0=0;//不同音符间短暂停顿,利用延时开关定时器实现
			Delay(5);	
			TR0=1;
		}
		else	//如果是停止标志位
		{
			TR0=0;  //关闭定时器
			while(1);
		}
	}
}

void Timer0_Routine() interrupt 1
{
	if(FreqTable[FreqSelect])	//如果是休止符(0),那么不播放声音,只进行延时
	{
		//取对应频率值的重装载值到定时器(确认音高)FreqSelect=Music[MusicSelect]
		TL0 = FreqTable[FreqSelect]%256;		//设置低位定时初值
		TH0 = FreqTable[FreqSelect]/256;		//设置高位定时初值
		Buzzer=!Buzzer;	//翻转蜂鸣器IO口(注意这里的重装值是周期的一半,故仅进行一次蜂鸣器的翻转)
	}
}

定时器:

void Timer0Init(void)
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0=1;
	EA=1;
	PT0=0;
}

延时函数Delay()

void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-01-30 19:05:27  更:2022-01-30 19:06:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:21:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码