项目三:声乐盒(音节+音乐)实验

摘要:

本项目以AT89C52为基础,通过矩阵键盘实现7个基本音节的低、中、高音,并在数码管上加以显示,同时通过按键切换模式,不同模式可以播放不同的歌曲

一.主体思路

单片机控制蜂鸣器需要一定频率的方波信号,在一个频率周期内让单片机的某个IO口一半时间高电平,一半时间低电平,一直重复便会生成这个频率的方波信号,就可以驱动蜂鸣器发出想要的声音

如下图为音符延时表

播放音乐要设置每个音符的频率,时长,即在播放音乐过程中,先选择该音符对应的频率和时长,然后进入定时器中断程序使蜂鸣器发声,同时计数变量自增,选择下一音符,以此类推,播放整首音乐

二.主要内容

1.主要功能

(一)矩阵键盘按键控制发出7个基本音节的低、中、高音

(二)蜂鸣器播放指定音乐

(三)单一按键发声

2.硬件电路设计

2.1 元件选取

如上图所示,选取AT89C52开发板,7SEG-MPX1-CA晶体数码管,NPN型三极管、BUZZER(ACTIVE)有源蜂鸣器、按钮BUTTON以及电阻RES和排阻RESPACK-8以及复位所需元器件

2.2 单片机IO口选取

如上图所示,使用了P0、P1的全部IO口,使用了P3的0~3IO口和第7IO以及复位所需IO口

2.3 硬件部分作用

(一)蜂鸣器模块

该模块的作用是发出声音,此处选择有源蜂鸣器,将电压参数改为5V,如下图所示

IO口为高电平时蜂鸣器鸣叫,但由于蜂鸣器的驱动电流较大,IO口无法直接进行驱动,所以需要经过三极管放大电流驱动,其中R1位三极管基极的限流电阻,R2是基极下拉电阻,保证基极浮空或者处于高组态时,三极管有效关断,防止误触发。
(二)矩阵键盘模块

该模块的作用是选择7个基本音节,传递键值给数码管模块。

先不断使行变为低电平,即假设某行按键被按下,再扫描该行的哪一列的按键被按下,消除抖动后传递该按键的值

(三)7SEG-MPX1-CA晶体数码管模块

该模块的作用是显示输出的数据,显示矩阵键盘的值

(四)按键模块

该模块的作用是切换模式,使晶体数码管显示不同的内容

(五)复位模块

该模块的作用是使系统复位,从而切换其他模式

3.软件设计

先进行模块化编程

如上图所示,将整体程序分为主函数main,延时函数delay,按键模块key,蜂鸣器模块Buzzer,音乐模块music,定时器模块timer

(一)music模块

使用define定义相关引脚(低、中、高音频率,下标,音节时长),如上图所示

再使用sbit定义蜂鸣器的P3^7引脚

创建数码管上显示数字的数组dis,创建频率数组FreqTable,代表每个音节的频率,创建音节字符数组tab,和音乐乐谱,音乐乐谱创建过程如下图

定义display显示函数,使P0端口为dis数组中的元素值,从而驱动数码管显示数字

定义fun为音符函数,首先扫描矩阵键盘按键值,定义cntt变量和flag变量,使按键每次按下蜂鸣器只发出一次声音,而不是一直发声

定义fun2、fun3、fun4为音乐函数,先定义计数变量MusicSelect,如果在乐谱数组中没有到结束位置,就先选择音符对应的频率,然后通过延时函数和中断函数使该段时长发出该音符的声音,然后关闭并再次打开定时器,如果到了结束位置,则关闭计时器并一直循环

定义定时器中断函数timer_routine

进入中断函数后,给TH0和TL0赋值频率数组除以和取模256后的值,并使蜂鸣器IO口反转发声

(二)BUZZER模块

使用sbit定义蜂鸣器P3^7引脚

编写蜂鸣器专用延时函数,一次延时500us,再编写蜂鸣器发声函数,在短暂的时间段内使蜂鸣器发声和延时

(三)timer模块

定义timer_init函数,对定时器进行初始化。

初始化步骤如下:

1.首先设置TMOD寄存器,定时器T0工作在方式1,使TMOD寄存器的M1,M0=01,设置C/T=0,为定时器工作模式,对T0的运行仅由TR0来控制,应使相应的GATE位为0,定时器T1不使用,各相关位均设为0,所以TMOD寄存器应初始化为0x01。

2.计算定时器T0的计数初值,设定时时间为50ms,通过公式计算可得出相应的高八位和低八位,分别装入TH0和TL0。

3.设置IE寄存器,将寄存器中的EA,ET0位置1

4.启动和停止定时器T0,将定时器控制寄存器TCON中的TR0=1,则启动定时器T0;TR0=0,则启动定时器T0计时

(四)key模块

通过控制按钮改变点阵中所显示的内容

首先使用sbit定义相关引脚,如上图所示

模式切换函数key( ):

不断扫描是否有按键按下,若有按键按下,则该引脚变为低电平,对其进行消除抖动,并判断是否松开,若松开,进行二次消除抖动,并传回相关按键的值

矩阵键盘函数key_scan( ):

每次都先初始化P1端口,重置为高电平,然后使某一行为低电平,扫描该行是否有某列的按键按下,若有,则传递该行该列的键值

(五)delay模块

编写能够延时1ms和延时12us的函数

(六)main模块

首先对定时器进行初始化

在循环中不断扫描key的按键值,不同的按键值代表点阵显示不同的模式,每个模式都有相对应的功能

4.源程序代码

(一)main模块

#include <reg52.h>
#include <intrins.h>
#include "delay.h"
#include "timer.h"
#include "Buzzer.h"
#include "Key.h"
#include "music.h"
#define uchar unsigned char
#define uint unsigned int
uchar ys;
void main(){timerInit();while(1){ys=key();if(ys==1){while(1)fun();	}else if(ys==2){while(1)fun2();}else if(ys==3){while(1)fun3();}else if(ys==4){while(1)fun4();}}
}

(二)delay模块

#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
void delay(uint x){uchar i, j;while(x--){i = 2;j = 239;do{while (--j);}while (--i);}
}
void delay12us(uint x){uchar i;for(i=0;i<x;i++){;}
}

(三)key模块

#include <reg52.h>
#include "delay.h"
#define uchar unsigned char
#define uint unsigned int
sbit L0=P1^0;
sbit L1=P1^1;
sbit L2=P1^2;
sbit L3=P1^3;
sbit L4=P1^4;
sbit L5=P1^5;
sbit L6=P1^6;
sbit L7=P1^7;
sbit K0=P3^0;
sbit K1=P3^1;
sbit K2=P3^2;
sbit K3=P3^3;
uchar Key(){uint number=0;if(K0==0){delay(20);while(K0==0);delay(20);number=1;}if(K1==0){delay(20);while(K1==0);delay(20);number=2;}if(K2==0){delay(20);while(K2==0);delay(20);number=3;}if(K3==0){delay(20);while(K3==0);delay(20);number=4;}return number;
}
uchar key_scan(){uchar KeyNumber;P1=0xFF;L0=0;if(L4==0){delay(20);while(L4==0);delay(20);KeyNumber=0;}if(L5==0){delay(20);while(L5==0);delay(20);KeyNumber=1;}if(L6==0){delay(20);while(L6==0);delay(20);KeyNumber=2;}if(L7==0){delay(20);while(L7==0);delay(20);KeyNumber=3;}P1=0xFF;L1=0;if(L4==0){delay(20);while(L4==0);delay(20);KeyNumber=4;}if(L5==0){delay(20);while(L5==0);delay(20);KeyNumber=5;}if(L6==0){delay(20);while(L6==0);delay(20);KeyNumber=6;}if(L7==0){delay(20);while(L7==0);delay(20);KeyNumber=7;}P1=0xFF;L2=0;if(L4==0){delay(20);while(L4==0);delay(20);KeyNumber=8;}if(L5==0){delay(20);while(L5==0);delay(20);KeyNumber=9;}if(L6==0){delay(20);while(L6==0);delay(20);KeyNumber=10;}if(L7==0){delay(20);while(L7==0);delay(20);KeyNumber=11;}P1=0xFF;L3=0;if(L4==0){delay(20);while(L4==0);delay(20);KeyNumber=12;}if(L5==0){delay(20);while(L5==0);delay(20);KeyNumber=13;}if(L6==0){delay(20);while(L6==0);delay(20);KeyNumber=14;}if(L7==0){delay(20);while(L7==0);delay(20);KeyNumber=15;}return KeyNumber;
}

(四)timer模块

#include <reg52.h>
sbit P37=P3^7;
void timerInit(){TMOD&=0xF0;TMOD|=0x01;TL0=0x18;TH0=0xFC;TF0=0;TR0=1;ET0=1;EA=1;PT0=0;P37=0;
}

(五)Buzzer模块

#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit P37=P3^7;
void Buzzer_Delay500us(){uchar i;_nop_();i=247;while(--i);
}
void Buzzer_Time(uint ms){uint i;for(i=0;i<ms*2;i++){P37=!P37;Buzzer_Delay500us();}
}

(六)music模块

#include <reg52.h>
#include <intrins.h>
#include "delay.h"
#include "timer.h"
#include "Buzzer.h"
#include "Key.h"
#define uchar unsigned char
#define uint unsigned int
#define SPEED	500
#define di1 159
#define di2 142
#define di3 126
#define di4 119
#define di5 106
#define di6 95
#define di7 84#define zh1 80
#define zh2 71
#define zh3 63
#define zh4 60
#define zh5 53
#define zh6 47
#define zh7 42#define gao1 40
#define gao2 35
#define gao3 32
#define gao4 30
#define gao5 27
#define gao6 24
#define gao7 21
#define P	0
#define S1	1
#define S1_	2
#define S2	3
#define S2_	4
#define S3	5
#define S4	6
#define S4_	7
#define S5	8
#define S5_	9
#define S6	10
#define S6_	11
#define S7	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
sbit P37=P3^7;
uchar i,ans;
uint k,KeyNum;
uchar flag;
uchar cntt;
uchar FreqSelect,MusicSelect;
uchar dis[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e
};uint 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,
};uchar tab[]={di1,di2,di3,di4,di5,di6,di7,zh1,zh2,zh3,zh4,zh5,zh6,zh7,gao1,gao2};uchar code MusicA[]={//1P,	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,//2M6,	4+2,M5,	2,M6, 4,H1,	4,M5,	4+4+4,M3,	4,M4,	4+2,M3,	2,M4,	4,H1,	4,//3M3,	4+4,P,	2,H1,	2,H1,	2,H1,	2,M7,	4+2,M4_,2,M4_,4,M7,	4,M7,	8,P,	4,M6,	2,M7,	2,0xFF
};
uchar code MusicB[]={//4H1,	4+2,M7,	2,H1,	4,H3,	4,M7,	4+4+4,M3,	2,M3,	2,M6,	4+2,M5,	2,M6, 4,H1,	4,//5M5,	4+4+4,M2,	2,M3,	2,M4,	4,H1,	2,M7,	2+2,H1,	2+4,H2,	2,H2,	2,H3,	2,H1,	2+4+4,//6H1,	2,M7,	2,M6,	2,M6,	2,M7,	4,M5_,4,M6,	4+4+4,H1,	2,H2,	2,H3,	4+2,H2,	2,H3,	4,H5,	4,0xFF
};
uchar code MusicC[]={//7H2,	4+4+4,M5,	2,M5,	2,H1,	4+2,M7,	2,H1,	4,H3,	4,H3,	4+4+4+4,//8M6,	2,M7,	2,H1,	4,M7,	4,H2,	2,H2,	2,H1,	4+2,M5,	2+4+4,H4,	4,H3,	4,H3,	4,H1,	4,//9H3,	4+4+4,H3,	4,H6,	4+4,H5,	4,H5,	4,H3,	2,H2,	2,H1,	4+4,P,	2,H1,	2,//10H2,	4,H1,	2,H2,	2,H2,	4,H5,	4,H3,	4+4+4,H3,	4,H6,	4+4,H5,	4+4,//11H3,	2,H2,	2,H1,	4+4,P,	2,H1,	2,H2,	4,H1,	2,H2,	2+4,M7,	4,M6,	4+4+4,P,	4,0xFF
};
void display(uchar k){P0=dis[k];
}
//音符函数
void fun(){KeyNum=key_scan();display(KeyNum);if(cntt!=KeyNum){cntt=KeyNum;flag=1;}if(flag){for(k=0;k<249;k++){P37=~P37;delay12us(tab[KeyNum]);}flag=0;P37=0;}delay(70);
}
void fun2(){MusicSelect=0;Buzzer_Time(100);while(1){if(MusicA[MusicSelect]!=0xFF)		//如果不是停止标志位{FreqSelect=MusicA[MusicSelect];	//选择音符对应的频率MusicSelect++;delay(SPEED/4*MusicA[MusicSelect]);	//选择音符对应的时值MusicSelect++;TR0=0;delay(5);						//音符间短暂停顿TR0=1;}else								//如果是停止标志位{TR0=0;while(1);}}
}
void fun3(){MusicSelect=0;Buzzer_Time(100);while(1){if(MusicB[MusicSelect]!=0xFF)		//如果不是停止标志位{FreqSelect=MusicB[MusicSelect];	//选择音符对应的频率MusicSelect++;delay(SPEED/4*MusicB[MusicSelect]);	//选择音符对应的时值MusicSelect++;TR0=0;delay(5);						//音符间短暂停顿TR0=1;}else								//如果是停止标志位{TR0=0;while(1);}}
}
void fun4(){MusicSelect=0;Buzzer_Time(100);while(1){if(MusicC[MusicSelect]!=0xFF)		//如果不是停止标志位{FreqSelect=MusicC[MusicSelect];	//选择音符对应的频率MusicSelect++;delay(SPEED/4*MusicC[MusicSelect]);	//选择音符对应的时值MusicSelect++;TR0=0;delay(5);						//音符间短暂停顿TR0=1;}else								//如果是停止标志位{TR0=0;while(1);}}
}
void timer_routine() interrupt 1{if(FreqTable[FreqSelect]){                  //如果不是休止符TH0 = FreqTable[FreqSelect]/256;		//设置定时初值TL0 = FreqTable[FreqSelect]%256;		//设置定时初值P37=!P37;                         		//翻转蜂鸣器IO口}
}

至此,我们已经基本完成了整个项目,.h文件自然不必多说,相信各位读者的能力。

相信大家对蜂鸣器和矩阵键盘的使用更加熟练,也更多的了解到了AT89C52单片机,欢迎各位一起讨论和交流。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机中班音乐,【精品】中班音乐教案6篇

【精品】中班音乐教案6篇 作为一名无私奉献的老师&#xff0c;就难以避免地要准备教案&#xff0c;编写教案有利于我们科学、合理地支配课堂时间。教案应该怎么写呢&#xff1f;下面是小编为大家整理的中班音乐教案6篇&#xff0c;仅供参考&#xff0c;希望能够帮助到大家。 中…

在线绘图网站

https://www.freedgo.com/

https://app.diagrams.net/在线画图的一些技巧

最近工作需要,实践了在线画图的case, 下面就把使用心得记录一下: 关于diagrams 的一些小技巧: 登入的网页是:Flowchart Maker & Online Diagram Software 1: 利用group 的选项,这个可以整体移动,不用担心会漏掉一个: 就是选中一个图标,然后,看右边arrange 下面…

在线画图网站Graph Editor的使用

网站链接 链接 网站介绍 CS Academy是一个在线的算法学习和竞赛的网站&#xff0c;打开网站左侧导航栏中的App目录下有一个可以在线画图的应用Graph Editor&#xff0c;用来画图&#xff08;有向、无向&#xff09;非常好用。 网站使用 网站的界面如下&#xff1a; 左侧为…

一个实例讲讲 ChatGPT 推理

吴恩达与 OpenAI 官方联合推出了 1.5 小时的免费视频课&#xff1a;地址&#xff1a; https://learn.deeplearning.ai/chatgpt-prompt-eng/lesson/2/guidelines 今天我学了第四讲&#xff0c;ChatGPT Inferring&#xff0c;即推理 教学中&#xff0c;给的例子是情绪判断。 我很…

AUTOSAR的现状和利弊

利 篇 做AUTOSAR项目一段时间了&#xff0c;做完了几个基于AUTOSAR架构的控制器软件项目&#xff0c;也完成了符合功能安全ASILC的AUTOSAR架构的软件平台。 在做这些项目的过程中&#xff0c;通过项目招标&#xff0c;供应商考察&#xff0c;对比同行以及自己亲自实施的情况&…

软件测试助理利弊,女生做软件测试的利弊都有什么?

在编程领域&#xff0c;女程序猿是相对较少的&#xff0c;因为编程思维即逻辑思维就难倒了大部分女生。但是在另外一个领域&#xff0c;女生却在近来几年占据越来越多&#xff0c;那就是软件测试行业。相对于其他IT岗位来说&#xff0c;软件测试对技术的要求没有那么高&#xf…

机器人改变生活利弊英语作文_机器人的利弊作文

人类在里面住上一辈子也没关系,只有操纵器和一个透明的东西,却随时可以看到机器人在街道上走来走去? 以下是小学生作文网小编为你推荐的末来的机器人作文 &#xff0c;希望对你有所帮助。... 2018-12-28 阅读全文 >> 机器人是自动控制机器(Robot)的俗称&#xff0c;自动…

使用ChatGPT生成思维导图

前言 当我们要处理一些复杂的事务&#xff0c;特别是需要组织和整理很多信息时&#xff0c;思维导图是一种非常有用的工具。它是一种图像化的表示方法&#xff0c;通过将相关的概念和信息写在一个中心主题的周围&#xff0c;然后随着我们的思考和积累&#xff0c;不断地添加和…

Github README中的小图标如何制作

github README中的小图标如何制作 实质就是通过一个网站&#xff08;https://img.shields.io/badge/&#xff09;加载一张svg图片&#xff0c;只需要改其中的后缀便可以获得不同的图片 ![](https://img.shields.io/badge/-Jupyter-F37626?styleflat-square&logojupyter&…

chatgpt赋能python:Python在桌面上的图标SEO

Python在桌面上的图标SEO 对于许多程序员和开发人员来说&#xff0c;Python已经成为了一种不可或缺的编程语言。在许多应用场景中&#xff0c;Python语言已经成为了首选的编程语言。Python语言的优势在于其简单易学、高效、可读性强等特点。而许多开发人员在使用Python语言时&…

chatgpt赋能Python-pycharm桌面图标变白

PyCharm是一个非常流行的Python集成开发环境&#xff0c;它可以帮助Python开发人员更快更高效地编写代码。但是&#xff0c;有些用户可能会遇到一个问题&#xff1a;他们的PyCharm桌面图标突然变成了白色&#xff0c;而不是原来的彩色图标。在这篇文章中&#xff0c;我将详细介…

在Python里使用ChatGPT

近来chatGPT挺火的&#xff0c;也试玩了一下&#xff0c;确实挺有意思。这里记录一下在Python中如何去使用chatGPT。 本篇文章的实现100%基于 chatGPT&#xff0c;我是搬运工无疑了&#xff01;&#xff01;&#xff01; 知识点&#x1f4d6;&#x1f4d6; pip install open…

谷歌报复性砸出5620亿参数大模型!比ChatGPT更恐怖,机器人都能用,学术圈已刷屏...

明敏 发自 凹非寺量子位 | 公众号 QbitAI 为应对新一轮技术竞赛&#xff0c;谷歌还在不断出后手。 这两天&#xff0c;一个名叫PaLM-E的大模型在AI学术圈疯狂刷屏。 它能只需一句话&#xff0c;就让机器人去厨房抽屉里拿薯片。 即便是中途干扰它&#xff0c;它也会坚持执行任务…

如何查询Facebook广告账户的账单和发票?

我们在BM上投放广告时&#xff0c;每个月都需要支付对应的账单&#xff0c;在支付之前&#xff0c;我们可以有两种方式可以查看本月各个账户的消费情况。 第一种&#xff0c;我们确切知道要查询的账户&#xff0c;这样的话我们可以BM商务管理平台&#xff0c;找到广告账户&…

微信对账单功能开发(V2)

下载交易账单接口开发 应用场景&#xff1a; 商户可以通过该接口下载历史交易清单。比如掉单、系统错误等导致商户侧和微信侧数据不一致&#xff0c;通过对账单核对后可校正支付状态。 注意&#xff1a; 1、微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易…

财务报表分析

财务报表分析的概念 1.以了解企业盈利能力为主要目标 2.企业投资风险分析 3.未来盈利预测 4.估计企业的内在价值 财务报告的构成 财务报告是指公司对外提供的反映公司某一特定日期财务状况和某以会计期间经营成果、现金流量的文件。 财务报告包括【财务报表、财务情况说…

python分析财务报表

前言 其实这也是老师要求我们分析的一个项目&#xff0c;所以记录下分析的过程。 财务大数据作为大数据方向的一个热门方向&#xff0c;如果能学好&#xff0c;对于我们的今后工作是会有很大帮助的&#xff0c;同时目前市场人才需求也是很大的。 实验目的 利用python构建…

用chatGPT写一个SAP的资产负债表

最近爆火的ChatGpt相信大家都不陌生&#xff0c;听说它还能写代码&#xff0c;而且能力不凡。 chatGPT能用来干什么&#xff1f; 它可以自动生成文本对话&#xff0c;因此可以用来实现聊天机器人等应用。 例如&#xff0c;您可以利用ChatGPT构建一个聊天机器人&#xff0c;用…

ChatGPT 提示的艺术 — 编写清晰有效提示指南

术语解释 所谓 ChatGPT 提示&#xff08;Prompt&#xff09;&#xff0c;就是你与 ChatGPT 对话的时候在输入框输入的文本内容&#xff0c;例如&#xff1a; 红框内的文本就是这段对话中提供给 ChatGPT 的提示。 如果你还没有 ChatGPT 账号&#xff0c;请参考这篇教程获取&…