单片机第一季:零基础8——蜂鸣器

蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。

蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。

想要压电式蜂鸣器发声,需提供一定频率的脉冲信号;想要电磁式蜂鸣器发声,只需提供电源即可。

我们开发板上使用的蜂鸣器是无源蜂鸣器,属于压电式蜂鸣器类型。这里说的有源和无源,并不是指电源的意思,而是指蜂鸣器内部是否含有振荡电路,有源蜂鸣器内部自带振荡电路,只需提供电源即可发声,而无源蜂鸣器则需提供一定频率的脉冲信号才能发声,频率大小通常在1.5-5KHz 之间。 

对于无源蜂鸣器,如果改变频率就可以调节蜂鸣器音调,产生各种不同音色、音调的声音。如果改变输出电平的高低电平占空比,则可以改变蜂鸣器的声音大小。

对于有源蜂鸣器,通常内部已经固定了频率,对于调节频率或占空比可能改变不了蜂鸣器的音调和音量,当然也有的有源蜂鸣器可以实现和无源蜂鸣器一样的效果。 

在前面章节中我们已经对51 单片机的GPIO 做了简单介绍,并且还使用了其中IO 口直接控制开发板上的LED。对于本章要实现蜂鸣器的控制,我们能否直接使用单片机的IO 口驱动呢?答案是否定的,因为51 单片机IO 口的驱动能力较弱(即使外接上拉电阻),而蜂鸣器驱动需要约30mA,所以非常困难,即使可以驱动,那对于整个芯片的其它IO 剩下驱动能力就更加弱甚至无法工作。所以我们不会直接使用IO 口驱动蜂鸣器,而是通过三极管把电流放大后再驱动蜂鸣器,这样51 单片机的IO 口只需要提供不到1mA 的电流就可控制蜂鸣器。所以我们也经常说到51 单片机是用来做控制的,而不是驱动。 

从图中可以看出,蜂鸣器模块独立,J7 端子可接任意IO 控制,因此可直接连接到51 单片机的管脚上。图中使用三极管进行电流放大,从而驱动蜂鸣器,当管脚输出高电平,三极管截止,蜂鸣器不得电;当管脚输出低电平,三极管导通,蜂鸣器得电。

开发板上使用的是无源蜂鸣器,它需要一定频率的脉冲(高低电平)才会发声,因此需要让单片机管脚以一定频率不断输出高低电平信号才能控制蜂鸣器发出声音。 

 两种控制蜂鸣器的程序代码:

第一种:

/********************************************************************
******************
实验名称:蜂鸣器实验
接线说明:
实验现象:下载程序后蜂鸣器发出声音,一段时间后关闭
注意事项:
*********************************************************************
******************/
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
sbit BEEP=P0^0; //将P0.0 管脚定义为BEEP
/********************************************************************
***********
* 函数名: delay_10us
* 函数功能: 延时函数,ten_us=1 时,大约延时10us
* 输入: ten_us
* 输出: 无
*********************************************************************
**********/
void delay_10us(u16 ten_us)
{
	while(ten_us--);
}

void delay1ms(void)   //误差 0us
{
    unsigned char a,b;
    for(b=199;b>0;b--)
        for(a=1;a>0;a--);
}

/********************************************************************
***********
* 函数名: main
* 函数功能: 主函数
* 输入: 无
* 输出: 无
*********************************************************************
**********/
void main()
{
	u16 i=2000;
	while(1)
	{
		while(i--)//循环2000 次
		{
			BEEP=!BEEP;//产生一定频率的脉冲信号
			delay1ms();
		}
		i=0;//清零
		BEEP=0;//关闭蜂鸣器
	}
}

第二种:使用定时中断的方法

#include <reg51.h>

sbit buzzer =P0^0;

void buzzer_isr() interrupt 1 using 1	 //定时器T0中断执行程序
{
	TL0 = 0x17;                          //计数器重新赋值
	TH0 = 0xfc;
	buzzer = !buzzer;

}

void main()
{
	TMOD = 0x01;	 //工作模式1,16位定时/计数器
	TL0 = 0x17;		 //定时时间1ms
	TH0 = 0xfc;
	TR0 = 1;
	ET0 = 1;
	EA = 1;

	while(1);

}

可以让蜂鸣器唱歌的程序:

 

/************************************************************************  
[文件名]  C51音乐程序(八月桂花)  
[功能]    通过单片机演奏音乐  
  
/**********************************************************************/   
#include <REG51.H>    
//#include <INTRINS.H>    
//本例采用89C52, 晶振为11.0592MHZ    
//关于如何编制音乐代码, 其实十分简单,各位可以看以下代码.    
//频率常数即音乐术语中的音调,而节拍常数即音乐术语中的多少拍;    
//所以拿出谱子, 试探编吧!    

sbit Beep =  P0^0 ; 			// 要根据实际的接线来修改
   
unsigned char n = 0;  //n为节拍常数变量    
unsigned char code music_tab[] = 
{   
	0x18, 0x30, 0x1C , 0x10, //格式为: 频率常数, 节拍常数, 频率常数, 节拍常数,    
	0x20, 0x40, 0x1C , 0x10,   
	0x18, 0x10, 0x20 , 0x10,   
	0x1C, 0x10, 0x18 , 0x40,   
	0x1C, 0x20, 0x20 , 0x20,   
	0x1C, 0x20, 0x18 , 0x20,   
	0x20, 0x80, 0xFF , 0x20,   
	0x30, 0x1C, 0x10 , 0x18,   
	0x20, 0x15, 0x20 , 0x1C,   
	0x20, 0x20, 0x20 , 0x26,   
	0x40, 0x20, 0x20 , 0x2B,   
	0x20, 0x26, 0x20 , 0x20,   
	0x20, 0x30, 0x80 , 0xFF,   
	0x20, 0x20, 0x1C , 0x10,   
	0x18, 0x10, 0x20 , 0x20,   
	0x26, 0x20, 0x2B , 0x20,   
	0x30, 0x20, 0x2B , 0x40,   
	0x20, 0x20, 0x1C , 0x10,   
	0x18, 0x10, 0x20 , 0x20,   
	0x26, 0x20, 0x2B , 0x20,   
	0x30, 0x20, 0x2B , 0x40,   
	0x20, 0x30, 0x1C , 0x10,   
	0x18, 0x20, 0x15 , 0x20,   
	0x1C, 0x20, 0x20 , 0x20,   
	0x26, 0x40, 0x20 , 0x20,   
	0x2B, 0x20, 0x26 , 0x20,   
	0x20, 0x20, 0x30 , 0x80,   
	0x20, 0x30, 0x1C , 0x10,   
	0x20, 0x10, 0x1C , 0x10,   
	0x20, 0x20, 0x26 , 0x20,   
	0x2B, 0x20, 0x30 , 0x20,   
	0x2B, 0x40, 0x20 , 0x15,   
	0x1F, 0x05, 0x20 , 0x10,   
	0x1C, 0x10, 0x20 , 0x20,   
	0x26, 0x20, 0x2B , 0x20,   
	0x30, 0x20, 0x2B , 0x40,   
	0x20, 0x30, 0x1C , 0x10,   
	0x18, 0x20, 0x15 , 0x20,   
	0x1C, 0x20, 0x20 , 0x20,   
	0x26, 0x40, 0x20 , 0x20,   
	0x2B, 0x20, 0x26 , 0x20,   
	0x20, 0x20, 0x30 , 0x30,   
	0x20, 0x30, 0x1C , 0x10,   
	0x18, 0x40, 0x1C , 0x20,   
	0x20, 0x20, 0x26 , 0x40,   
	0x13, 0x60, 0x18 , 0x20,   
	0x15, 0x40, 0x13 , 0x40,   
	0x18, 0x80, 0x00   
};   

 // T0定时控制的是音乐的节拍(某一个音节持续的时间)而不管音调(频率)
 // 音调是直接使用delay做出来的。
void int0()  interrupt 1   //采用中断0 控制节拍    
{  
	TH0 = 0xd8;   
   	TL0 = 0xef;   
   	n--;   
}   
   
void delay (unsigned char m)   //控制频率延时    
{   
 	unsigned i = 3 * m;   
 	while (--i);   
}   
   
void delayms(unsigned char a)  //豪秒延时子程序    
{   
  	while (--a);                  //采用while(--a) 不要采用while(a--); 各位可编译一下看看汇编结果就知道了!    
}   
   
void main()   
{ 
	unsigned char p, m;   // m为频率常数变量    
  	unsigned char i = 0;   

  	TMOD &= 0x0f;   
  	TMOD |= 0x01;  		// timer0 工作在模式1,16位定时器下 
  	TH0 = 0xd8;
	TL0 = 0xef;   		// 这个TH和TL的值合起来定了1个10ms左右的一个时间
  	IE = 0x82;   
play:   
   	while (1)   
    {   
a: 		p = music_tab[i];   
       	if (p == 0x00)   		// 一遍播放完了,延时1s后自动开始下一遍    
		{ 
			i=0, delayms(1000); 
			goto play;
		}     //如果碰到结束符,延时1秒,回到开始再来一遍    
       	else if (p == 0xff)  
		{ 
			i = i + 1;
			delayms(100), TR0 = 0; 
			goto a;
		}  //若碰到休止符,延时100ms,继续取下一音符    
        else         
		{
			m = music_tab[i++], n = music_tab[i++];
		}  // m取频率常数 和 n取节拍常数    
		TR0 = 1;                              //开定时器1    
		while (n != 0)
		{ 
			Beep = ~Beep;
			delay(m);        	//等待节拍完成, 通过P1口输出音频(可多声道哦!)    
       	}
		TR0 = 0;                         	//关定时器1    
    }   
}
  

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

spring AOP中pointcut表达式详解

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是「奇点」&#xff0c;江湖人称 singularity。刚工作几年&#xff0c;想和大家一同进步&#x1f91d;&#x1f91d; 一位上进心十足的【Java ToB端大厂…

从零开始理解Linux中断架构(19)--中断线程化irq_thread

前面一节讲到的中断流处理流程是在hard_irq 流程上&#xff0c;工作在中断堆栈上。还有一种情况是使用中断线程的情形。request_threaded_irq参数中有两个处理函数handler,thread_fn是有区别的。handler主中断处理例程&#xff0c;运行hard_irq 流程上。而如果驱动程序填写thre…

Java程序员需要掌握的前端知识(一)

对于前端知识&#xff0c;需要进一步巩固和加强&#xff0c;进入企业之后&#xff0c;要具备一定的接口调试&#xff0c;参数接收的能力&#xff0c;以及单体页面的开发&#xff0c;这里我学习一下前端知识巩固一下自身的技术栈和水平。本次笔记是跟学黑马的同名课程&#xff0…

Bash 有效电话号码

193 有效电话号码 给定一个包含电话号码列表&#xff08;一行一个电话号码&#xff09;的文本文件 file.txt&#xff0c;写一个单行 bash 脚本输出所有有效的电话号码。 你可以假设一个有效的电话号码必须满足以下两种格式&#xff1a; (xxx) xxx-xxxx 或 xxx-xxx-xxxx。&…

通识强化学习,初步了解强化学习的运行规则和估值方法

1.强化学习的发展及应用现状 1.1.强化学习的由来 目前&#xff0c;大家认为强化学习&#xff08;Reinforcement Learning, RL&#xff09;的来源与两个领域密切相关&#xff1a;即心理学的动物试错学习和最优控制的优化理论。 这里都是有相应的共性的&#xff0c;在environme…

HCIP第七天

题目 拓扑图 1.所有路由器各自创建一个环回接口&#xff0c;合理规划IP地址 测试 2. R1-R2-R3-R4-R6之间使用OSPF协议&#xff0c;R4-R5-R6之间使用RIP协议 3. R1环回重发布方式引入OSPF网络 4. R4/R6上进行双点双向重发布 将OSPF中的环回接口改成broadcast 因为华为默认环回接…

阿里云AliYun物联网平台使用-客户端API获取设备传感数据

一、前言 上一篇文章中&#xff0c;已经实现了虚拟数据上云&#xff0c;本文我们将进行上位机客户端的开发&#xff0c;即通过调用阿里云IOT物联网云平台的SDK&#xff0c;开发能获取传感器的遥感数据。 二、云平台操作 调用API需要用户的AccessKey Secret&#xff0c;这意味着…

KaiwuDB CTO 魏可伟:多模架构 —“化繁为简”加速器

以下为浪潮 KaiwuDB CTO 魏可伟受邀于7月4日在京举行的可信数据库发展大会发表演讲的实录&#xff0c;欢迎大家点赞、收藏、关注&#xff01; 打造多模引擎&#xff0c;AIoT数据库探索之路 01 何为“繁”&#xff1f; 工业 4.0 时代&#xff0c; 物联网产业驱动数据要素市场不…

国产芯片——单片机32位mcu的应用

随着物联网与人工智能和智能制造的发展&#xff0c;单片机作为嵌入式系统的核心控制器&#xff0c;在各类行业应用中占据重要位置。其中32位MCU在芯片设计、制造工艺、封装技术上等取得显著突破&#xff0c;以高性能的技术条件被广泛应用在智能物联等行业的方案开发中。今天我们…

windows安装mysql8.0.23版本成功示例-免安装

windows安装mysql8.0.23版本成功示例 一.通过mysql-installer-*.msi安装包的方式1.安装准备1.1 官网下载地址1.2 选择合适的版本点击下载 2.安装mysql 二.通过mysql-8.0.23-winx64.zip压缩包免安装方式1.安装准备1.1 下载官网压缩包1.2 解压后配置文件my.ini信息1.3 配置my.ini…

java ajax

1.ajax定义:异步刷新技术 2.ajax语法 3.ajax实战 在不需要点击刷新按钮时达到局部刷新显示&#xff0c;如下图所示 步骤一&#xff1a;创建工程/包/js 步骤二&#xff1a;数据库/表创建 步骤三&#xff1a;实体类 步骤四&#xff1a;UserDao package cn.kgc.dao;import cn…

Linux下JDK版本与安装版本不一致问题

目录 一. &#x1f981; 前言二. &#x1f981; 操作流程三. &#x1f981; 总结四. &#x1f981; Happy Ending 一. &#x1f981; 前言 最近重新安装了centos7.9,针对以前遇到的Java版本不一致的情况, 提出了另一种方法,该方法简单易行,容易理解。 二. &#x1f981; 操作…

银行安全用电监管平台可行性研究及解决方案

2017年4月26日&#xff0c;国务院安全生产委员会印发《国务院安全生产委员会关于开展电气火灾综合治理工作的通知》&#xff08;安委〔2017〕4号&#xff09;&#xff0c;强调用三年时间综合治理电气火灾工作&#xff0c;提高社会单位发现和处置消防电气安全隐患能力&#xff0…

vue2 element-ui el-cascader地址省市区分开单独写

使用 npm 或 yarn 安装 element-china-area-data 包&#xff1a; npm install element-china-area-data 在你的代码中导入 element-china-area-data import { regionData } from element-china-area-data let that; 完整代码 <template><div><el-form ref&quo…

【http-server】http-server的安装、前端使用http-server启动本地dist文件服务:

文章目录 一、http-server 简介:二、安装node.js:[https://nodejs.org/en](https://nodejs.org/en)三、安装http-server:[https://www.npmjs.com/package/http-server](https://www.npmjs.com/package/http-server)四、开启服务&#xff1a;五、http-server参数&#xff1a;【1…

Redis 优惠卷秒杀(二) 异步秒杀、基于Stream的消息队列处理

目录 基于Stream的消息队列 Redis优化秒杀 登录头 改进秒杀业务&#xff0c;调高并发性能 Redis消息队列实现异步秒杀 ​编辑基于List结构模拟消息队列 基于PuSub的消息队列 ​编辑 基于Stream的消息队列 Redis消息队列 基于Stream的消息队列 Redis优化秒杀 登录头 改…

LeetCode 142.环形链表II

142. 环形链表 II - 力扣&#xff08;LeetCode&#xff09; /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/ class Solution { public:ListNode *detectCycle(ListNode …

【微信小程序创作之路】- 小程序窗口整体配置(导航栏、标题)

【微信小程序创作之路】- 小程序窗口导航栏配置 第五章 微信小程序窗口导航栏配置 文章目录 【微信小程序创作之路】- 小程序窗口导航栏配置前言一、入口文件的配置二、页面配置三、全局默认窗口配置1.navigationBarTitleText&#xff1a;导航栏标题文字2.navigationBarBackgr…

【UE4 C++】02-编译、生成当前的C++程序

一、编译 编译快捷键&#xff1a; CtrlF7 如果不使用快捷键&#xff0c;可以点击顶部菜单栏中的下拉按钮&#xff0c;然后选择自定义 点击添加命令 点击“生成”&#xff0c;选择编译“”&#xff0c;点击“确定” 此时可以看到顶部菜单栏多了一个用于编译的按钮 二、生成 鼠…

TypeScript学习笔记

TypeScript学习笔记 1、运行环境 1.1、初始化 npm init -y npm i -D webpack webpack-cli webpack-dev-server typescript ts-loader html-webpack-plugin1.2、webpack.config.js const path require(path) const htmlWebpackPlugin require("html-webpack-plugin&…