红外遥控音乐播放器单片机课程设计:基于51单片机音乐播放器课程设计

来源:英国留学 发布时间:2020-03-24 点击:

  

 单片机课程设计

 项目名称

  红外遥控音乐播放器设计

  专业班级

  通信X班

  学生姓名

 指导教师

 X年 X 月

 X日

 摘

 要

 随着计算机技术的发展, 单片机的应用范围也不断扩大,目前单片机渗透到工作和生活的各个领域。在以单片机为核心的控制系统中,红外遥控成为目前使用比较广泛的一种无线通信和遥控手段。本课程设计提出一种基于单片机的红外遥控音乐播放器的设计方法。主要采用单片机为控制核心,以红外信号为通信手段,通信蜂鸣器发声,来完成音乐播放器的功能。本设计具有无线、非接触控制,抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等显著优点及特色。通过本设计可以完成简单的音乐播放器的功能,包括播放及更换歌曲等内容。通过本次课程设计,我对单片机中断系统等知识有了进一步的了解,对单片机的相关知识做到理论联系实际。

 关键词:单片机;红外遥控;中断系统;

  该单片机程序设计基于HOT-51型单片机开发板电路编写,故可在其开发板上使用。

 本设计中未使用HOT-51单片机开发板配套红外遥控器,使用的红外遥控器的按键对应码值已在表4-1中写出,根据自已红外遥控器的按键对应码值修改代码中按键码值部分即可使用。

 Abstract

 With the development of computer technology, the application range of the microcontroller expanding microcontroller penetrated into various fields of work and life. Microcontroller as the core of the control system, infrared remote control to use a wireless communication and remote control means. This course is designed infrared remote control music player based microcontroller design method. Mainly using SCM as the control center, the infrared signal as a means of communication, communication buzzer sound to complete the functionality of the music player. The design of wireless, non-contact control, anti-interference ability, reliable transmission of information, low power consumption, low cost, easy to realize significant advantages and characteristics. Through this design can be completed simple music player functions, including play and change songs. Design through the course, I interrupt timer, external knowledge have a better understanding, to do the theory with actual knowledge of the microcontroller.

 Keywords: Microcontroller Unit;Infrared Remote Control;Interrupt System;

  目

 录

 摘

 要 I

 Abstract II

 第1章

 绪论 1

 1.1

 概述 1

 1.2

 主要功能 1

 第2章

 电路设计 2

 2.1

 整体电路设计 2

 2.2

 电路模块设计 3

 2.2.1

 单片机最小系统电路 3

 2.2.2

 红外解码电路 4

 2.2.3

 显示及播放电路 5

 第3章

 程序设计 8

 3.1

 红外解码程序 8

 3.2

 播放及显示程序 12

 第4章

 硬件调试 17

 结论 19

 参考文献 20

 附录1

 整体电路图及实物图 21

 附录2

 电路元件 22

 附录3

 程序源码 23

 致谢 32

 第1章

 绪论

 1.1

 概述

 利用单片机演奏音乐是单片机爱好者的兴趣之一,应用的范围也比较广泛。所谓音乐播放器,由单片机进行信息处理,再经过信号放大,由蜂鸣器发出乐曲声。我们知道,振动产生声音,振动频率不同所发出的声音也就不同。有规律的振动发出的声音叫“乐音”。音乐由音频和节拍构成,音频即发声的频率;节拍即延时的长短。因此利用单片机的定时器,产生一定频率的方波,即可以产生一定频率的声音。再利用单片机软件延时的方法来产生不同的节拍。把音频和节拍结合起来,进行合理的排列,即可播放出比较悦耳的音乐。本文比较详细地介绍了音乐播放器的工作原理、设计思路、硬件的选择及相关作用、软件的实现方法以及详细的程序清单。

 控制单片机播放音乐的方式有很多,多数使用者利用单片机存储音乐与控制播放。本设计利用AT89S52单片机及少数外围电路控制音乐播放,产生两首不同的歌曲。 对于单片机产生音乐,关键是控制频率的输出。本设计采用了定时器T0中断的方法产生不同频率的脉冲,从而产生不同频率的声音。此外,使用红外一体化头SM0038接收红外信号,通过外部中断INT1来进行对红外信号的解码,由单片机内部程序对不同的键值完成不同的操作。并且使用常用的无源蜂鸣器进行发声,实现了一个简单的遥控音乐播放器的功能。

 1.2

 主要功能

 本设计以单片机为核心实现红外遥控音乐播放器功能,主要完成功能为两首歌曲的选择播放、暂停、暂停后断点播放、结束播放歌曲,播放下一曲,播放上一曲等功能。同时,使用数码管显示红外信号解码后的键值。其中为了方便,将32位的二进制红外信号编码解码为8位16进制编码。其中,本设计只显示红外信号解码后8位16进制编码中的两位数据码,其它的用户编码与数据码的反码共6位不予显示。本设计中使用常见的家用红外遥控器进行控制,使用其中的1、2两个数字键(对应功能选择1、2两首歌曲),音量加、减两个按键(对应功能上一曲、下一曲),频道加、减两个按键(对应功能暂停、结束播放),以及确定键(对应功能播放歌曲)。

 第2章

 电路设计

 2.1

 整体电路设计

 根据设计要求,红外遥控音乐播放器可以分为三个模块进行设计:

 1.单片机最小系统电路:单片机最小系统,或者称为最小应用系统,是指用最少的元件组成的单片机可以工作的最小的系统单元。

 对51系列单片机来说,最小系统一般应该包括:单片机、时钟电路、复位电路。本设计中使用的单片机为AT89S52,晶振电路使用12MHZ的晶振。复位电路:由电容串联电阻构成,当系统一上电,RST脚将会出现高电平,当RST脚的高电平持续两个机器周期以上就将复位。

 2.红外解码电路:本电路主要用于对红外遥控器发出的红外信号进行解码,然后程序根据解码后的不同键值相应完成不同的功能。

 3.显示及播放电路:本部分电路用于显示红外遥控器不同按键所对应的不同按键值,实物中用两位16进制数在数码管上进行显示。播放电路主要用蜂鸣器来播放不同的音乐曲目。

 分析各模块电路的功能,画出原理框图如图2-1所示:

 A

 T

 8

 9

 S

 5

 2

 单片机复位电路

 单片机时钟电路

 红外解码 电路

 红外解码

 显示电路

 音乐播放电路

 图2-1 红外遥控音乐播放器原理框图

 2.2

 电路模块设计

 2.2.1

 单片机最小系统电路

 单片机最小系统电路如图2-2所示:

 图2-2 单片机最小系统电路图

 由图2-2可以知道,单片机最小系统主要由复位电路、时钟电路等组成。

 1.复位电路:由电容串联电阻构成,并结合"电容电压不能突变"的性质,可以知道,当系统一上电,RST脚将会出现高电平,并且,这个高电平持续的时间由电路的RC值来决定。

 典型的51单片机当RST脚的高电平持续两个机器周期以上就将复位,所以,适当组合RC的取值就可以保证可靠的复位。一般教科书推荐C 取10uF,R取8.2K左右。当然也有其他取法的,原则就是要让RC组合可以在RST脚上产生不少于2个机周期的高电平。单片机复位电路就好比电脑的重启部分,当电脑在使用中出现死机,按下重启按钮电脑内部的程序从头开始执行。单片机也一样,当单片机系统在运行中,受到环境干扰出现程序跑飞的时候,按下复位按钮内部的程序自动从头开始执行。

 2.时钟电路:单片机内部有一个高增益反相放大器,引脚XTAL1 和XTAL2 分别是该放大器的输入端和输出端,如果引脚XTAL1 和XTAL2 两端跨接上晶体振荡器(晶振)或陶瓷振荡器就构成了稳定的自激振荡电路,该振荡电路的输出可直接送入内部时序电

 路。

 单片机的时钟可由两种方式产生,即内部时钟方式和外部时钟方式。

 (1)内部时钟方式。内部时钟方式即是由单片机内部的高增益反相放大器和外部跨接的晶振、微调电容构成时钟电路产生时钟的方法。外接晶振(陶瓷振荡器)时,C1、C2 的值通常选择为30Pf左右;C1、C2 对频率有微调作用,晶振或陶瓷谐振器的频率范围可在1.2MHz ~12MHz之间选择。为了减小寄生电容,更好地保证振荡器稳定、可靠地工作,振荡器和电容应尽可能安装得与单片机引脚XTALl 和XTAL2 靠近。由于内部时钟方式外部电路接线简单,单片机应用系统中大多采用这种方式。内部时钟方式产生的时钟信号的频率就是晶振的固有频率,常用fsoc 来表示。

 (2)外部时钟方式。外部时钟方式即完全用单片机外部电路产生时钟的方法,外部电路产生的时钟信号被直接接到单片机的XTAL1引入,此时XTAL2 开路。

 3.内外程序存储器选择控制端EA/Vpp,决定了单片机访问内部或外部的程序存储器。EA高电平时,访问内部程序存储器,但当程序计数器(PC)值超过0FFFFH时,单片机自动转向外部程序存储器。当EA低电平时,不管单片机有无内部存储器,只访问外部存储器[1]。

 2.2.2

 红外解码电路

 红外解码电路如图2-3所示:

 图2-3 红外解码电路图

 由图2-3知道,红外解码电路中主要元件为红外一体化接收头SM0038。

 一体化红外接收头SM0038是集信号放大、滤波、检波、整形于一体的红外接收器,电路内置PIN二极管和前置放大器,采用可以红外滤波的环氧树脂材料封装,可靠性高,不易受环境影响并可以防止非控制信号的输出脉冲出现。

 内部结构如图2-4所示:

 图2-4 SM0038内部结构图

 SM0038内置带通滤波器、积分器、和自动增益控制电路以抑制各种干扰和噪音。数据信号和干扰信号的主要区别在于载波频率、脉冲波长和工作周期上。所以数据信号应该满足载波信号的频率尽量接近带通滤波器的中心频率(38KHZ);脉冲长度在300us以上;数据的编码类型相兼容。而本系统选用的SM0038在这三方面和NEC编码格式是相配的

 2.2.3

 显示及播放电路

 显示及播放电路如图2-5所示:

 图2-5 显示及播放电路图

 1.74HC573:八进制3态非反转透明锁存器。

 其真值表如表2-1所示:

 表2-1 74HC573真值表

 输入

 输出

 LE

 D

 Q

 L

 H

 L

 L

 L

 H

 H

 H

 L

 L

 X

 Q0

 H

 X

 X

 Z

 由真值表可知:当=0、LE=1时,输出端数据等于输入端数据;当=0、LE=0时,输出端保持不变;当=1时,无论LE、D为何,输出端为高阻态。

 74HC573与74HC138在电路中主要用于由数码管组成的显示电路。在数码管显示时,如果要维持一个数据的显示,往往要持续的快速的刷新。尤其是在四段八位数码管等这些要选通的显示设备上。在人类能够接受的刷新频率之内,大概每三十毫秒就要刷新一次。这就大大占用了处理器的处理时间,消耗了处理器的处理能力,还浪费了处理器的功耗。

 锁存器的使用可以大大的缓解处理器在这方面的压力。当处理器把数据传输到锁存器并将其锁存后,锁存器的输出引脚便会一直保持数据状态直到下一次锁存新的数据为止。这样在数码管的显示内容不变之前,处理器的处理时间和I/O引脚便可以释放。可以看出,处理器处理的时间仅限于显示内容发生变化的时候,这在整个显示时间上只是非常少的一个部分。而处理器在处理完后可以有更多的时间来执行其他的任务。这就是锁存器数码管显示方面的作用:节省了宝贵的MCU时间。

 锁存器就是把当前的状态锁存起来,使CPU送出的数据在接口电路的输出端保持一段时间锁存后状态不再发生变化,直到解除锁定。还有一些芯片具有锁存器,比如芯片74LS244 (3态8位缓冲器)就具有锁存器的功能,它可以通过把一个引脚置高电平后,输出就会保持现有的状态,直到把该引脚清0后才能继续变化。

 缓冲寄存器又称缓冲器,它分输入缓冲器和输出缓冲器两种。前者的作用是将外设送来的数据暂时存放,以便处理器将它取走;后者的作用是用来暂时存放处理器送往外设的数据。有了数控缓冲器,就可以使高速工作的CPU与慢速工作的外设起协调和缓冲作用,实现数据传送的同步。由于缓冲器接在数据总线上,故必须具有三态输出功能。

 2.74HC138:三通道输入、八通道输出译码器。

 其真值表如表2-2所示:

 表2-2 74HC138真值表

 Enable

 Address

 Output

 E3

 E2

 E1

 A2

 A1

 A0

 Y0

 Y1

 Y2

 Y3

 Y4

 Y5

 Y6

 Y7

 X

 X

 H

 X

 X

 X

 H

 H

 H

 H

 H

 H

 H

 H

 L

 X

 X

 X

 X

 X

 H

 H

 H

 H

 H

 H

 H

 H

 X

 H

 X

 X

 X

 X

 H

 H

 H

 H

 H

 H

 H

 H

 H

 L

 L

 L

 L

 L

 L

 H

 H

 H

 H

 H

 H

 H

 H

 L

 L

 L

 L

 H

 H

 L

 H

 H

 H

 H

 H

 H

 H

 L

 L

 L

 H

 L

 H

 H

 L

 H

 H

 H

 H

 H

 H

 L

 L

 L

 H

 H

 H

 H

 H

 L

 H

 H

 H

 H

 H

 L

 L

 H

 L

 L

 H

 H

 H

 H

 L

 H

 H

 H

 H

 L

 L

 H

 L

 H

 H

 H

 H

 H

 H

 L

 H

 H

 H

 L

 L

 H

 H

 L

 H

 H

 H

 H

 H

 H

 L

 H

 H

 L

 L

 H

 H

 H

 H

 H

 H

 H

 H

 H

 H

 L

 74HC138译码器可接受3位二进制加权地址输入(A0, A1和A2),并当使能时,提供8个互斥的低有效输出(Y0至Y7)。74HC138特有3个使能输入端:两个低电平有效(E1和E2)和一个高电平有效(E3)。除非E1和E2置低且E3置高,否则74HC138将保持所有输出为高。利用这种复合使能特性,74HC138充当一个8输出多路分配器,本设计中用于进行数码管的位选。

 3.ULN2003:高压大电流达林顿晶体管阵列,由七个硅NPN复合晶体管组成。电路特点: ULN2003的每一对达林顿都串联一个2.7K的基极电阻,在5V的工作电压下它能与TTL和CMOS电路 直接相连,可以直接处理原先需要标准逻辑缓冲器来处理的数据。具有电流增益高、工作电压高、温度范围宽、带负载能力强等特点,适应于各类要求高速大功率驱动的系统。本设计中用于无源蜂鸣器的驱动,同时可以为再次扩展时提供驱动电路。

 第3章

 程序设计

 分析红外遥控音乐播放的功能,包括选择播放两首歌曲、暂停、暂停后断点播放、结束播放歌曲,播放下一曲,播放上一曲,并且使用数码管显示红外信号解码后的两位16进制的数据码。根据以上功能,可心得出结论:该程序设计的主要工作,即核心问题是红外信号的解码。因为,无论是播放音乐的哪一个操作,还是显示红外信号的数据码,都是建立在对红外信号的正确解码下的。首先进行正确的红外解码,然后根据解码后的键值进行播放歌曲与显示按键值。按照以上得出的结论,画出程序流程图如图3-1所示:

 开始

 主函数判断有无红外信号

 收到红外信号

 未收到红外信号

 处理红外信号

 显示解码键值

 播放选择歌曲

 暂停与结束曲

 播放上一曲

 播放下一曲

 图3-1 程序流程图

 结合程序流程图,可以知道:将整个程序的设计分为两个模块,即:红外解码、播放及显示。

 3.1

 红外解码程序

 在进行程序设计之前,先分析一下红外信号的波形。每当次按键按下,红外发射器会发出一串脉冲,红外接收器会收到这一串脉冲宽度不等的脉冲波形流,其脉冲流包括:(1)前导码:第1个脉冲波形;(2)用户码1:第2到第9个脉冲波形;(3)用户码2:第10到第17个脉冲波形;(4)数据码:第18到第25个脉冲波形;(5)数据反码:第26到第33个脉冲波形;(6) 连续按键脉冲:第34和第35个脉冲为结束脉冲,在每次按键结束后会有两个结束脉冲,如果一直按键不放的话,会一直发送连续按键脉冲,并可以认为在收到10

 个连续按键脉冲后是下一个按键(本次设计中不考虑连续按键脉冲)。其码型结构如图3-2所示:

 图3-2 红外信号码型图

 由图3-2可知:红外信号码型中本次设计中要使用的部分,即是图3-2中的8位键数据码。下面分析具体的怎样进行红外信号的解码。

 红外信号为采用脉宽调制的串行码,以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的“0”;以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的“1”,其波形如图3-3所示。

 图3-3 红外信号脉冲宽度图

 上述“0”和“1”组成的32位二进制码经38kHz的载频进行二次调制以提高发射效率,达到降低电源功耗的目的。然后再通过红外发射二极管产生红外线向空间发射,即产生了如图3-2所示的有效码组序列。在图3-3中同样可以看到引导码脉宽为9ms,间隔4.5ms。在红外信号经过解码电路后,原码型中的高低电平进行反转。在得到的新码型中,去掉第一个下降沿(引导码),第二个下降沿开始即为有效码序列,应该进行解码并记录。在本设计中,将解码后的信号引入外部中断1,由于是下降沿有效,故IT1=1[2]。红外解码源码如下:

 unsigned char irtime;

  //脉冲宽度时间值

 unsigned char startflag;//接收开始标志

 unsigned char bitnum;

  //码组位数

 unsigned char irreceok; //接收完成标志

 unsigned char irprocok; //解码完成标志

 unsigned char irdata[33];//脉冲宽度数组

 unsigned char ircode[4]; //解码值数组

 void timer0init(void)

 {

  TMOD=0x02;

 //定时器0

 定时方式2

 8位自动重装

  TH0=0x00;

 //初值为0

 实现定时256us

  TL0=0x00;

  ET0=1;

  //开定时器0中断

  EA=1;

  //开总中断

  TR0=1;

  //启动定时器0

 }

 void int1init(void)

 {

  IT1=1;

  //外部中断1负跳变沿有效

  EX1=1;

  //开外部中断1中断

  EA=1;

  //开总中断

 }

 void irproc(void)

 //解码函数

  {

  uchar k,value,m,j;

  k=1;

  for(j=0;j<4;j++)

 //4组二进制码

  {

  for(m=0;m<8;m++)

  //每组8位

 {

  value=value>>1;

  //由于低位在前,所以右移到正常顺序

  if(irdata[k]>6)

  //irtime大于6*256us

  则解码数据为1

  {

 value=value | 0x80; //解码数据为1

 则高位或1

 则高位置1

  }

  k++;

  //所有二进制码的位

 }

 ircode[j]=value;

  //每组解码后的值存入ircode

  }

  irprocok=1;

  //解码完成

 }

 void main()

 {

  timer0init();

  //定时器初始化

  int1init();

  //外部中断初始化

  while(1)

  {

 if(irreceok)

  //接收完成

 {

  irproc();

  //解码

  irreceok=0;

 }

 if(irprocok)

  //解码完成

 {

  irwork();

  //把解码后的数据转成16进制的两位数

  irprocok=0;

 }

 }

 }

 void timer0() interrupt 1

 {

  irtime++;

 }

 void int1() interrupt 2

 {

  if(startflag==1)

  {

 if(irtime>32)

  //检测9ms引导码

 {

  bitnum=0;

  }

 irdata[bitnum]=irtime;

 irtime=0;

 bitnum++;

 if(bitnum==33)

 //接收结束

 {

 bitnum=0;

  irreceok=1;

 //接收完成

 }

  }

  else

  {

 startflag=1;

  //接收开始标志位

 irtime=0;

  }

 }

 3.2

 播放及显示程序

 分析音乐播放的过程,其为不同频率声音的组合,当一组恰当频率声音组合按照一定的先后顺序与节拍播放时,即可产生音乐。故要产生音频信号,只要算出某一音频的周期,将此周期除以2即为半周期的时间,利用定时器计时此半周期时间,计时到后取反输出,重复此过程即得到此频率的声音信号。此信号从P2.3脚输出,用ULN2003驱动蜂鸣器播放音乐。其中每个音符使用两个字节表示:低位字节(偶地址)代表音级,表示的音级为c、﹟c、d、﹟d、e、f、……a3、﹟a3、b3;高位字节(奇地址)代表音符的时值(节拍),表示拍数为1/8拍(0.10s)~8拍(6.40s)。

 程序设计中用软件延时程序来控制音级, 与红外解码共用定时器0进行节拍的控制,并在播放和暂停播放中随时判断是否有红外信号的改变,以便随时更换或结束音乐。本设计中歌曲的音符存在一个数组中,以在开始位置和在中间位置播放不同的曲目。红外信号解码后,用两位共阴数码管显示其中的数据码[3]。显示电路的74HC573用于数码管的驱动,74HC138用于数码管动态扫描时的位选,蜂鸣器播放音乐源码如下:

 #define uchar unsigned char

 #define uint

 unsigned int

 sbit FM=P2^3;

 //定义蜂鸣器引脚

 uchar count;

 unsigned char code song[] ={

 //祝你平安

 0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,0x26,0x20,0x30,0x20,

 0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,0x26,0x20,0x20,0x20,0x20,0x20,0x1c,0x20,

 0x20,0x80,0x2b,0x20,0x26,0x20,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20,

 0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,0x39,0x10,0x26,0x20,

 0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10,

 0x2b,0x20,0x30,0x10,0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x20,

 0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,0x18,0x20,0x26,0x20,

 0x20,0x20,0x20,0x40,0x26,0x20,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20,

 0x20,0x80,0x1c,0x20,0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,0x10,

 0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,0x10,0x2b,0x10,0x2b,0x80,

 0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x60,0x26,0x10,0x2b,0x20,0x30,0x20,

 0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,0x20,

 0x39,0x20,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x10,0x40,0x10,0x20,0x10,

 0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x00,

 //八月桂花遍地开

 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};

 void delay_50us(uint t)

 //延时50微秒

 {

  uchar j;

  for(;t>0;t--)

  {

 for(j=19;j>0;j--);

  }

 }

 void timer0init(void)

 {

  TMOD = 0x01;

  //定时器0

 定时方式1

  IE

  = 0x82;

  //开定时器中断

 开总中断

  TH0

 = 0xDC;

  //定时10ms

  TL0

 = 0x00;

  //定时10ms

 }

 void play(uchar i)

 //音乐播放函数

 {

  uchar temp1,temp2;

  uint addr;

 //song[]播放位置

  count = 0;

 //中断计数清0

  addr = i * 217;

  while(1)

  {

 temp1 = song[addr++];

  if (temp1 == 0xFF)

 //休止符

  {

 TR0 = 0;

 //关闭定时器0

 delay_50us(100);

  }

  else if (temp1 == 0x00) //歌曲结束符

  {

 return;

  }

  else

  {

 temp2 = song[addr++];

 TR0 = 1;

 //启动定时器0

  while(1)

  {

 FM = ~FM;

  delay_50us(temp1);

 if(temp2 == count)//节拍

  {

 count = 0;

 break;

  }

 }

  }

  void main()

 {

  timer0init();

  //定时器初始化

  while(1)

  {

 play(0);

 // play(0)为祝你平安

  play(1)为八月桂花遍地开

  }

 }

 void timer0() interrupt 1

 {

  TH0 = 0xDC;

  TL0 = 0x00;

  count++;

 //长度加1

 }

 数码管显示红外解码值源码如下:

 #define uchar unsigned char

 uchar table[16] =

  {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

 //数码管显示编码

 uchar disp[2];

  //送往数码管的数

 void irwork(void)

  //把解码后的数据转成16进制的两位数

 {

 disp[0]=ircode[2]/16;

  //取出ircode中的两位“数据码”

  disp[1]=ircode[2]%16;

  //取出ircode中的两位“数据码”

 }

 void display(void)

  //数码管显示函数

 {

 P0=table[disp[0]];

  //P0口送数据

 P2=0x06;

  //数据管位选

 delay_50us(2);

 //显示数值保持100us

 P2=0x00;

  //关闭位选

 P0=table[disp[1]];

  //P0口送数据

 P2=0x07;

  //数据管位选

 delay_50us(2);

 //显示数值保持100us

 P2=0x00;

  //关闭位选

 }

 void main()

 {

  while(1)

  {

 display();

  }

 }

 第4章

 硬件调试

 根据上述设计电路画出电路原理图,根据原理图焊接电路板,实物图如图4-1所示:

 图4-1 实物图

 在本设计中使用的红外遥控器如图4-2所示,遥控器各按键相应码值如图4-3所示:

  1b

  18

 17

 16

  15

 14

 13

  12

 11

 10

  0f

 1a

 0e

  19

 00

  08

 02

 07

 06

 05

 0a

 1d

  03

 1f

 04

  0b

 图4-2 红外遥控器

 图4-3 遥控器按键码值

  红外遥控音乐播放器的设计中,对于红外遥控器未将全部的按键设计功能,本设计

 使用按键对应码值及功能如表4-1所示:

 表4-1 遥控器按键、码值及功能表

 遥控器按键

 按键对应码值

 功能

 数字键1

 17

 曲目1

 数字键2

 16

 曲目2

 频道“+”

 02

 暂停

 音量“-”

  07

 上一曲

 确认

 06

 确认

 音量“+”

 05

 下一曲

 频道“-”

 0a

 停止

 根据设计功能进行硬件调试,调试过程如下:

 (1)单片机上电,此时无按键按键,数码管显示00,蜂鸣器不工作。

 (2)按下数字键1,对应码值17,数码管显示17,蜂鸣器工作,实现播放曲目1:祝你平安。

 (3) 按下数字键2,对应码值16,数码管显示16,蜂鸣器工作,实现播放曲目2:八月桂花遍地开。

 (4) 按下频道“+”,对应码值02,数码管显示02,蜂鸣器暂停播放曲目2。按下确认键,对应码值06,数码管显示06,蜂鸣器继续工作,实现断点播放曲目2。

 (5) 按下频道“+”,对应码值02,数码管显示02,蜂鸣器暂停播放曲目2。按下音量“-”,对应码值07,数码管显示07,蜂鸣器播放曲目1,实现暂停时更换曲目。

 (6) 按下音量“+”,对应码值05,数码管显示05,蜂鸣器播放曲目2,实现播放时更换曲目。

 (7) 按下频道“-”,对应码值0a,数码管显示0a,蜂鸣器停止工作,实现停止播放功能。

 结论

 通过此次课程设计,我对单片机的相关知识有了进一步的了解和认识,在单片机外围电路的设计过程中也学到了许多课本上没有的知识,并且学会了使用Proteus仿真软件,可以让我们在虚拟的环境中进行仿真,可以先通过它来检验电路的正确性和程序的可行性,而不需要真实电路环境的介入,不必顾及仪器设备的短缺与环境的限制,能够极大的提高实验的效率。

 本次设计让我学到的知识有很多,提高了我的逻辑思维能力,使我在逻辑电路的分析与程序的设计上有了更大的进步。加深了我对组合逻辑电路、时序逻辑电路以及单片机程序设计方面的认识,也进一步增进了对一些常见逻辑器件的了解。另外,我还在焊接单片机电路的过程中,学到了许多焊接方面的知识与技巧。并且,培养了我查阅参考书和独立思考的能力。这次课程设计使我真正懂得了理论与实际相结合的重要性。

 参考文献

 [1] 张毅刚.MCS-51单片机应用设计.哈尔滨:哈尔滨工业大学出版社,2003

 [2] 求是科技.8051系列单片机C程序设计完全手册.北京:人民邮电出版社,2006

 [3] 李升.单片机原理与接口技术.北京:北京大学出版社,2011

 附录1

 整体电路图及实物图

 附录2

 电路元件

 1

 单片机

 AT89S52

 1片

 2

 锁存器

 74HC573

 1片

 3

 三八译码器

 74HC138

 1片

 4

 达林顿晶体管

 ULN2003

 1片

 5

 红外一体接收头

 SM0038

 1个

 6

 电容

 30PF

 2个

 7

 电容

 104

 1个

 8

 电解电容

 10UF

 2个

 9

 电阻

 10K

 1个

 10

 电阻

 100

 2个

 11

 排阻

 10K

 1个

 12

 晶振

 12MHz

 1个

 13

 两位共阴数码管

 1个

 14

 蜂鸣器

 1个

 15

 按键

 1个

 附录3

 程序源码

 #include<reg52.h>

 #define uchar unsigned char

 #define uint

 unsigned int

 sbit FM=P2^3;

 //定义蜂鸣器引脚

 uchar table[16] =

  {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//数码管显示编码

 uchar irtime,startflag,bitnum,irreceok,irprocok,shuaxin,n;

 uchar i,count;

 uchar irdata[33];

 //所有irtime

 uchar ircode[4];

  //解码后数据

 uchar disp[2];

 //送往数码管的数

 uchar qumu[2] ={0,1}; //曲目数组

 unsigned char code song[] ={

 //祝你平安

 0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,0x26,0x20,0x30,0x20,

 0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,0x26,0x20,0x20,0x20,0x20,0x20,0x1c,0x20,

 0x20,0x80,0x2b,0x20,0x26,0x20,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20,

 0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,0x39,0x10,0x26,0x20,

 0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10,

 0x2b,0x20,0x30,0x10,0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x20,

 0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,0x18,0x20,0x26,0x20,

 0x20,0x20,0x20,0x40,0x26,0x20,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20,

 0x20,0x80,0x1c,0x20,0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,0x10,

 0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,0x10,0x2b,0x10,0x2b,0x80,

 0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x60,0x26,0x10,0x2b,0x20,0x30,0x20,

 0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,0x20,

 0x39,0x20,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x10,0x40,0x10,0x20,0x10,

 0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x00,

 //八月桂花遍地开

 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};

 void delay_50us(uint t)

 //延时50微秒

 {

  uchar j;

  for(;t>0;t--)

  {

 for(j=19;j>0;j--);

  }

 }

 void delay_25us(uint t)

 //延时25微秒

 {

  uchar j;

  for(;t>0;t--)

  {

 for(j=3;j>0;j--);

  }

 }

 void timer0init(void)

 {

  TMOD=0x02;

 //定时器0

 定时方式2

 8位自动重装

  TH0=0x00;

 //初值为0

 实现定时256us

  TL0=0x00;

  ET0=1;

  //开定时器0中断

  EA=1;

  //开总中断

  TR0=1;

  //启动定时器0

 }

 void int1init(void)

 {

  IT1=1;

  //外部中断1负跳变沿有效

  EX1=1;

  //开外部中断1中断

  EA=1;

  //开总中断

 }

 void irproc(void)

  //解码函数

  {

  uchar k,value,m,j;

  k=1;

  for(j=0;j<4;j++)

 //4组二进制码

  {

  for(m=0;m<8;m++)

  //每组8位

 {

  value=value>>1;

  //由于低位在前,所以右移到正常顺序

  if(irdata[k]>6)

  //irtime大于6*256us

  则解码数据为1

  {

 value=value | 0x80; //解码数据为1

 则高位或1

 则高位置1

  }

  k++;

  //所有二进制码的位

 }

 ircode[j]=value;

  //每组解码后的值存入ircode

  }

  irprocok=1;

 //解码完成

 }

 void irwork(void)

  //把解码后的数据转成16进制的两位数

 {

 disp[0]=ircode[2]/16;

  //取出ircode中的两位“数据码”

  disp[1]=ircode[2]%16;

  //取出ircode中的两位“数据码”

 }

 void display(void)

  //数码管显示函数

 {

 P0=table[disp[0]];

  //P0口送数据

 P2=0x06;

  //数据管位选

 delay_50us(2);

 //显示数值保持100us

 P2=0x00;

  //关闭位选

 P0=table[disp[1]];

  //P0口送数据

 P2=0x07;

  //数据管位选

 delay_50us(2);

 //显示数值保持100us

 P2=0x00;

  //关闭位选

 }

 void play(uchar l)

  //音乐播放函数

 {

  uchar temp1,temp2;

  uint addr;

 //song[]播放位置

  count = 0;

 //中断计数清0

  addr = l * 217;

  while(1)

  {

 temp1 = song[addr++];

  if (temp1 == 0xFF)

 //休止符

  {

 TR0 = 0;

 //关闭定时器0

 delay_50us(100);

  }

  else if (temp1 == 0x00)

 //歌曲结束符

  {

 return;

  }

  else

  {

 temp2 = song[addr++];

 TR0 = 1;

 //启动定时器0

  while(1)

  {

 P0=table[disp[0]];

 //P0口送数据

 P2=0x06;

 //数据管位选

  FM = ~FM;

  delay_25us(temp1);

 P2=0x00;

 //关闭位选

  P0=table[disp[1]];

 //P0口送数据

 P2=0x07;

 //数据管位选

 delay_25us(temp1);

 P2=0x00;

 //关闭位选

  if(temp2 == count)

 //节拍

  {

 count = 0;

 break;

  }

 }

  }

 if(irreceok)

  //接收完成

 {

  irproc();

  //解码

  irreceok=0;

 }

 if(irprocok)

  //解码完成

 {

  irwork();

  //把解码后的数据转成16进制的两位数

  irprocok=0;

  if(ircode[2]==0x02&&shuaxin==1)

  //暂停

  {

 shuaxin=0;

 while(1)

 {

  if(irreceok)

  //接收完成

  {

 irproc();

  //解码

 irreceok=0;

  }

  if(irprocok)

  //解码完成

  {

 irwork();

  //把解码后的数据转成16进制的两位数

 irprocok=0;

  }

  display();

 //显示

  if(ircode[2]==0x06)

  //暂停后重新播放

  {

 shuaxin=0;

 break;

  }

  if(ircode[2]==0x0a&&shuaxin==1)

 //停止播放

  {

 shuaxin=0;

 return;

  }

  if(ircode[2]==0x17&&shuaxin==1)

  //曲目0

  {

 shuaxin=0;

 return;

  }

  if(ircode[2]==0x16&&shuaxin==1)

  //曲目1

  {

 shuaxin=0;

 return;

  }

  if(ircode[2]==0x07&&shuaxin==1)

 //播放上一曲

  {

 if(l==0)

  //当前播放曲目0

 {

  shuaxin=0;

  n=1;

  return;

  //返回主函数播放qumu[n]

 }

 else

 //当前播放曲目1

 {

  shuaxin=0;

  n=0;

  return;

  //返回主函数播放qumu[n]

 }

  }

  if(ircode[2]==0x05&&shuaxin==1)

  //播放下一曲

  {

 if(l==0)

  //当前播放曲目0

 {

  shuaxin=0;

  n=1;

  return;

 //返回主函数播放qumu[n]

 }

 else

  //当前播放曲目1

 {

  shuaxin=0;

  n=0;

  return;

 //返回主函数播放qumu[n]

 }

 }

 }

  }

  if(ircode[2]==0x0a&&shuaxin==1)

  //停止

  {

 shuaxin=0;

 return;

  }

  if(ircode[2]==0x17&&shuaxin==1)

  //曲目0

  {

 shuaxin=0;

 return;

  }

  if(ircode[2]==0x16&&shuaxin==1)

  //曲目1

  {

 shuaxin=0;

 return;

  }

  if(ircode[2]==0x07&&shuaxin==1)

 //播放上一曲

  {

 if(l==0)

  //当前播放曲目0

 {

  shuaxin=0;

  n=1;

  return;

  //返回主函数播放qumu[n]

 }

 else

 //当前播放曲目1

 {

  shuaxin=0;

  n=0;

  return;

  //返回主函数播放qumu[n]

 }

  }

  if(ircode[2]==0x05&&shuaxin==1)

  //播放下一曲

  {

 if(l==0)

  //当前播放曲目0

 {

  shuaxin=0;

  n=1;

  return;

  //返回主函数播放qumu[n]

 }

 else

 //当前播放曲目1

 {

  shuaxin=0;

  n=0;

  return;

  //返回主函数播放qumu[n]

 }

 }

 }

  }

 }

 void main()

 {

  timer0init();

 //定时器初始化

  int1init();

  //外部中断初始化

  while(1)

  {

 if(irreceok)

  //接收完成

 {

  irproc();

  //解码

  irreceok=0;

 }

 if(irprocok)

  //解码完成

 {

  irwork();

  //把解码后的数据转成16进制的两位数

  irprocok=0;

 }

 display();

 //显示

  if(ircode[2]==0x06)

 //播放歌曲

 {

 shuaxin=0;

  play(qumu[0]);

 }

 if(ircode[2]==0x17)

 //播放曲目0

 {

  shuaxin=0;

  play(qumu[0]);

  }

 if(ircode[2]==0x16)

 //播放曲目1

 {

  shuaxin=0;

  play(qumu[1]);

  }

 if(ircode[2]==0x07)

 //上一曲

 {

  shuaxin=0;

  play(qumu[n]);

 }

 if(ircode[2]==0x05)

 //下一曲

 {

  shuaxin=0;

  play(qumu[n]);

 }

  }

 }

 void timer0() interrupt 1

 {

  irtime++;

  i++;

  if(i==39)

  //39*256us=10ms

  {

 i=0;

 count++;

 //蜂鸣器节拍

  }

 }

 void int1() interrupt 2

 {

  if(startflag==1)

  {

 if(irtime>32)

 //检测9ms引导码

 {

  bitnum=0;

  }

 irdata[bitnum]=irtime;

 irtime=0;

 bitnum++;

 if(bitnum==33)

 //接收结束

 {

 bitnum=0;

  irreceok=1;

 //接收完成

 }

  }

  else

  {

 startflag=1;

 //接收开始标志位

 irtime=0;

  }

  shuaxin=1;

 }

 致

 谢

 本次单片机课程设计是在XX老师的指导和要求下完成的,每一个电路的设计步骤和程序设计过程都有老师的细心教导,同时也有同学们的各种帮助。所以课程设计要感谢老师的精心指导,让我受益匪浅,也感谢同学们对我的帮助。在此向老师表示深深的感谢和崇高的敬意。

推荐访问:播放器 单片机 遥控
上一篇:在组织干部人事档案工作培训班上的发言:干部人事档案意义
下一篇:[290人力资源管理案例] 人力资源管理案例简短

Copyright @ 2013 - 2018 优秀啊教育网 All Rights Reserved

优秀啊教育网 版权所有