自动控制升降旗装置课程设计报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
湖南人文科技学院
课程设计报告课程名称:单片机原理及应用课程设计
设计题目:自动控制升降旗装置
系别:通信与控制工程系
专业:通信工程
摘要
本系统采用单片机STC89C52作为自动控制升降旗系统的检测和控制核心,采用由单片机控制的步进电机带动国旗升降,实现对国旗升降的自动控制。
该电路主要由电机驱动控制模块、键盘与显示模块及语音模块几个部分组成。
电机驱动控制模块采用集成驱动芯片ULN2003L,采用键盘作为输入控制和数码管作为输出显示,语音模块采用报警蜂鸣器(LS)电路。
关键字:步进电机;自动控制;语音;数码管显示;按键
目录
设计要求 (1)
1 方案选择与论证 (1)
1.1电机的选择与论证 (1)
1.2 电机驱动方案的选择与论证 (2)
2 自动控制升降旗整体电路设计 (2)
2.1整体电路原理 (2)
3 单元电路设计 (3)
3.1 步进电机电路的设计 (3)
3.2 数码管显示电路的设计 (4)
3.3 音乐发声电路的设计 (5)
3.4 矩阵4X4键盘电路的设计 (6)
3.5 外部ROM存储器电路设计 (7)
4 自动控制升旗装置软件设计 (8)
4.1 系统总程序流程图 (8)
4.2 步进电机转动的软件设计 (9)
4.3 数码管实时显示的软件设计 (10)
4.4 国歌音乐的软件设计 (10)
4.5 矩阵键盘实时控制软件设计 (11)
4.6 外部ROM实时访问的软件设计 (12)
5 详细仪器清单 (13)
6 总结与思考及致谢 (14)
参考文献 (15)
附录一:系统程序代码 (16)
附录二:总原理图 (27)
自动控制升降旗装置
设计要求
基本部分:
1).按下上升按键后,旗帜匀速上升,同时流畅地播放歌曲,上升到最高端时
自动停止上升,歌曲停奏;按下下降按键后,旗帜匀速下降,降旗的时间不放歌曲,下降到最低端时自动停止;
2).旗帜在最高端,上升按键不起作用;在最低端时,下降按键不起作用;
3).升降旗的时间均为43秒,与国歌的演奏时间相等;
4).即时显示旗帜所在的高度,以CM为单位,误差不大于2CM。
发挥部分:
1). 重新合上电源后,所显示的旗帜高度数据不变;
2). 要求升降旗的速度可调整,调整范围是30—120秒钟,步进1秒(除43
秒
外,其他时间可与国歌不同步);
3). 在最高升降速度下(以自选的电机参数定),能在指定的位置上自动停止,定位误差≤±2CM。
1 方案选择与论证
1.1电机的选择与论证
方案一:采用普通的直流电机。
普通直流电动机具有优良的调速特性,调速平滑、方便,调整范围广,过载能力强,能承受频繁的冲击负载,可实现频繁的无级快速启动、制动和反转。
方案二:采用步进电机。
步进电机是纯粹的数字控制电动机,它将电脉冲转化为角位移,即一脉冲,电机就转动一角度,因此很适合单片机控制。
步进电机的一个显著特点是具有快速的启停能力,如果负荷不超过步进电机所能提供的动态转矩值,就能够立即使步进电机启动或反转。
另一个显著特点是转换精度高,可以通过步数实
现精确定位,可正转反转控制灵活。
综上所述,我们选用方案二。
1.2 电机驱动方案的选择与论证
方案一:采用继电器对电动机的开或关进行控制,通过控制开关的切换速度实现对电机的运行速度进行调整。
这个电路的优点是电路结构简单,其缺点是继电器的响应时间长,易损环,寿命短,耗电流,不能很好的驱动步进电机,可靠性不是很高。
方案二:采用由达林顿管组成的H桥型PWM电路。
用单片机控制达林顿管使之工作在占空比可调的开关状态,可精确调整电动机的运动状态(前进,后退,左转,右转)。
这种电路由于工作在管子的饱和截至模式下,效率很高。
H桥电路保证了可以简单的实现转速和方向的控制,但不能很精确的控制步距和速度。
方案三:采用ULN2003驱动。
ULN2003 是高耐压、大电流达林顿陈列,由七个硅NPN 达林顿管组成,具有电流增益高、工作电压高、温度范围宽、带负载能力强等特点,适应于各类要求高速大功率驱动的系统。
所以综上所述我们采用方案三。
2 自动控制升降旗整体电路设计
2.1整体电路原理
系统整体电路原理框图如图1所示:
图1总体电路框图
3 单元电路设计
3.1 步进电机电路的设计
根据设计要求,我们采用了步进电机的准确步进来控制旗杆的升降,电路图如图3所示:
图 3 步进电机原理图
步进电机是数字控制电机,不同于直流电机。
它将脉冲信号转变为角位移,即给一个脉冲信号,步进电机就转动一个角度,非常适合单片机控制。
工作原理如下:
(1)控制换相顺序
通电换相这一过程称为脉冲分配。
例如:三相步进电机的六拍工作方式,其各相通电顺序为A-AB-B-BC-C-CA-A,通电控制脉冲必须严格按照这一顺序分别控制A,B,C各相得通断。
(2)控制步进电机的转向
如果给定工作方式正序换相通电,电机正转,如果按反序通电换相,电机就反转。
(3)控制步进电机的速度
如果给步进电机发一个控制脉冲,它就转一步,再发一个脉冲,它就会再转一步。
两步脉冲的时间间隔越短,步进电机就转的越快。
调整单片机发出的脉冲频率,就可以对步进电机进行调速。
步进电机步序表如表1所示:
表1 步进电机步序表
如果按步序1-->步序8输出数据,步进电机正转,按步序8—>步序一输出数据,步进电机反转。
3.2 数码管显示电路的设计
由于要求升降过程中即时显示所在高度,故采用四位数码管即可显示出来。
本试验所采用的开发板上有一排六位的数码管,每个数码管的8段是由芯片8255得PB口控制亮灭,即可得到所要显示的数字,每个数码管的公共脚分别由8255的PA0—PA5经三极管扩流后进行控制,原理图如图4所示:
图 4 数码管显示电路原理图
要在某位数码管上显示一个数字,首先把待显示数字的显示码送给8255的PB 口,接着选中要显示的位。
例如:要在开发板的最左边的数码上显示一个‘0’,则需要先把‘0’得显示码0xc0送8255得PB口,接着PA0赋‘0’(低电平),随后让单片机保持这个值不变。
3.3 音乐发声电路的设计
为了在升旗得过程中同步放出国歌的音乐,本实验采取蜂鸣器来奏响国歌。
单片机的P33引脚用来控制蜂鸣器的工作,当P33输出高电平时,蜂鸣器不工作。
当P33引脚输出低电平时,三极管导通,蜂鸣器工作,同时二极管发光。
蜂鸣器音乐电路如图5示:
图 5 音乐发声电路
3.4 矩阵4X4键盘电路的设计
本实验中用来控制的功能比较多,故采取按键控制的方法来实现控制功能。
电路如图6示:
图 6 矩阵4X4键盘电路
矩阵式键盘的按钮识别办法可以确定矩阵式键盘上何键被按下,采用的方法之一为“行扫描法”。
行扫描法又称为逐行(或列)扫描查询法,是一种最常见的按钮识别方法,键盘如上所示。
具体实现过程如下:判断键盘中有无键按下。
将全部行线置低电平,然后检测列线的状态。
只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键低于低电平线与4根行线交叉的4个按钮之中。
若所有列线均为高电平,则按键中无键按下。
判断闭合键所在的位置:在确认有键按下的情况下,即可进入确定具体键的过程。
操作是:依次将行线置为低电平,即在置某根行线为低电平时,其他线为高电平。
在确定某根行线为低电平后,再逐行检测各列线的电平状态。
若某列为低,则该线与置为低电平的行线交叉处的按钮就是闭合的按钮。
3.5 外部ROM存储器电路设计
由于设计要求要掉电后将数据保存,即重开电源后单片机要从上次掉电前得状态继续执行,故采取I2C总线形式挂载外部程序存储器来存储掉电前得数据。
原理图如图7所示:
图7 外部ROM存储器电路
I2C总线是一种用于IC器件之间连接的二进制总线。
它通过SDA(串行数据线)及SCL(串行时钟线)两根线在连到总线上的器件之间传送信息,并根据地址识别每个器件:不管是单片机、存储器、LCD驱动器还是键盘接口。
AT24C08是低功耗的CMOS串行EEPROM,内含256*8位存储空间,工作电压宽,擦写次数多,写入速度快等特点。
本设计中24C08的1、2、3脚是三条地址线,用于确定芯片的硬件地址。
在开发板上均接地,第8脚和第4脚分别接正、负
电源。
第5脚SDA为串行数据输入输出,数据通过这条I2C总线串行传送,与单片机的P27连接。
第6脚SCL为串行时钟输入线与单片机的P26连接。
SDA与SCL 都需要和正电源间各接一个2K的上拉电阻。
第7脚需接地。
4 自动控制升旗装置软件设计
4.1 系统总程序流程图
系统工作总程序流程图如图8所示:
图8 整体程序流程图
步进电机是一种将电脉冲转化为角位移的执行机构。
当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(及步进角)。
可以通过控制脉冲个数来控制角位移量,从而达到准确定位的目的;同时也可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。
其工作流程图如图9所示:
图9 步进电机程序流程图
此次设计中,采用的为四相八拍的步进电机控制方式。
代码中,先定义了要用到的步进电机正转和反转的时序数组,以使后面的程序能够随时更改电机接收到的脉冲时序,以达到实时地控制电机的正转和反转,从而实现旗帜的上升与下降。
更改脉冲时序的条件由所按下的键盘按键决定,所以可以实时地更改脉冲的时序,达到实时地控制电机转动方式。
数码管显示的部分硬件上是通过8255扩展I/O芯片实现控制,且采用的为动态数码管显示的方法,也就是六要数码管共用的为一个八位数据线。
上面函数的功能为在指定的数码管上显示指定的数字。
实际中要显示的数字不只有一位,所以必须在人的视觉停留的时间内,即1/12秒的时间内,把所有要显示的数码管全部点亮,才能给人感觉像是所有数码管同一时刻全部点亮了。
数码管工作流程图如图10所示:
图10 数码管子程序流程图
4.4 国歌音乐的软件设计
音乐功能主要在两个中断中完成;定时器0中断主要输出一定频率的方波,定时器1中断完成音长的控制,在完成特定音符的音长后读取下一个音符,并且更新定时器0的初始设置值。
演奏时,要根据音符的不同把对应半周期的定时时间初始值送入定时器T0,再由定时器T1按时输出高低电平,定时器控制音乐程序流
程图如图11所示:
图11 定时器T0、T1控制音乐子程序流程图
4.5 矩阵键盘实时控制软件设计
本次设计采用的为4X4矩阵键盘,这种键盘是由16个按键组成的开关矩阵。
其程序流程图如图12所示,程序中用来识别用户按下的按键采用的方式为动态扫描的方式,即分别对矩阵进行行扫描,再进行列扫描即可得到识别按键所需的两个坐标值,在程序中定义全局变量test_x,test_y用来存储键盘扫描得到的值。
个体的程序设计中,因为实时控制电机的转动,音乐的开关均以用户按下的按键为基准,故程序中多次要用到键盘扫描,所以将键盘扫描程序抽象出来形成一个单独的函数scanKeyboard(),提高编码效率。
图12 键盘程序流程图
4.6 外部ROM实时访问的软件设计
因为RAM存储器的掉电易失性,而要达到掉电保存数据的效果,就必须将要保存的数据写到ROM中。
本次设计中,采用外部程序存储器24C08,采用的通讯协议为I2C串行总线方式,外部ROM程序流程图如图13所示。
具体的程序设计中,将主要对存储器的操作抽象为两个函数以供调用,即存储器写函数Write24c02(uint ch,uchar address),功能为每一次写一字节到指定的存储器地址上,存储器读函数Read24c02(uchar address),功能为读出指定地址上的一个字节。
图13 外部ROM程序流程图5 详细仪器清单
表格 1 仪器清单
6 总结与思考及致谢
本系统采用单片机STC89C52作为自动控制升降旗系统的检测和控制核心,采用由单片机控制的步进电机带动国旗升降,通过用按生键来实现对国旗升降的自动控制,最终与实践相结合的升降旗系统,实现单片机与人们活的密切应用。
做本设计,深刻的体会到,要把各功能模块搞懂才能达到各硬件的融合,达到硬件和软件的结合。
软件设计中,由于汇编的繁琐性,本系统采用C来编写程序,其实C是每一条语句可转化为汇编,汇编是更接近硬件的语言,写汇编可以对单片机的实际操作有更好的理解,故有时间可以尝试写“双语”。
感谢学校能给我们这次机会,让我们有一个发挥自己的平台,让我们把从课本学到的知识用到实际生活当中,从中得到锻炼。
在系统设计过程中,刘老师、方老师、谭老师、周老师等提出了许多宝贵的意见,在此深表感谢!同时得到了在校老师和同学们的支持与帮助,在此表示感谢!
参考文献
[1] 朱定华,戴汝平.单片微机原理与应用(M).北京:清华大学出版社.2003
[2] 张鑫.单片机原理及应用(M).电子工业出版社.2009
[3] 彭秀华.单片机高级语言c51Windows环境编程与应用(M).电子工业出版社 2001
[4] 全国大学生电子设计竞赛组委会.全国大学生电子设计竞赛获奖作品选编(M).北京:理工大
学出版社.2003年
[5] 彭为.单片机典型系统设计实例精讲(M).电子工业出版社.2005
[6] 沈庆阳.8051单片机实践与应用(M).清华大学出版社.2002
[7] 张立科.单片机典型模块设计实例导航(M).北京:人民邮电出版社.2004
[8] 陈涛.单片机应用及c51程序设计(M).机械工业出版社.2007
附录一:系统程序代码
#include <config.h>
#include <reg52.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
uchar code FFW[8]={0x75,0x65,0x6d,0x4d,0x5d,0x1d,0x3d,0x35};//步进电机正转数组
uchar code REV[8]={0x35,0x3d,0x1d,0x5d,0x4d,0x6d,0x65,0x75};//步进电机反转数组
//setflag用标志定位是否有效test_x,test_y用于定义16个按键中的任一个
uchar test_x=10,test_y=10,setflag=0;
uchar setfalse=0;
uint counter=0;//用于定义每隔多少个脉冲数码管上数字自增
//定义四个变量分别存储四个要显示的数位的值four显最高位第四位的值,依此类推
uint sum=0,four=0,three=0,two=0,one=0;
uint four_max=0,three_max=0,two_max=0,one_max=0;//定义四个变量,用来定位停止//音乐模块用到的些定义常量,变量,数组
unsigned char volatile FlagBeat;//基本节拍单位计数变量
unsigned int volatile FreqTemp;
unsigned char volatile music_temp; //暂时存放从MusicTable数组中读出的变量unsigned char volatile beat;
unsigned char volatile freq;//简谱码对应T值数组的下标
unsigned char volatile *pmusic;
sbit Pin_Buzzer=P3^3;
//串行外存定义的量
#define WriteDeviceAddress 0xa0//定义器件在IIC总线中的地址
#define ReadDviceAddress 0xa1
sbit SCL=P2^6;
sbit SDA=P2^7;
unsigned char x1,x2,x3;
unsigned int code FreqTab[]={ //简谱对应的简谱码、T值
65535,63628,63835,64021,64103,64260,64400,64524,64580,64684,64777,64820,64
898,64968,65030};
unsigned char code MusicTable[]={//音符节拍码
0x52,0x84,0x02,0x82,0x82,0x01,0x81,0x52,0x61,0x71,0x84,0x84,0xa2,0x82,0x91, 0xa1,0xc2,0x01,0xc1,0xc4,0xa2,0x01,0xa1,0x82,0x01,0xa1,0xc2,0x01,0xa1,0x94,0x94, 0x04,0xd4,0xc4,0x94,0xa4,0xc2,0xa4,0xc2,0xa2,0x91,0xa1,0x82,0x01,0x91,0xa4,0xc2, 0x01,0x61,0x82,0xa2,0x01,0xa1,0xc2,0x01,0xc1,0x92,0x92,0x92,0x62,0x01,0x61,0x94, 0x02,0x52,0x84,0x02,0x82,0xa4,0x02,0xa2,0xc4,0x04,0xc4,0x04,0x82,0x01,0xa1,0xc2, 0x01,0xc1,0xd4,0xc4,0xa2,0x01,0x81,0xc2,0xc2,0xc2,0xa2,0x82,0x54,0x84,0x32,0x01, 0x81,0xc2,0xc2,0xc2,0xa2,0x82,0x54,0x84,0x54,0x84,0x54,0x84,0x84,};
unsigned char const dis_table[16]={
0xA0, /*0*/
0xBB, /*1*/
0x62, /*2*/
0x2A, /*3 */
0x39, /*4*/
0x2C, /*5 */
0x24, /*6*/
0xBA, /*7*/
0x20, /*8*/
0x28, /*9 */};
void DelayMs(unsigned int number) {
unsigned char temp;
for(;number!=0;number--) {
for(temp=112;temp!=0;temp--) ;}}
//开始总线
void Start() {SDA=1;SCL=1;SDA=0;SCL=0;}
//结束总线
void Stop() {SCL=0;SDA=0;SCL=1;SDA=1;}
//发ACK0
void NoAck() {SDA=1;SCL=1;SCL=0;}
//测试ACK
bit TestAck() {bit ErrorBit;SDA=1;SCL=1;ErrorBit=SDA;SCL=0;return(ErrorBit);}
//写入8个bit到24c08
Write8Bit(unsigned int input) {
unsigned char temp;
for(temp=8;temp!=0;temp--) {
SDA=(bit)(input&0x80);
SCL=1;
SCL=0;
input=input<<1;}}
//写入一个字节到24c08中
void Write24c02(uint ch,uchar address) {
Start();
Write8Bit(WriteDeviceAddress);
TestAck();
Write8Bit(address);
TestAck();
Write8Bit(ch);
TestAck();
Stop();
DelayMs(10);}
//从24c08中读出8个bit
uchar Read8Bit() {
unsigned char temp,rbyte=0;
for(temp=8;temp!=0;temp--) {
SCL=1;
rbyte=rbyte<<1;
rbyte=rbyte|((unsigned char)(SDA));
SCL=0;}
return(rbyte);}
//从24c08中读出1个字节
uchar Read24c02(uchar address) {
uchar ch;
Start();
Write8Bit(WriteDeviceAddress);
TestAck();
Write8Bit(address);
TestAck();
Start();
Write8Bit(ReadDviceAddress);
TestAck();
ch=Read8Bit();
NoAck();
Stop();
return(ch);}
void delay(){//延时主要用于控制display函数执行速度,以及电机的转带uint i = 0;
for(i = 0; i<20;i++);
}
void delaytest(){//延时主要用作按键消抖作用。
uint i = 0;
for(i = 0; i<25000;i++);}
//动态扫描4X4键盘,不停的扫描则可以确实按下的为哪一个按键。
void scanKeyboard(){
uint i,j,PC_data = 0;
a8255_CON=0x89;
a8255_PB=0xff;
a8255_PA=0xff;
delay();
PC_data=a8255_PC;
for(j = 0;j<4;j++){
if((PC_data&(1<<j)) == (1<<j)){
for(i = 0;i<4;i++) {
a8255_PA=1<<i;
delay();
PC_data=a8255_PC;
if((PC_data&(1<<j)) == (1<<j)){
test_x = i;
test_y = j;
break;}}}}}
//定时器,音乐模块的一些初始化
void initial(){
pmusic=MusicTable;
beat=1;
FlagBeat=0;
TMOD=0x11;//定时器0,1都工作16位计数方式
ET0=1; //允许定时器0溢出中断;
ET1=1; //允许定时器1溢出中断
EA=1;
TL1=0xF0;
TH1=0xFF;
TR1=1;
IT0=1; //外中断跳变产生中断
EX0=1;}
//数码管显示方法,在指定的place位置显示num数字。
void display(uchar place,uint num){
uchar i = 0,display_num = 0;
uint test = 0;
a8255_CON=0x89;
a8255_PB=0xff;
a8255_PA=0xff;
delay();
if(place == 1) test = ~(0x1<<0);
else if(place == 2) test = ~(0x1<<1);
else if(place == 3) test = ~(0x1<<2);
else if(place == 4) test = ~(0x1<<3);
else if(place == 5) test = ~(0x1<<4);
else if(place == 6) test = ~(0x1<<5);
a8255_PA=test;
if(num == 0) display_num = dis_table[0];
else if(num == 1) display_num = dis_table[1];
else if(num == 2) display_num = dis_table[2];
else if(num == 3) display_num = dis_table[3];
else if(num == 4) display_num = dis_table[4];
else if(num== 5) display_num = dis_table[5];
else if(num == 6) display_num = dis_table[6];
else if(num == 7) display_num = dis_table[7];
else if(num == 8) display_num = dis_table[8];
else if(num == 9) display_num = dis_table[9];
a8255_PB=display_num;
delay();}
//主函数入口,主要用来组合音乐,电机,显示模块以及通过按键实时的控制步进机,音乐播放
void main(void){
//用于掉电保存的数据,每次开机时,用于加载掉电前的数据
uint stoNum=Read24c02(0x04);
four_max=stoNum/100;
three_max=stoNum/10%10;
two_max=stoNum%10;
four=four_max;
three=three_max;
two=two_max;
one=one_max;
while(1){
//设定初始位置值,电机转到指定的位置停止
while(1){
scanKeyboard();//每次调用延时,以消除键盘抖动。
if(test_x==0&&test_y==3){delaytest();test_x=0,test_y=1;four_max =
++four_max%2;setfalse=1;}
if(test_x==1&&test_y==3){delaytest();three_max=++three_max%6;
test_x=0,test_y=1;setfalse=1;}
if(test_x==2&&test_y==3){delaytest();two_max=
++two_max%10;test_x=0,test_y=1;setfalse=1;}
if(test_x==3&&test_y==3){delaytest();one_max=
++one_max%10;test_x=0,test_y=1;setfalse=1;}
display(1,four_max);
display(2,three_max);
display(3,two_max);
display(4,one_max);
if(test_x==0&&test_y==0){break;}
if(test_x==1&&test_y==0){break;} }
if(four_max!=0||three_max!=0||two_max!=0||one_max!=0)setflag=1;
if( (test_x==0&&test_y==0) || (test_x==1&&test_y==0) ){
initial();
while(1){
uint i;
scanKeyboard();
for(i=0;i<8;i++){
if(test_x==0&&test_y==0)
P1 = FFW[i];//正转
else if(test_x==1&&test_y==0)
P1 = REV[i]; //反转
if(test_x==0&&test_y==0){//如果为上升则,显示管四个数位依次累加if(counter= =15){
one++;if(one= =10){ two++;one=0;
if(two= =10){ two=0; three++;
if(three= =10){ three=0; four++;
if(four= =10)four=0; }}}
counter=0;}}
else if(test_x= =1&&test_y= =0){//如果为下降,则数码管四个数位依次递减EA=0;
if(counter= =15){
if(one!=0)one--;
if(one= =0&&(two!=0||three!=0||four!=0)){one=9;if(two!=0)two--;}
if(two= =0&&(three!=0||four!=0)){two=9;if(three!=0)three--;}
if(three= =0&&four!=0){three=9;if(four!=0)four--;}
if(four= =0)four=0;
counter=0;}}
//达到1500处,电机停止,声音停止
if(four= =1&&three= =5&&two= =0){ uint stoNum=four*100+three*10+two;
Write24c02(stoNum,0x04);
while(1){
display(1,1);
display(2,5);
display(3,0);
display(4,0);
scanKeyboard();
EA=0;
if(test_x= =1&&test_y= =0)break;}}
//达到0000处,则电机停止
if(four= =0&&three= =0&&two= =0){
uint stoNum=four*100+three*10+two;
Write24c02(stoNum,0x04);
while(1){
display(1,0);
display(2,0);
display(3,0);
display(4,0);
scanKeyboard();
EA=0;
if(test_x= =0&&test_y= =0){EA=1;break;}}
//自动定位到指定位置
if(four= =four_max&&three= =three_max&&two= =two_max&&setflag&&setfalse){ uint stoNum=four*100+three*10+two;
Write24c02(stoNum,0x04);
while(1){
display(1,four_max);
display(2,three_max);
display(3,two_max);
display(4,one_max);
EA=0;
scanKeyboard();
if(test_x= =0&&test_y= =2){
delaytest();setflag=0;test_x=0;test_y=0;EA=1;
break; }}}
display(1,four);
display(2,three);
display(3,two);
display(4,one);
counter++; } } } } }
//定时器中断两个用来做声音模块。
void timer0() interrupt 1 using 0{
TR0=0;
TL0= FreqTemp;
TH0= FreqTemp>>8;
TR0=1;
Pin_Buzzer=~Pin_Buzzer;
}
void timer1() interrupt 3 using 1{
FlagBeat++;
TR1=0;
TL1=0x68;
TH1=0x48;
TR1=1;
if(*pmusic= =0x00)pmusic=MusicTable;{ if(FlagBeat= =beat) {
FlagBeat=0;
music_temp=*pmusic;
beat= music_temp&0x0F; //取得节拍数
beat=beat*4;
freq =music_temp>>4; //取得音符编码
pmusic++;
if(freq==0)TR0=0;
else {
TR0=0;
FreqTemp=FreqTab[freq];
TL0= FreqTemp;
TH0= FreqTemp>>8;
TR0=1; } } } }
附录二:总原理图。