STC89C52单片机学习——第25节: [11-1]蜂鸣器

news2025/3/20 2:35:03

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难,但我还是想去做!

本文写于:2025.03.18

51单片机学习——第25节: [11-1]蜂鸣器

  • 前言
  • 开发板说明
  • 引用
  • 解答和科普
  • 一、蜂鸣器原理和驱动
  • 二、乐理部分
  • 三、按键提示音设置
  • 问题
  • 总结
  • 鸡汤时刻

前言

   本次笔记是用来记录我的学习过程,同时把我需要的困难和思考记下来,有助于我的学习,同时也作为一种习惯,可以督促我学习,是一个激励自己的过程,让我们开始51单片机的学习之路。
   欢迎大家给我提意见,能给我的嵌入式之旅提供方向和路线,现在作为小白,我就先学习51单片机了,就跟着B站上的江协科技开始学习了.
   在这里会记录下江协科技51单片机开发板的配套视频教程所作的实验和学习笔记内容,因为我之前有一个开发板,我大概率会用我的板子模仿着来做.让我们一起加油!
   另外为了增强我的学习效果:每次笔记把我不知道或者问题在后面提出来,再下一篇开头作为解答!

开发板说明

   本人采用的是慧净的开发板,因为这个板子是我N年前就买的板子,索性就拿来用了。不再另外购买视频中的普中开发板了。
   原理图如下
在这里插入图片描述
视频中的都用这个开发板来实现,如果有资源就利用起来。
仔细看了看:开发板的晶振为:11.0592Mhz;12Mhz晶振是用来给CH340G芯片外置晶振;

下图是实物图
在这里插入图片描述

引用

51单片机入门教程-2020版 程序全程纯手打 从零开始入门
还参考了下图中的书籍:
手把手教你学51单片机(C语言版)
在这里插入图片描述
STC89C52手册
在这里插入图片描述

解答和科普

一、蜂鸣器原理和驱动

在这里插入图片描述
可以看到我们使用的是无源蜂鸣器,我们控制震荡脉冲,通过调整提供振荡脉冲的频率,可以发出不同频率的声音。
在这里插入图片描述
我们要编这个音乐,首先需要去找到它的谱子,我们有了这个谱子呢,至少得知道这个谱子它在我们的钢铁键盘上,它是怎么样去按的,然后知道这个谱子对应钢琴键,它怎么按之后按多长时间,然后呢我们利用单片机去把每个键它背后的音给模拟出来。根据这个频率对照表,把每个按键它的音模拟出来,然后我们编写这个曲目,由谱曲到我们的蜂鸣器播放。这整个过程才能实现。那么我们单片机的任务呢就是模拟这个钢琴键盘,我们按下它按多长时间。
然后把它的频率发出来就好了,这就是我们代码的任务。那么还有一个任务呢就是,我们需要根据这个谱子,看到这个谱子之后,知道它是怎么对应的这个钢琴键盘上的。然后我们怎么去按。
在这里插入图片描述
我们首先来看一下这个蜂鸣器的介绍,第一句话是蜂鸣器是一种将电信号转化为声音信号的器件,那我知道这个分频器它通电会响,那么怎么响呢?
我们来看一下他想的用途呢是用来产生我们设备的按键音,报警音等提示信号。它可以分为有源蜂鸣器和无源蜂鸣器,有源蜂鸣器频率是固定的,不能随之改变。内部自带震荡源,那么它使用起来就是很简单,将正负极接上直流电压即可持续发生,频率固定。我们给他的是直流电,但直流电本身不能发声,它内部有电路产生的震荡,所以它发声,那因此呢它的频率也是固定的。因为它内部的震荡源它已经固定好了,它的频率就只有只有这么大。
三极管驱动:

在这里插入图片描述
在这里插入图片描述
低电平导通,高电平断开。之前已经分析过三极管(PNP)的驱动原理。
在这里如果P1^3输入低电平那么基极和发射极直接有电压差,就会控制发射极和集电极导通,因此就是蜂鸣器接上了电源,此时发声。
芯片驱动
在这里插入图片描述
控制P15的1或0,就能控制蜂鸣器是是否有电流
无源蜂鸣器不能一直通电,很容易烧毁,IO口上电默认为高电平,BZ默认为0;始终通电流。
在这里插入图片描述
在这里插入图片描述
给1取反为0,有驱动,给0取反为1,好像不行;
在这里插入图片描述
我们蜂鸣器原理和驱动部分就已经讲完了,接下来我们就呃给大家讲一下这个这个乐理部分。

二、乐理部分

在这里插入图片描述

首先我们来认识一下这个钢琴键盘,这钢琴键盘呢上面就是钢琴键盘。这个呢是五线谱,然后下面是简谱。然后呢钢键盘嗯它可以分组,小写字母也是一组,它命名方式一组有七个白键,五个黑键组成的。然后这个呢就叫做小字组。然后左边这个叫做大字组,如果左边还有人就大字一组,右边这个叫做小字二组,小字二组右边还有就是小字三组,在这里这里首先分为几组,这几组呢每一个都是单独的,就是常见的do re mi fa so la xi。然后呢每一个组的相同的音,比如说这个C1和C2相差8度.相邻的按键是半音。
然后呢我们来讲一下如何根据这个简谱去对应的这个键盘啊,就是再升高8度的话,那么这个一上面要加个点,然后呢如果降低8度呢,就是在下面在这个音的,在这个数字下面加点,降低两个8度,下面加两个点。那么升高两个8度呢,就上面加两个点。我们就可以把所有音高给表示出来。所有的白键音标就可以表示出来,然后如果我们想表示黑键的音高,我们就需要用到升音符号和降音符号这两个符号进行。
在这里插入图片描述
-表示时长延长, #表示升半个音,就是黑键,b为降音
有了这个数字上面加点,下面加点,然后再配合升降符号的话,就可以表示所有钢琴上的按键了。我们就可以把钢琴键盘所有的音高的表示出来了,然后呢有了音高之后,我们按钢琴这个键盘的时候,主要有音高和按的时长,主要有这两个因素。我们这写程序也按照这两个因素来。一个是音高,一个是时间。有了这两个部分,我们就能够演奏出这个音乐了。

在这里插入图片描述
在这里插入图片描述
4分音符 500us ,2分1s,8分音符250ms 16音符为125ms,5表示4分音符,5-表示2分音符;下面加一个横线是8分音符,加两条线是16分音符。他们时间都是二倍的关系,利用它们组合起来,我们就可以组合各种时长。在我们下面呢一般来说都是以四分音符为基准。
4/4是拍号,四分音符为一拍,每小节4拍;
1的上面加点表示音高,右边有点表示附点,延长原来的1/2,500+250,250,500,500;
——为连音,时长加起来;

我们直接写个数字,它就是我们的四分音符,如果想表示二分音符的话,那么这个数字后面再加一个横线,它就可以表示二分音符。如果是全音符的话,在后面加两条横线,我加三条横线,一共四倍的关系,这就是全音符。
然后如果想表示分开,比如说四分音符分成八分音符,那么就在下面加线,比这个六我下面加一个线,它就是四分音符时值的一半。如果下面加两条线呢,就是八分音符。在右边加线就增长,下面加线就缩短,就可以表示时长然后表示完时长之后,右边这个4/4就是我们的拍号从下往上读,它叫做以四分音符为一拍,每小节有四拍。
我们需要以一个音符时长为基准,就以四分音符为基准,就是写一个数字,画一条竖线就代表小节,一小节有4拍,这就是以四分音符为一拍,每小节四拍的意思。
==右边加点就是附点这个音符加上原来的一半,比如说这个四分音符是500ms,然后加个点它加原来500ms的一半,就是加上250ms,就是750ms。
在这里插入图片描述
弧度是延音线,按下去不放的, 为了识谱方便.
在这里插入图片描述
我们就是根据这个频率值,根据频率值去控制我们的定时器,产生一个相应频率的计时,有了频率就有了计时频率,计时的周期我们有了,然后去控制我们的中断,再去控制IO口的翻转,就可以控制我们的频率.
在这里插入图片描述
频率关系是:首先需要一个基准的频率,就是低音6,小子组的a为基准频率440,下一个a是880,左边的a是220,中间是以等比数列,也叫十二平分律。440*2^(1/12)是下一个频率。

利用定时器中断产生频率,依靠我们TH0、TL0,产生周期,周期等于1/f,然后是IO口,一个周期IO翻转两次,所以反正一次用的时间是半个周期,
在这里插入图片描述
12MHZ对应的重装载值

在这里插入图片描述
11.05926HZ对应的重装载值
在这里插入图片描述
其中的转化过程,因为时钟频率不同,机器周期不同,重装载值也不同。

三、按键提示音设置

3.1 main.c

#include <REGX52.H>
#include <INTRINS.H>
#include "Delay.h"
#include "Key.h"
#include "Timer0.h"
#include "LCD1602.h" 
#include "Init.h"
#include "Nixie.h"


sbit  Buzzer = P2^3;
unsigned char KeyNum;
unsigned int i;
void main()
{

	DianZhengGuan();			//关闭点阵
	while(1)
	{
		KeyNum=Key();
		if(KeyNum)
		{
			for(i=0;i<500;i++)	//2ms一个周期,500HZ 的频率响500ms
			{						//f=1/T=1/0.002=500hz
			Buzzer=!Buzzer;
			Delay(1);
			}
		Nixie(1,KeyNum);
		}
		
	}
}

3.2 Key.c

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


/**
  * @brief    独立按键获取键码值
  * @param  	无
  * @retval 	按下的键码值,范围1-8,没有独立按键按下是为0
  */
unsigned char Key()
{
	unsigned char KeyNumber=0;
	
	if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=1;}
	if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=2;}
	if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
	if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
	if(P3_4==0){Delay(20);while(P3_4==0);Delay(20);KeyNumber=5;}
	if(P3_5==0){Delay(20);while(P3_5==0);Delay(20);KeyNumber=6;}
	if(P3_6==0){Delay(20);while(P3_6==0);Delay(20);KeyNumber=7;}
	if(P3_7==0){Delay(20);while(P3_7==0);Delay(20);KeyNumber=8;}
	
	return KeyNumber;
	
}
#ifndef		__KEY_H
#define 	__KEY_H

unsigned char Key();

#endif

3、Nixie.c

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

sbit  	wei= P2^1;
sbit	duan=P2^0;
unsigned char NixieDuanTable[]= {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00};
unsigned char NixieWeiTable[]={0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};


void Nixie(unsigned char WeiNum, DuanNum)	//动态显示 
{

	duan=1;
	P0=NixieDuanTable[DuanNum];
	duan=0;
	
	wei=1;
	P0=NixieWeiTable[WeiNum];
	wei=0;
	Delay(1);                                                                                                                                                                                                                                      
}

#ifndef		__NIXIE_H
#define 	 __NIXIE_H

void Nixie(unsigned char WeiNum, DuanNum);

#endif

实验现象:

按键提示音(蜂鸣器)

对蜂鸣器设置私有化延迟函数
1、main.c

#include <REGX52.H>
#include <INTRINS.H>
#include "Delay.h"
#include "Key.h"
#include "Timer0.h"
#include "LCD1602.h" 
#include "Init.h"
#include "Nixie.h"
#include "Buzzer.h"


unsigned char KeyNum;

void main()
{
	
	


	DianZhengGuan();			//关闭点阵
	while(1)
	{
		KeyNum=Key();
		if(KeyNum)
		{
		Buzzer_Time(100);			//1Khz响100ms
		Nixie(1,KeyNum);
		}
		
		
	}
}

2.Buzzer.c

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

sbit  Buzzer = P2^3;		//蜂鸣器端口

/**
  * @brief    蜂鸣器私有延迟函数  //@11.0592MHz  500us
  * @param  	无
  * @retval 	无
  */
void Buzzer_Delay500us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	i = 227;
	while (--i);
}


/**
  * @brief      蜂鸣器鸣响 
  * @param  	xms :发声的时间
  * @retval 	无
  */
void Buzzer_Time(unsigned int xms)
{
	unsigned int i;
	for(i=0;i<xms*2;i++)	//1ms一个周期,1000HZ 的频率响xms
	{
	Buzzer=!Buzzer;
	Buzzer_Delay500us();
	}
}

#ifndef		__BUZZER_H
#define 	 __BUZZER_H

void Buzzer_Time(unsigned int ms);

#endif

问题

1、就是还是对乐理部分有点乱。

总结

本节课主要学了蜂鸣器的原理和驱动,学习了音乐相关的乐理知识。让我们看着简谱去弹钢琴,主要是音高和音长,这两点,其中有#升音、头上加点,b降音底部加点;下面加——,一半音,右边——延长,还有附点延长一半,还有弧度延音键为了看拍子数,这样基本解决了音高和音长两个关键。
接下来为了让单片机发出对应的音高,单片机不能控制频率,通过频率得到计数频率,所以通过控制周期,得到计数频率也就得到了技术周期,半个周期触发中断,进行一次IO变换,一个周期IO变换两次==(高电平半个周期,低电平半个周期)==,那么我们通过频率最后到达计算重装值。其中还进行了11.0592Mhz的转换。就剩下如何实现了。

鸡汤时刻

在这里插入图片描述

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

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

相关文章

音视频入门基础:RTP专题(19)——FFmpeg源码中,获取RTP的音频信息的实现(下)

本文接着《音视频入门基础&#xff1a;RTP专题&#xff08;18&#xff09;——FFmpeg源码中&#xff0c;获取RTP的音频信息的实现&#xff08;上&#xff09;》&#xff0c;继续讲解FFmpeg获取SDP描述的RTP流的音频信息到底是从哪个地方获取的。本文的一级标题从“四”开始。 四…

卷积神经网络 - 卷积的变种、数学性质

本文我们来学习卷积的变种和相关的数学性质&#xff0c;为后面学习卷积神经网络做准备&#xff0c;有些概念可能不好理解&#xff0c;可以先了解其概念&#xff0c;然后慢慢理解、逐步深入。 在卷积的标准定义基础上&#xff0c;还可以引入卷积核的滑动步长和零填充来增加卷积…

BLIP论文阅读

目录 现存的视觉语言预训练存在两个不足&#xff1a; 任务领域 数据集领域 相关研究 知识蒸馏 Method 单模态编码器&#xff1a; 基于图像的文本编码器&#xff1a; 基于图像的文本解码器&#xff1a; 三重目标优化 图像文本对比损失&#xff1a;让匹配的图像文本更加…

[动手学习深度学习]26. 网络中的网络 NiN

前面的LeNet、AlexNet、VGG在设计上的共同之处在于&#xff1a;先以卷积层构成的模块充分抽取空间特征&#xff0c;再以全连接层构成的模块来输出分类结果 其中AlexNet和VGG对LeNet的改进主要在于如何对这两个模块价款&#xff08;增加通道数&#xff09;和加深 这一节的NiN提出…

碰一碰发视频saas系统技术源头一站式开发文档

碰一碰发视频系统技术源头一站式开发文档 一、引言 在数字化信息传播高速发展的当下&#xff0c;如何让视频分享更便捷、高效&#xff0c;成为商家和开发者们关注的焦点。“碰一碰发视频”系统以其独特的交互方式和强大的功能优势&#xff0c;为视频分享领域带来了革命性变革。…

Linux目录理解

前言 最近在复习linux&#xff0c;发现有些目录总是忘记内容&#xff0c;发现有些还是得从原义和实际例子去理解会记忆深刻些。以下是个人的一些理解 Linux目录 常见的Linux下的目录如下&#xff1a; 1. 根目录 / (Root Directory) 英文含义&#xff1a;/ 是文件系统的根…

可视化图解算法:链表中倒数(最后)k个结点

1. 题目 描述 输入一个长度为 n 的链表&#xff0c;设链表中的元素的值为ai &#xff0c;返回该链表中倒数第k个节点。 如果该链表长度小于k&#xff0c;请返回一个长度为 0 的链表。 数据范围&#xff1a;0≤n≤105&#xff0c;0 ≤ai≤109&#xff0c;0 ≤k≤109 要求&am…

Swift 并发中的任务让步(Yielding)和防抖(Debouncing)

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

HW基本的sql流量分析和wireshark 的基本使用

前言 HW初级的主要任务就是看监控&#xff08;流量&#xff09; 这个时候就需要我们 了解各种漏洞流量数据包的信息 还有就是我们守护的是内网环境 所以很多的攻击都是 sql注入 和 webshell上传 &#xff08;我们不管对面是怎么拿到网站的最高权限的 我们是需要指出它是…

docker-compose install nginx(解决fastgpt跨区域)

CORS前言 CORS(Cross-Origin Resource Sharing,跨源资源共享)是一种安全措施,它允许或拒绝来自不同源(协议、域名、端口任一不同即为不同源)的网页访问另一源中的资源。它的主要作用如下: 同源策略限制:Web 浏览器的同源策略限制了从一个源加载的文档或脚本如何与另一…

设计模式(创建型)-单例模式

摘要 在软件开发的世界里&#xff0c;设计模式是开发者们智慧的结晶&#xff0c;它们为解决常见问题提供了经过验证的通用方案。单例模式作为一种基础且常用的设计模式&#xff0c;在许多场景中发挥着关键作用。本文将深入探讨单例模式的定义、实现方式、应用场景以及可…

鸿蒙NEXT开发问题大全(不断更新中.....)

目录 问题1&#xff1a;鸿蒙NEXT获取华为手机的udid ​问题2&#xff1a;[Fail]ExecuteCommand need connect-key? 问题3&#xff1a;测试时如何安装app包 问题1&#xff1a;鸿蒙NEXT开发获取华为手机的udid hdc -t "设备的序列号" shell bm get --udid 问题2&…

TI的Doppler-Azimuth架构(TI文档)

TI在AWR2944平台上推出新的算法架构&#xff0c;原先的处理方式是做完二维FFT后在RD图上做CFAR检测&#xff0c;然后提取各个通道数据做测角。 Doppler-Azimuth架构则是做完二维FFT后&#xff0c;再做角度维FFT&#xff0c;生成Doppler-Azimuth频谱图&#xff0c;然后在该频谱图…

「自动驾驶的数学交响曲:线性代数、微积分与优化理论的深度共舞」—— 解析人工智能背后的高阶数学工具链

引言 自动驾驶系统是数学工具链的集大成者。从传感器数据的多维空间映射到控制指令的生成,每一步都隐藏着线性代数、微积分、概率论和优化理论的精妙配合。本文将构建一个数学模型完整的自动驾驶案例,结合Python代码实现,揭示以下核心数学工具: 线性代数:张量运算与特征空…

调试 Rust + WebAssembly 版康威生命游戏

1. 启用 Panic 日志 1.1 让 Panic 信息显示在浏览器控制台 如果 Rust 代码发生 panic!()&#xff0c;默认情况下不会在浏览器开发者工具中显示详细的错误信息。这使得排查问题变得困难。 我们可以使用 console_error_panic_hook 这个 Rust crate&#xff0c;将 Panic 信息打…

VSCode通过SSH远程登录Windows服务器

系列 1.1 VSCode通过SSH远程登录Windows服务器 1.2 VSCode通过SSH免密远程登录Windows服务器 文章目录 系列1 准备工作2 远程服务器配置2.1 安装SSH服务器2.2 端口 3 本地电脑配置3.1 安装【Remote - SSH】。3.2 登录 1 准备工作 本地电脑Windows 11&#xff0c;已安装VS Cod…

qt下载和安装教程国内源下载地址

qt不断在更新中&#xff0c;目前qt6日渐成熟&#xff0c;先前我们到官方下载或者国内镜像直接可以下载到exe文件安装&#xff0c;但是最近几年qt官方似乎在逐渐关闭旧版本下载通道&#xff0c;列为不推荐下载。但是qt5以其广泛使用和稳定性&#xff0c;以及积累大量代码使得qt5…

mysql 到 doris 挪移数据

工具datax..... 下载地址&#xff1a;http://datax-opensource.oss-cn-hangzhou.aliyuncs.com/datax.tar.gz 下载以后解压&#xff1a;tar -xvzf datax.tar.gz 然后&#xff0c;理论上就可以直接使用了。但是&#xff0c;datax本身是python2写的&#xff0c;如果需要python3…

ubuntu系统下添加pycharm到快捷启动栏方法

一、背景 之前在ubuntu系统下使用pycharm时&#xff0c;总是要进入/home/dlut/pycharm-community-2022.1/bin文件夹下&#xff0c;然后终端执行命令下面的命令才可修改代码&#xff1a; ./pycharm.sh为了以后方便&#xff0c;这里给出添加pycharm到快捷启动栏的方法 二、添加…

开源:LMDB 操作工具:lmcmd

目录 什么是 LMDB为什么编写 lmcmd安装方法如何使用 连接数据库命令列表 小结 1. 什么是 LMDB LMDB&#xff08;Lightning Memory-Mapped Database&#xff09;是一种高效的键值存储数据库&#xff0c;基于内存映射&#xff08;memory-mapping&#xff09;技术&#xff0c;提供…