HUBEI NORMAL UNIVERSITY
单片机 课程
设计
领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计
MCU Curriculum Design
所在院系
教育信息与技术学院
专业名称
电子信息
工程
路基工程安全技术交底工程项目施工成本控制工程量增项单年度零星工程技术标正投影法基本原理
班级
1005
题目
音乐倒数计数器
指导教师
梁赫西
成员
刘杨
完成时间
2012.12.28
一、设计任务及要求:
设计任务:
利用数字AT89C51单片机实现倒数计数器的功能。
要 求:
⑴ 字符型LCD(16×2)显示器,显示格式为“TIME 分分:秒秒”。
⑵ 用4个按键操作来设置当前想要倒计数的时间。
⑶ 一旦按下键则开始倒计数,当计数为0时,发出一阵音乐声。
⑷ 程序执行后工作指示灯LCD闪动。
指导教师签名:
2012年12月30日
二、指导教师评语:
指导教师签名:
2012 年12月 30 日
三、成绩
验收盖章
2012年12月30 日
音乐倒数计数器的设计
摘要:随着人们生活水平的不断提高,单片机控制无疑是人们追求的目标之一,它给人带来的方便也是不可置否的,人们对它的要求越来越高,要为现代人工作、科研、生活、提供更好的更方便的设施就需要从单片机技术入手,一切向着数字化控制,智能化控制方向发展。
本设计利用AT89C51单片机结合字符型LCD显示器设计一个简易的倒数计数器,可用来煮方便面、煮开水或小睡片刻等。做一小段时间倒计数,当倒计数为0时,则发出一段音乐声响,通知倒计数终了,该做应当做的事。
关键词:单片机 ; AT89C51;倒数计数器,音乐, proteus。
1.设计要求与思路
1.1设计要求
利用数字AT89C51单片机实现倒数计数器的功能,设定时间后在LED数码管上显示相应的时间。其功能和性能指标如下:
⑴ 字符型LCD(16×2)显示器,显示格式为“TIME 分分:秒秒”。
⑵ 用4个按键操作来设置当前想要倒计数的时间。
⑶ 一旦按下键则开始倒计数,当计数为0时,发出一阵音乐声。
⑷ 程序执行后工作指示灯LCD闪动,
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
示程序开始执行,按下操作键K1~K4动作如下:
● K1---可调整倒计数的时间1~60分钟。
● K2---设置倒计数的时间为5分钟,显示“0500”。
● K3---设置倒计数的时间为10分钟,显示“1000”。
● K4--设置倒计数的时间为20分钟,显示“2000”
⑸ 复位后LCD的画面应能显示倒计时的分钟和秒数,此时按K1键,则在LCD上显示出设置画面。此时,若:
● 按K2键---增加倒计数的时间1分钟。
● 按K2键---减少倒计数的时间1分钟。
● 按K4键---设置完成。
1.2设计思路
音乐倒数计数器所倒数的时间由数字显示,控制器使用单片机AT89C51。本设计基于单片机技术原理,以单片机芯片AT89C51作为核心控制器,通过硬件电路的制作以及软件程序的编制,设计制作出一个计数器,包括以下功能:输出时间,按下键就开始计时,并将时间显示在LCD1602显示器上。当倒计数为0时,蜂鸣器就发出音乐声响等等。该计数器系统主要由计数器模块、LCD显示器模块、蜂鸣器模块、键盘模块、复位模块等部分组成。
本设计利用Keil uVision4作为编程软件进行源程序设计及调试,同时使用PROTEUS7.7进行硬件电路的搭建仿真。
2.1系统硬件设计
以AT89C52单片机作为主控制器,外加按键、复位电路、LCD显示和蜂鸣器组成
图2-1 总体设计方框图
2.2系统软件设计
主程序开始初始化,然后扫描键盘、复位电路和计数器。当键盘按键有按下时,调整计数器值,LCD显示新值。当复位键有按下时,计数器复位为初值,重新倒计数。当计数器值倒计为0时,蜂鸣器发出声音,计数器停止倒计,程序结束。
是
是 否
是
否
否
3.1硬件电路详细设计
3.1.1 AT89C51单片机
AT89C51是一个低电压,高性能CMOS 8位单片机,片内含8k bytes的可反复擦写的Flash只读程序存储器和128 bytes的随机存取数据存储器(RAM),器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容
标准
excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载
MCS-51指令系统,片内置通用8位中央处理器和Flash存储单元,AT89C51单片机在电子行业中有着广泛的应用。
图3-1 AT89C51单片机
3.1.2 LCD1602液晶显示电路设计与原理
工业字符型液晶,能够同时显示16x02即32个字符(16列2行)。1602字符型LCD通常有14条引脚线或16条引脚线的LCD,多出来的2条线是背光电源。VCC(15脚)和地线GND(16脚),其控制原理与14脚的LCD完全一样。1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。
图3-2 LCD1602液晶显
3.1.3复位电路
当MCS -5l系列单片机的复位引脚RST(全称RESET)出现2个机器周期以上的高电平时,单片机就执行复位操作。如果RST持续为高电平,单片机就处于循环复位状态。上电复位要求接通电源后,自动实现复位操作。当单片机已在运行当中时,按下复位键后松开,也能使RST为一段时间的高电平,从而实现上电或开关复位的操作。
图3-3 复位电路
3.1.4按键电路模块
按键用于控制数码显示、LCD显示、扬声器等模块的工作。通过扫描键盘来判断是否有按键按下,来设定各模块的工作情况,使各模块可以在按键的控制下,有序地进行工作。设计中使用单个按键实现单个功能,属于较为简单的控制方式。在多功能系统设计的试验中我们使用五个按键分别与单片机的p1.0、p1.1、p1.2、p1.3、p1.4相连。通过按下相应的按键来处理相应的程序。如下图:
图3-4 按键电路模块
3.1.5蜂鸣器
蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。蜂鸣器在电路中用字母“H”或“HA”表示。
单片机驱动他激蜂鸣器的方式有两种:一种是PWM 输出口直接驱动,另一种是利用I/O 定时翻转电平产生驱动波形对蜂鸣器进行驱动。比如为2500Hz 的蜂鸣器的驱动,可以知道周期为400μs,这样只需要驱动蜂鸣器的I/O 口每200μs 翻转一次电平就可以产生一个频率为2500Hz,占空比为1/2duty 的方波。如下图:
图3-5 蜂鸣器
3.2软件详细设计
解释一下按键代码的工作原理(以部分代码为例,其他按键类似):
if(key2==0)
{
delay(time); 延时,用于按键去抖;
if(key2==0)
{
flag0=0; 状态标志位:若flog0=0,则执行下面代码;
{
if(minute>0)
minute=minute-1;
write_time(7,minute);
}
if(second==0)
{
k=1;
second=60; 设置成60秒,也就是按一下加1min;
}
}
}
其实,难点不在按键问题上;而是如何蜂鸣器发音的问题上;
其计数值的求法如下:
T=65536-N=65536-Fi
2
Fr
例如:设K=65536,F=1000000=Fi=1MHz,球低音DO(261Hz)。中音DO(523Hz)。高音的DO(1046Hz)的计算值
T=65536-N=65536-Fi
2
Fr=6
2
Fr=6/Fr
低音DO的T=6/262=63627
低音DO的T=6/523=64580
低音DO的T=6/1047=65059
table1[]={64580,64684,64777,64820,64898,64968,65030};
这就是不同频率的,DO的发音,当然本设计中没有考虑这么复杂,而是直接最简单的do re mi fa so la si,这7种基本发音。
举例1:音调do,发音长度为两拍,即二分音符,将其编码为0x18。
举例2:音调re,发音长度为半拍,即八分音符,将其编码为0x22
4、系统仿真
图4-1 硬件图仿真
4.结论
经过这次的的课程设计,简单带有LCD显示的音乐倒数计数器基本完成,系统基本功能基本实现,测试运行也基本正常。
在实际的操作中,还是遇到了许多问题。例如:最小系统的有和无,对程序也没有影响;复位键的复位功能,不能实现;虽然在电路上搭建起来了。还有就是延时去抖,和不加延时去抖代码效果一样。所以这个系统还存在许多有待完善的地方。整个电路图的搭建并不难,主要是代码部分。所以,主要是代码部分,而代码部分可以用汇编和C语言来进行编写。本次设计主要是用C编写的,参考了网上的一部分代码。最后也完成了设计。主要是代码的理解,吃透代码与AT89S51相对应的各个部分代码的功能。
通过本次课程设计,我更深刻的认识到了教学实践在大学课程中的重要性,同时也发觉到了自己在学习方面存在的许多不足之处,在以后的学习中我会努力改进这些不足,不断提高自己的动手实践能力。
参考文献
[1]谭浩强.C程序设计[M].北京:清华大学出版社 2008
[2]郭天祥.51单片机C语言
教程
人力资源管理pdf成真迷上我教程下载西门子数控教程protel99se入门教程fi6130z安装使用教程
[M].北京:电子工业出版社 2011
[3]张毅刚.单片机原理及应用[M].北京:高等教育出版社 2011
附录:程序源代码
#include
#include
#define time 100
#define uint unsigned int
#define uchar unsigned char
uint t,flag,flag0,flag1,flag2,flag3,flag4,flag5,minute,second=60;
uchar num,j,i,k=0;
uchar code table[]="TIME 00:00";
uint code table1[]={64580,64684,64777,64820,64898,64968,65030};
sbit key1=P1^0;
sbit key2=P1^1;
sbit key3=P1^2;
sbit key4=P1^3;
sbit key5=P1^4;
sbit P1_5=P1^5;
sbit RS=P2^0;
sbit RW=P2^1;
sbit E=P2^2;
sbit led_red=P2^3;
void write_time(uint addr,uint date);
/////////延时函数///////
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
///////延时1S////////////
void delay1(void)
{
uchar a,b,c;
for(c=13;c>0;c--)
for(b=247;b>0;b--)
for(a=142;a>0;a--);
_nop_;
}
////////1602写命令函数//////
void write_com(uchar com)
{
RS=0;
P3=com;
delay(5);
E=1;
delay(10);
E=0;
}
//////1602写数据函数//////
void write_date(uchar date)
{
RS=1;
P3=date;
delay(5);
E=1;
delay(10);
E=0;
}
//////按键1处理函数///////
void KEY1()
{
while(flag1)
{
if(key2==0)
{
delay(time);
if(key2==0)
{
if(minute<=60)
minute=minute+1;
write_time(7,minute);
}
}
if(key3==0)
{
delay(time);
if(key3==0)
{
if(minute>0)
minute=minute-1;
write_time(7,minute);
}
}
if(key4==0||key5==0)
{
delay(150);
if(key4==0||key5==0)
{
flag1=0;
flag =1;
TR0=1;
}
}
}
}
//////按键2处理函数//////
void KEY2()
{
minute=5;
write_time(7,minute);
while(flag2)
{
if(key5==0)
{
delay(time);
if(key5==0)
{
flag2=0;
flag =1;
TR0=1;
}
}
}
}
//////按键3处理函数//////
void KEY3()
{
minute=10;
write_time(7,minute);
while(flag3)
{
if(key5==0)
{
delay(time);
if(key5==0)
{
flag3=0;
flag =1;
TR0=1;
}
}
}
}
//////按键4处理函数//////
void KEY4()
{
minute=20;
write_time(7,minute);
while(flag4)
{
if(key5==0)
{
delay(150);
if(key5==0)
{
flag4=0;
flag =1;
TR0=1;
}
}
}
}
void write_time(uint addr,uint date)
{
uint ge,shi;
ge=date%10;
shi=date/10;
write_com(0x80+addr);
write_date(0x30+shi);
write_date(0x30+ge);
if(addr==7&&date==0)
j=1;
if(j==1&&addr==10&&date==0)
{
flag0=1;
TR0=0;
TR1=1;
flag5=1;
}
}
//////初始化函数//////
void init()
{
P1=0xff;
RW=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x80);
TMOD=0x11;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TH1=0xfc;
TL1=0x44;
ET1=1;
ET0=1;
// TR1=1;
// TR0=1;
EA=1;
flag0=1;
for(num=0;num<12;num++)
{
write_date(table[num]);
delay(20);
}
}
void start()
{
if(key1==0)
{
delay(time);
if(key1==0)
{
flag0=0;
flag1=1;
KEY1();
}
}
if(key2==0)
{
delay(time);
if(key2==0)
{
flag0=0;
flag2=1;
KEY2();
}
}
if(key3==0)
{
delay(time);
if(key3==0)
{
flag0=0;
flag3=1;
KEY3();
}
}
if(key4==0)
{
delay(150);
if(key4==0)
{
flag0=0;
flag4=1;
KEY4();
}
}
}
void write_time0()
{
minute=minute-1;
write_time(7,minute);
write_time(10,59);
flag=0;
}
void counter()
{
if(t==20)
{
led_red=led_red^1;
if(flag==1)
write_time0();
t=0;
second=second-1;
write_time(10,second);
if(k==1&&second==59)
{
if(minute>0)
minute=minute-1;
write_time(7,minute);
}
if(second==0)
{
k=1;
second=60;
}
}
}
int main()
{
init();
while(1)
{
while(flag0)
start();
counter();
while(flag5)
{
delay1();
i++;
if(i>7)
i=0;
}
}
return 0;
}
void inter0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
t++;
}
void initer1() interrupt 3
{
TH1=table1[i]/256;
TL1=table1[i]%256;
P1_5=~P1_5;
if(key5==0)
{
delay(100);
if(key5==0)
{
TR1=0;
flag5=0;
k=0;
j=0;
}
}