51单片机学习笔记_11 蜂鸣器,识简谱,根据简谱编写蜂鸣器代码

news2024/11/28 20:48:54

蜂鸣器实验

蜂鸣器简单地说,就是电磁线圈和磁铁对振动膜的作用。

单片机的是无源蜂鸣器,不能一直充电,需要外部控制器发送震荡信号,可以改变频率产生不同的音色、音调。

大多数有源蜂鸣器则没有这个效果,有源蜂鸣器外观与之相同,内部自带震荡源,接上电就能响,但不能改变频率。

image-20230207154444964

我们知道三极管的作用是不用单片机自己直接驱动单片机。

另一种方法是步进电机。

image-20230207155956609

ULN 2003,高电压 高电流驱动器,给信号就被驱动。IN 取反输出 OUT。

简谱

image-20230207163112788

首先整个谱大概分为几个区。大字组、小字组、小字1组、小字2组。每个组之间差8度,每相邻的两个键(如黑白)差半音,相邻的两个同色键差一个全音。

几个白键的表示方法就是下面的简谱,差半音的黑键用左上角的#表示升半音,b表示降半音。

演奏两大要素:音高和时值。

img

谱上一个数字是1/4 音符,二分是其两倍,数字加个横线 - 。全音符就是(2 - - -)。这个线叫增时线。

八分是其1/2,数字下加一条线(2).再/2就再加一条,叫减时线。

试着识一个完整的谱:

image-20230207233115087

4/4:以四分音符为一拍,每小节有四拍。

第二节 1 ˙ \dot{1} 1˙ · 上面的点我们知道代表高音,后面的点代表:前一位音符延长1/2长度,即四分音符+1/2的四分音符。也就是3/8哈哈哈。

看第一节,一般连着两个八分音符就把 underline 连起来。但是这种哪怕是一个音,中间也要先断开再重响。比如右上角的3 3

升音和降音在本小节中有效。如第三行的 7 #4 4 7 ,两个4都是升音。

不过如果顶端画了延音线,就是连起来的不用断开。如中间的 77 ^ \widehat{7 7} 77 ,拆开写是为了好读谱。

接下来就是如何把谱转化为单片机代码。左上角 1=c 说明是c调的。d大调会出现黑键,c调只有白键。

image-20230208000727170

音具体是怎么定义的?首先以中音a为基准,高音a是其2倍,低音a是其1/2。

中间每次升音都是等比数列递增的,即*2的1/12次方

使用蜂鸣器

响起来很简单:不断反转 P1^5 口(是不是这个口得看自己的板子型号)。

void main()
{
	u16 i=2000;//决定时值
	while(1){
		while(i--)
		{
			BEEP=!BEEP;
			delay10Us(100);//决定音高
		}
        i=2000;
        BEEP=0;
	}
}

时值还好确认,音高怎么说?

首先我们有上图的音符与频率对照表。我们把频率转化为周期,即1/频率。这里周期单位是us。

image-20230208093509168

然后周期时长转化为机器周期,即记一个数需要的时间。我们看看需要多少机器周期。

1机器周期=12时钟周期,时钟周期=1/单片机晶振。比如对于我的11.0592MHZ 晶振,机器周期=12/11.0592MHZ (单位:us)。

据此把“需要切换的周期时长”转化为“需要切换的周期需要执行几次指令”。即周期/机器周期。如果是12MHZ 晶振这一步相当于没有。

image-20230208094537336

然后电平从低到高,从高到低才是一个周期。所以实际电平反转一次的周期是周期的一半。

image-20230208095158230

我们知道定时器原理是 TH TL 加至65536触发中断。因此重装载值(定时器初值)=65536-取整值。

音符频率周期需要的机器周期数需要的机器周期数/2取整重装载值
12623816.7943517.5572521758.778626175963777
1#2773610.1083327.0758121663.537906166463872
22943401.3613134.6938781567.346939156763969
2#3113215.4342963.3440511481.672026148264054
33303030.3032792.7272731396.363636139664140
43492865.332640.6876791320.34384132064216
4#3702702.7032490.8108111245.405405124564291
53922551.022351.0204081175.510204117664360
5#4152409.6392220.7228921110.361446111064426
64402272.7272094.5454551047.272727104764489
6#4662145.9231977.682403988.841201798964547
74942024.2911865.587045932.793522393364603
15231912.0461762.141491881.070745788164655
1#5541805.0541663.537906831.768953183264704
25871703.5781570.017036785.008517978564751
2#6221607.7171481.672026740.836012974164795
36591517.4511398.482549699.241274769964837
46981432.6651320.34384660.171919866064876
4#7401351.3511245.405405622.702702762364913
57841275.511175.510204587.75510258864948
5#8311203.3691109.025271554.512635455564981
68801136.3641047.272727523.636363652465012
6#9321072.961988.8412017494.420600949465042
79881012.146932.7935223466.396761146665070
11046956.0229881.0707457440.535372844165095
1#1109901.7133831.018936415.50946841665120
21175851.0638784.3404255392.170212839265144
2#1245803.2129740.2409639370.120481937065166
31318758.7253699.2412747349.620637335065186
41397715.8196659.6993558329.849677933065206
4#1480675.6757622.7027027311.351351431165225
51568637.7551587.755102293.87755129465242
5#1661602.047554.846478277.42323927765259
61760568.1818523.6363636261.818181826265274
6#1865536.193494.155496247.07774824765289
71976506.0729466.3967611233.198380623365303

使用方法:TH=重装载值/256,TL=重装载值%256.

音高从低到高逐位响起代码:

#include "reg52.h"
#include "Delay.h"
#include "Timer0.h"
sbit beep=P1^5;

unsigned int beep_table[]={//可以加个0代表不响的0
	63777,63872,63969,64054,64140,64216,64291,64360,64426,64489,64547,64603,
	64655,64704,64751,64795,64837,64876,64913,64948,64981,65012,65042,65070,
	65095,65120,65144,65166,65186,65206,65225,65242,65259,65274,65289,65303	
};

unsigned char beep_select=0;

void main(){																	 
	unsigned char i;
	timer0Init();
	while(1){
		beep_select++;
		delayMs(50);//时值		
	}
}

void timer0Interrupt() interrupt 1
{
    TH0 = beep_table[beep_select]/256; // 因为触发中断时,TH TL 归零,所以记得赋初值!
    TL0 = beep_table[beep_select]%256;
	beep=!beep;
}

编曲:

image-20230208125043337

根据乐谱写一个数组。

unsigned int little_star[]={12, 12, 19, 19,
                            21, 21, 19,    //增时线
                            17, 17, 16, 16,
                            14, 14, 12,
                            19, 19, 17, 17,
                            16, 16, 14,
                            19, 19, 17, 17,
                            16, 16, 14,
                            12, 12, 19, 19,
                            21, 21, 19, 
                            17, 17, 16, 16,
                            14, 14, 12
                           };

遍历数组,得到的音高再去 beep_table 中获取重装载值。

TH0 = beep_table[little_star[beep_select]]/256; // 因为触发中断时,TH TL 归零,所以记得赋初值!
TL0 = beep_table[little_star[beep_select]]%256;

但是播放起来都是连着的,听起来效果并不好。可以每次播完一个音先关闭中断并延时一段时间,再继续播放。

while(1){
		beep_select++;
		delayMs(50);
		TR0=0;
		delayUs(1);
		TR0=1;		
	}

増时线如何处理?中间是不断开一直想的,因此需要几个特定的音符delay时间更长一些。怎么区分哪些音符加长哪些不加呢?

最好还是存储乐谱时搞一个二维数组(逻辑上物理上都可以),既能存储音高,也能存储时值。

unsigned int little_star[]={12, 4,
                            12, 4,
                            19, 4,
                            19, 4,
                            21, 4,
                            21, 4,
                            19, 8,  //增时线
                            17, 4,
                            17, 4,
                            16, 4,
                            16, 4,
                            14, 4,
                            14, 4,
                            12, 8,
                            19, 4,
                            19, 4,
                            17, 4,
                            17, 4,
                            16, 4,
                            16, 4,
                            14, 8,
                            19, 4,
                            19, 4,
                            17, 4,
                            17, 4,
                            16, 4,
                            16, 4,
                            14, 8,
                            12, 4,
                            12, 4,
                            19, 4,
                            19, 4,
                            21, 4,
                            21, 4,
                            19, 8,
                            17, 4,
                            17, 4,
                            16, 4,
                            16, 4,
                            14, 4,
                            14, 4,
                            12, 8,
                            0xFF,4//终止标志防越界
                           };

如果数组大小超限,在魔术棒-Target-Memory Model 中选择第三个。不过这只是治标不治本,因为 RAM 只有512字节所以存不下太长。可以在定义数组时加上关键词 code 来存在 ROM 8K 的闪存中。不过这样的数组是只读的。

当然这样找索引比较麻烦。最好是索引全部重新宏定义。

//音符与索引对应表,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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/331352.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript(四)-全面详解(学习总结---从入门到深化)

👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者 📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 📧如果文章…

JAVA开发(Redis的主从与集群)

现在web项目无处不在使用缓存技术,redis的身影可谓无处不在。但是又有多少项目使用到的是redis的集群?大概很多项目只是用到单机版的redis吧。作为缓存的一块,set ,get数据。用的不亦乐乎。但是对于高可用系统来说,数据…

Tomcat简介

目录 一、Tomcat简介 二、下载安装Tomcat 三、利用Tomcat部署静态页面 一、Tomcat简介 Tomcat是一个HTTP服务器,可以按照HTTP的格式来解析请求来调用用户指定的相关代码然后按照HTTP的格式来构造返回数据。 二、下载安装Tomcat 进入Tomcat官网选择与自己电脑…

电子科技大学人工智能期末复习笔记(二):MDP与强化学习

目录 前言 期望最大搜索(Expectimax Search) ⭐马尔科夫决策(MDP)——offline(超重点) 先来看一个例子 基本概念 政策(Policy) 折扣(Discounting) 如…

Mysql中的事务

1. MyIsam是不支持事务的, InnoDB支持 2.事务的四大特性ACID 原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节,而且事务在执行过程中…

PythonWeb开发基础(四 完)Response使用及wsgify装饰器

课程地址:Python 工程师进阶技术图谱 文章目录🌾 Response使用及wsgify装饰器1、Response的使用2、wsgify装饰器🌾 Response使用及wsgify装饰器 1、Response的使用 前面一节我们知道了,使用webob的Request模块可以很方便地对请求…

若依框架---PageHelper分页(十五)

👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者 📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 &#x1f4…

STM32开发(7)----CubeMX配置串口通讯(轮询方式)

CubeMX配置串口通讯(轮询方式)前言一、串口的介绍二、实验过程1.实验材料2.STM32CubeMX配置PWM3.代码实现重载printf轮询接收4.编译烧录5.硬件连接6.实验结果重载printf结果串口轮询接收结果总结前言 本章介绍使用STM32CubeMX对串口进行配置的方法&…

​力扣解法汇总1797. 设计一个验证系统

目录链接: 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:力扣 描述: 你需要设计一个包含验证码的验证系统。每一次验证中,用户会收到一个…

vue:自定义组件如何使用v-model

问题: 在使用自定义组件时,我们有时候需要使用 v-model 来双向绑定。方法: 在vue中,v-model 的值相当于默认传递了一个名为 value 的 prop 和一个名为 input 的事件(注意,这个value的prop是需要在自定义组件…

《皮格马利翁效应》-期待效应

“ 人生没有白走的路,没有白读的书,你触碰过的那些文字会在不知不觉中帮你认知这个世界 #每天读本书 #关注我每天解读一本书”《皮格马利翁效应》01关于作者朱瑟琳•乔塞尔森,女性心理学家,是国际 公认的精神医学大师欧文•亚隆的…

刚刚,微软推出支持chatGPT的必应

文章目录刚刚,微软推出支持chatGPT的必应什么是新的必应?如何体验页面初体验结语:搜索引擎的新时代刚刚,微软推出支持chatGPT的必应 这款新的必应功能允许用户通过自然语言方式与chatgpt进行交流,以获得快速、准确的信…

华为HCIE学习之openstack基础

文章目录一、Openstack各种文件位置二、Openstack命令操作1.使用帮助三、用命令发放云主机1、创建租户2、创建用户并与租户绑定3、注册镜像4、创建规格5、创建公有网络及其子网(做弹性IP用)6、创建私有网络及其子网7、创建路由并设置网关与端口8、创建安…

C++类与对象(中)

✅<1>主页&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;C &#x1f525;<3>创作者&#xff1a;我的代码爱吃辣 ☂️<4>开发环境&#xff1a;Visual Studio 2022 &#x1f4ac;<5>前言&#xff1a;C类中一共有六个默认成员函…

当ChatGPT遇到网络安全

ChatGPT&#xff1a;是人工智能技术驱动的自然语言处理工具&#xff0c;它能够通过学习和理解人类的语言来进行对话&#xff0c;还能根据聊天的上下文进行互动&#xff0c;真正像人类一样来聊天交流&#xff0c;甚至能完成撰写邮件、视频脚本、文案、翻译、代码等任务。GPT 是 …

活动星投票文艺巡演活动免费投票程序制作网页投票网站

“文艺巡演活动”网络评选投票_线上小程序的投票方式_视频投票的功能_在线投票程序用户在使用微信投票的时候&#xff0c;需要功能齐全&#xff0c;又快捷方便的投票小程序。而“活动星投票”这款软件使用非常的方便&#xff0c;用户可以随时使用手机微信小程序获得线上投票服务…

ConcurrentHashMap底层原理介绍

概述: ConcurrentHashMap相对于HashMap的性能较差一些,但相比于Hashtable而言性能要高很多,因为Hashtable内部的所有方法都是同步方法,加了synchronized锁,所以性能上比较差,但在多线程环境下是具有很强的安全性的ConcurrentHashMap避免了对全局加锁改成了局部加锁操作&#xf…

Go最新版下载 Go1.20版新特性

Go官方正式发布了Go1.20稳定版 该版本依然保持 Go1 兼容性&#xff0c;可以升级到 Go1.20&#xff0c;而不需要做任何代码改动。 可以使用你任何喜欢的方式升级&#xff1a; 比如&#xff1a; go install golang.org/dl/go1.20latest 具体的可以参考官网教程&#xff1a; ht…

简介DNS协议、ICMP协议、NAT技术

文章目录一、DNS 协议1.背景2.域名二、ICMP 协议1.功能2.格式3. ping 命令4. traceroute 命令三、NAT 技术1.基本理解2. NAT 转换过程3. NAPT4. NAT 技术的缺陷5. NAT 和代理服务器一、DNS 协议 DNS&#xff08;Domain Name System&#xff0c;域名系统&#xff09;&#xff0…

【头歌】串的运算及应用

串的运算及应用第1关&#xff1a;求子串任务描述本关任务&#xff1a;实现字符串的求子串操作。相关知识为了完成本关任务&#xff0c;你需要理解&#xff1a;1. 求子串操作&#xff0c;2.字符串的顺序存储。求子串操作从一个字符串S的某个位置开始截取若干个连续字符&#xff…