㈠ 单片机数字钟毕业中期检查表中的一个问题
详细点???你问什么问题??
淮安信息职业技术学院
综合毕业实践说明书(论文)
2009-2010 学年
系 专业
摘要:数字电子时钟电路设计系统,以AT89C51单片机为控制核心,由键盘显示、定时闹铃、LED共阴极数码管和LED灯显示等功能模块组成。基于题目基本要求,本系统对时间显示和定时报警进行了重点设计。本系统大部分功能由软件来实现,吸收了硬件软件化的思想,大部分功能通过软件来实现,使电路简单明了,系统稳定性大大提高。本系统不仅成功的实现了要求的基本功能,而且有一定的创新功能。
关键字:单片机 AT89C51 共阴极LED数码显示器
Abstract This digital electronic clock circuit design system ,based on chip microcomputer AT89C51,is composed by the following functional moles : keyboard displaying , timing alarmg. common cathode LED digital tube,LED lights display,and so on.
According to the basic requirements of the subject ,the system stresses on the realization of Time display and regularly report to the police.
The design achieved all the required basic technical indexes. Furthermore , adopting the idea of hardware-to-software, most of those functions are realized by softwares, which makes the electrocircuit more concise and the system more stable.
Key words: chip microcomputer AT89C51
Common cathode LED digital display
目 录
一、 前言……………………………………………….. ….. ..1
二、 总体方案设计………………………………………..…..1
三、 系统硬件设计………………………………………..…..2
(1)输入部分……………………………………….. …….. ...2
1 电源模块……………………………………………………………….2
2 按键模块……………………………………………………………….5
(2)输出部分……………………………………….. .. ……...3
1 显示模块……………………………………………………………….3
2 闹铃模块……………………………………………………………….4
3 LED灯显示模块……………………………………………………….4
(3)电路相关参数……………………………………....……...4
1 LED数码显示器………………………………………………………..4
2 集成器件CD4511……………………………………………………….5
3 集成器件74LS138……………………………………………………. .5
四、 系统软件设计………………………………………..…..6
主程序流程图…………………………………………………………….7
五、 系统调试……………………………………………..…..9
1 系统功能……………………………………………………………….9
2 时钟精度分析………………………………………………………... .9
六、 系统设计总结………………………………………..…..9
七、 参考文献………………………………………….…... .10
附录……………………………………………………………11
1) 系统原理图……………………………………………......................................11
2) 系统PCB图……………………………………………................................... .12
3) 源程序…………………………………………………..................................... .13
一、前言
本文通过对一个能实现按键开关可调整时、分、秒,且具有加密功能、定时报警的24小时制的时间系统的设计学习,详细介绍了51单片机应用中的定时中断原理、数码管显示原理、动态扫描显示原理等,进一步学习、应用单片机C语言系统的实现了各种功能。从而使自身明白使用单片机汇编语言和C语言之间的效率、整体性问题。系统由AT89C51、独立式按键、二极管、LED数码管、蜂鸣器等部分构成,能实现24小时制时、分、秒的时钟显示,能实现时钟简单的加密功能。同时也可进行时、分、秒的校准、定时报警和LED二极管流水灯显示。
本系统主要是和实际生活的数字钟结合起来,可用1功能键进行加密,进入时间校准等。可用3个带有不同按键分别对时钟的时、分、秒进行校准。每个按键伴有不同的声响以示区别。
文章后附有本次课程设计系统电路原理图及源程序,以供读者参考。
二、总体方案设计
本次设计根据实验要求设计数字时钟。可利用如下两种方案实现。
方案一:本方案采用美国DALLAS公司的专用时钟芯片DS1302。该芯片主要特点是采用串行数据传输,可为掉电保护电源提供可编程的充电功能,并且可以关闭充电功能。其内部采用石英晶体振荡器,其芯片精度不大于10ms/年,且具有完备的时钟闹钟功能,因此,可直接对其以用于显示或设置,使得软件编程相对简单。为保证时钟在电网电压不足或突然掉电等突发情况下仍能正常工作,芯片内部包含锂电池。当电网电压不足或突然掉电时,系统自动转换到内部锂电池供电系统。而且即使系统不上电,程序不执行时,锂电池也能保证芯片的正常运行,以备随时提供正确的时间。
方案二:本方案完全用软件实现数字时钟。原理为:在单片机内部存储器设三个字节分别存放时钟的时、分、秒信息,并通过程序控制扫描输出显示数据。利用定时器0与软件结合实现1秒定时中断,每产生一次中断,存储器内相应的秒值加1;若秒值达到60,则将其清零,并将相应的分字节值加1;若分值达到60,则清零分字节,并将时字节值加1;若时值达到24,则将时字节清零。该方案具有硬件电路简单的特点,但当单片机不上电,程序将不执行。且由于每次执行程序时,定时器都要重新赋初值,所以该时钟精度不高。
鉴于以上两种方案,虽然时钟芯片DS1302具有更多的优点,由于实验硬件的因素,现有的硬件缺少DS1302,为不影响实验进度,本设计采用方案二完成数字时钟的功能。
根据题目要求设计的总体框图,如图1 — 1所示:
图1 — 1单片机数字钟硬件系统的总体设计框图
三、系统硬件设计
(1)、输入部分:
1.电源模块
方案一:采用干电池作为单片机数字钟的电源,由于调试时间较长,使用干电池需经常更换电池,不符合节约型社会的要求。并且需要有一个硬件将3节电池串联在一起以产生足够的电压,若如此,将造成携带不方便。
方案二:采用200W/5V直流稳压电源作为系统电源,不仅功率上可以满足系统需要,不需要更换电源,并且比较轻便,使用更加安全可靠。但稳压电源我们不能自备,若要调试系统,只能到实验室才能做。
方案三:采用普通的USB线连接微型计算机作为系统电源,虽然功率上可以满足稍大于系统需要,但同样不需要更换电源,并且比直流稳压电源更轻便,可随时使用、调试系统。
基于以上分析,由于本次设计系统都是软硬件想结合,所以要采用微机设备,有足够的USB接口供我们使用,所以我们决定采用方案三
2.按键模块
键盘是人与单片机打交道的主要设备,按键的读取容易引起误动作。可采用软件去抖动的方法处理,软件的触点在闭合和断开的时候会产生抖动,这时触点的逻辑电平是不稳定的,如不采取妥善处理的话,将引起按键命令错误或重复执行,在这里采用软件延时的方法来避开抖动,延时时间为20ms ( ).
方案一:采用独立式键盘。独立式按键是直接用I/O口线构成的单个按键电路,其特点是每个按键单独占用一根I/O口线,每个按键的工作不会影响其它I/O口线的状态。但当所需按键数量多,会占用过多的I/O口线。
方案二:采用矩阵键盘。因为单片机的I/O口有限, 显然,在按键数量较多时,矩阵式键盘较之独立式按键键盘要节省很多I/O口线。但必须将行线、列线信号配合起来作适当处理,才能确定闭合键的位置。
基于以上分析,我们选用方案一,因为本次设计中仅用到4个按键。独立式按键键盘有利于PCB的作图。
(2)、输出部分:
1、 显示模块
显示模块是本次单片机课程设计最核心的部分。
方案一:采用LCD1602。LCD1602为工业字符型液晶,能够同时显示16x02即32个字符。其采用标准的16脚接口,该液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,所以可分容易的实现数字钟数码显示。
方案二:采用LED共阴极数码管。共阴数码管在应用时将公共极COM接到地线GND上,当某一字段发光二极管的阳极为高电平时,相应字段就点亮。当某一字段的阳极为低电平时,相应字段就不亮。
基于以上分析,我们考虑到现实经济因素,所以选择了方案二。
对于6路共阴极数码管数码管要正常显示,就要用驱动电路来驱动数码管的各个段码,从而显示出我们要的数字,因此根据数码管的驱动方式的不同,可以分为静态式和动态式两类:
方案一:静态显示驱动。就是每一个数码管显示器都要占用单独的具有锁存功能的I/O接口用于笔划段字形代码。这样单片机只要把要显示的字形代码发送到接口电路,直到要显示新的数据时,再发送新的字形码,因此,使用这种办法单片机中CPU的占用较小。但对于静态显示方式,所需的数据锁存装置很多,引线多而复杂,且可靠性也较低。
方案二:动态显示驱动。通过单片机对数码管位选通COM端电路的控制,只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的的COM端,就使各个数码管轮流受控显示,这就是动态驱动。动态显示可以大幅度地降低硬件成本和电源的功耗,因为某一时刻只有一个数码管工作,也就是所谓的分时显示,故显示所需要的硬件电路可分时复用。动态显示方式,可以避免静态显示的问题。但设计上如果处理不当,易造成亮度低,闪烁问题。因此合理的设计既应保证驱动电路易实现,又要保证显示后的数据稳定,无闪烁。动态显示采用多路复用技术的动态扫描显示方式, 复用的程度不是无限增加的, 因为利用动态扫描显示使我们看到一幅稳定画面的实质是利用了人眼的暂留效应和发光二极管发光时间的长短, 发光的亮度等因素. 我们通过实验发现, 当扫描刷新频率(发光二极管的停闪频率) 为50Hz, 发光二极管导通时间≥1m s 时, 显示亮度较好, 无闪烁感.。
鉴于上述的方案分析, 我们采用方案二
2、闹铃模块
方案一:采用语音芯片ISD1110闹铃。ISD1110 具有多种采样率对应,多种录放时间,可以利用振荡电阻自已决定采样率。操作简单,灵活。音质好,适应电压范围广。可先对录放音设备录入一段音乐或其他报时方式,当到设定时间时,单片机控制录放音设备放音。
方案二:采用蜂鸣器闹铃,当到设定时间时,单片机向蜂鸣器送出低电平,蜂鸣器响铃。采用蜂鸣器闹铃结构简单,只需要单路信号控制,发出的闹铃声音可以根据响和不响的不同的软件延时时间来控制,当然也能发出音乐声音。
基于两种方案分析,虽然语音芯片ISD1110具备更多优点,但鉴于经济因素,我们本次设计还是决定采用方案二。当然如果在大型比赛的话,还是偏向于采用方案一的。
3、LED灯显示模块
采用LED灯可以方便的用不同的流水方式或单个LED灯来判断系统的工作状态,实现不同的显示功能,是一种经济又实用的方式。
(3)电路相关参数
1、LED数码显示器
通常用的七段数码显示器的内部有8个发光二极管,其中7个发光二极管组成了数字“8”,剩下一个发光二极管就是这位数字所带的小数点。数码管结构图如图1 - 2所示。各段码位与显示段的对应关系如表1。
图1 – 2 LED数码管结构引脚图
表1 各段码位的对应关系
段码位 D7 D6 D5 D4 D3 D2 D1 D0
显示段 dp g f e d c b a
2、集成器件CD4511
CD4511是一个用于驱动共阴极 LED (数码管)显示器的 BCD 码—七段码译码器,特点如下:
具有BCD转换、消隐和锁存控制、七段译码及驱动功能的CMOS电路能提供较大的拉电流。可直接驱动LED显示器。其引脚图如图1 — 3所示。
图 1 — 3 CD4511 引 脚 图
其功能介绍如下:
BI:4脚是消隐输入控制端,当BI=0 时,不管其它输入端状态如何,七段数码管均处于熄灭(消隐)状态,不显示数字。
LT:3脚是测试输入端,当BI=1,LT=0 时,译码输出全为1,不管输入 DCBA 状态如何,七段均发亮,显示“8”。它主要用来检测数码管是否损坏。
LE:锁定控制端,当LE=0时,允许译码输出。 LE=1时译码器是锁定保持状态,译码器输出被保持在LE=0时的数值。
A1、A2、A3、A4、为8421BCD码输入端。
a、b、c、d、e、f、g:为译码输出端,输出为高电平1有效。
3、集成器件74LS138
74LS138 为3 线-8 线译码器,本设计中74LS138做为对数码管位选通COM端电路的控制,将需要显示的数码管的选通控制打开。
图1 — 3 74LS138引脚图
74LS138工作原理如下:当一个选通端(G1)为高电平,另两个选通端( 和 )为低电平时,可将地址端(A、B、C)的二进制编码在一个对应的输出端以低电平译出。
四、系统软件设计
1、主程序流程图如图1 — 4所示:
图1 — 4 主程序流程图
2、定时器0子程序流程图如图1 — 5所示:
图1 — 5 定时器0子程序流程图
五、系统调试
1、系统功能
本系统已符合设计课程基本要求,即可以实现24小时方式;可用六位LED数码管显示时、分、秒;可使用按键开关可实现时、分调整。
除了满足这些基本要求外,本系统还做了一些创新:
(1) 通过1功能按键KEY1开关可使系统具有加密功能。加密前后可通过观察LED二极管的显示方式来判断。当LED做流水灯显示方式时,为加密前的状态;当只有LED灯中的LED2(由P0.1口控制亮灭)时,代表已对系统进行加密。
(2) 通过功能按键开关KEY1进入可进入时间校准系统。KEY2控制秒的校准,KEY3控制分的校准,KEY4控制时的校准。每次一有校准按键按下时,系统会发出不同的声响,以提示用户目前正在校准的是时、分、秒的哪一种。校准完成后仍然是通过功能按键KEY1返回时钟显示。
(3) 通过更改主程序中定时器的定时初值,可实现不同样式的数字钟显示方式。通过实验测得以下参数如表2所示(程序中定时参数CYCLE在以下简称C):
C (ms)
数码管显示方式 静态 闪烁 拉幕式
(1) 可实现整点闹鸣功能。整点到时,可短蜂鸣一次。
2、时钟精度分析
为进一步使本次的系统做得更完美,我使用了标准的秒表对自己设计的时间进行了精度测量。本次设计系统使用的晶振为12MHZ.数码管显示
00:10:00时,用秒表测得相应的数据如表3所示:
表3:
序号 1 2 3 4 5
T(min) 10.00.5781 10.00.4787 10.00.5040 10.00.3096 9.59.2587
序号 6 7 8 9 10
T(min) 10.01.4335 10.00.2003 9.59.4556 10.01.2026 10.00.2597
序号 11 12 13 14 15
T(min) 9.58.9750 10.00.1181 10.00.9604 10.02.5060 9.59.8985
序号 16 17 18 19 20
T(min) 10.00.1081 10.01.0545 10.00.9560 10.00.7854 10.00.4355
通过计算可得数码管显示:00:10:00时,
秒表测得的数值平均值为:00:10:2343 。
以上数据表明了本次系统的精度基本符合实验课程精度要求。因为以上共有20组,测量时已去除了粗大误差。当然,如果将测量时间加长,所测得的精度将更精确。
六、系统设计总结
本次课程从基本方案的制定,再到硬件电路的选择,到制作电路完成,最后进行程序调试。在此期间我遇到很多困难,尤其是在做仿真时结果经常出不来。
经过仔细检查,仿真线路是没有错的,可结果就是不行。但当我将实物做出来后,进行了调试,实物上却可以出来成果。这说明了可能是仿真软件的。经过一次又一次品尝到了解决问题的喜悦,最终提前完成了要求的全部功能,并在空闲的时间里加入了一些创新的部分。在此次课程设计中我发现了自己知识的不足,通过一周的学习、实践,我学到了很多东西。
通过此次课程设计的教学实践,进一步学习、掌握单片机应用系统的有关知识,加深了解单片机的工作原理。初步掌握简单单片机应用系统的设计、制作、调试的方法。提高动手实践能力。通过这次对数字时钟的设计,让我系统的了解和学会应用单片机C语言来对所需实现的功能进行编程。
在调试时遇到了一些问题,比如,刚开始进行按键输入检测时,我们直接用万用表测量按键两端的电平,刚测时,万用表显示高电平,当有按键按下时,则万用表显示低电平,这说明了按键是正常的,但当直接用按键时,系统板则不能正常使用按键。后面重新焊接了按键,系统板则才能正常使用按键。还有,LED灯显示模块的上拉电阻,也是出现了同样的情况。原先焊接时发现了电阻的管脚比之前看到的同阻值电阻管脚细。后面经过万用表调试后,重新焊接了电阻,部里就解决了。
上述电子钟,无论在外观上还是功能上都实现了较为完善的设计。特别值得一提的是本系统的加密效果,可与现实生活中的数字钟相媲美,因为有了加密效果,可以使用户在购买时知道其产品是否是新的,还是二手货。但本系统在定时闹鸣时,声音不过响应,因为我为了让蜂鸣器闹鸣时系统时间不受到影响,而是继续走动,所以把闹鸣时间控制在定时器0 1s定时里面,所以定时时间到了时,响的时间不到1s,通过的电流过小,要解决此问题,可在蜂鸣器的放大电路中多加一级放大电路,使定时时间到了时,通过的电流足够大以驱动蜂鸣器。亦或通过软件设置蜂鸣,则可以正常实现蜂鸣器的功能。
七、参考文献:
[1]崔凤波.《数字电子技术》.大连理工大学出版社,2007.7.
[2]戴仙金.《51单片机及其C语言程序开发实例》.清华大学出版社,2008.12
[3]谭浩强.《C语言程序设计》.清华大学出版社.2007.11
[4]赵建领.《51系列单片机开发宝典》. 电子工业出版社,2007
[5]田立,马鸣鹤.《51系列单片机开发实例》.中国电力出版社,2009.8
[6]王昊天,李海涛,王志强等.《PIC单片机原理与应用》.机械工业出版社,2010.1
附录:
1、 系统原理图;
2、系统PCB图
3、源程序
/****************************Copyright (c)*************************
** File name: ShuZiZhong.c
** Last modified Date: 2009-05-22
**-----------------------------------------------------------------** Created by: 翁连益
** NO: 2006040235
** Descriptions: 单片机数字钟
******************************************************************/
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define CYCLE 1000 /*定时1ms时间 */
unsigned char i,j,k,ID; /*ID 为case 的次数 K为LED灯控制。*/
unsigned char temp;
unsigned char b,c;
uchar hour=0,min=0,sec=0; /*定义秒时分初始值*/
uchar a[6]; /*定数码管显示缓冲*/
uint t=0;
uint flag=0;
bit fla;
unsigned char count;
sbit KEY1=P3^0;
sbit KEY2=P3^1;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
sbit LED2=P1^0;
sbit BEEP=P0^7;
void Modifytime(); /*时间调整模块*/
void Adjust();
void scan(); /*扫描数码模块*/
void Time_BEEP();
void delay10ms(void) /*软件10ms定时*/
{ unsigned char i,j;
for(i=20;i>0;i--)
for(j=248;j>0;j--); /* 软件延时*/
}
void dely250(void)
{ unsigned char i,j;
for(i=2;i>0;i--) /* 软件延时*/
for(j=248;j>0;j--);
}
void main()
{ TCON=0x01; /*TIMER0工作在方式1*/
TMOD=0x01;
TH0=(65536-CYCLE)/256; /*设定T0每隔1000us(1ms)中断一次*/ TL0=(65536-CYCLE)%256;
TR0=1;
IE=0x82;
Modifytime();
while(1)
{ if (flag==100)
{
{ temp=0xfe;
P1=temp;
delay10ms()
for(k=0;k<8;k++)
{ b=temp<<k;
c=temp>>(8-k);
P1=b|c;
delay10ms();
}
for(k=0;k<8;k++)
{ b=temp>>k;
c=temp<<(8-k);
P1=b|c;
delay10ms();
}}
}
if(flag==1000) /*判断1秒钟到否*/
{ sec++; /*秒加一*/
Modifytime();
flag=0;
while ((min==0)&(sec==0)) { if (flag==100)
{ { BEEP=0;
BEEP=1;
} }
if (flag==600) break;
}
}
while(KEY1== 0)
{ while(1)
{
if(KEY1==0)
{
delay10ms();
if(KEY1==0)
{ ID++;
if(ID==2)
{
ID=0;
}
while(KEY1==0);
}
}
switch(ID)
{ case 0: Adjust();
break;
case 1:
LED2=0;
if(flag==1000) /*判断1秒钟到否*/
{ sec++; /*秒加一*/
Modifytime();
flag=0; while ((min==0)&(sec==0))
{ if (flag==100)
{ { BEEP=0;
BEEP=1;
}
}
if (flag==600) break;
}} break;
}
}
}}
}
void Modifytime() /*调整时间子程序*/
{ uchar temp;
temp=sec; /*uchar temp=sec;*/
sec%=60;
min+=temp/60; /*求余*/
temp=min;
min%=60;
hour=(hour+temp/60)%24;
a[0]=(sec%10); /*调整过的时间送到显示缓冲中*/
a[1]=(sec/10); /*对于秒计数单元中的数据要把它十位数和个数分开,方法仍采用对10整除和对10求余。 */
a[2]=(min%10); /*对于分计数单元中的数据要把它十位数和个数分开,方法仍采用对10整除和对10求余。 */
a[3]=(min/10);
a[4]=(hour%10); /*对于时计数单元中的数据要把它十位数和个数分开,方法仍采用对10整除和对10求余。 */
a[5]=(hour/10);
}
void scan( ) /*扫描6个数码管子程序*/
{ static uchar x;
x++;
if(x>5) x=0; /*6个数码管都扫描过了则重新开始*/
P0=x|(a[x]<<3); /*选中需要扫描的数码管并送数据*/
}
void Timer0Int() interrupt 1 using 2 /*中断定时 */
{ t++;
if(t==100) { flag=100;
}
else if(t==200)
{ flag=200;
}
else if(t==600)
{ flag=600;
}
else if (t==1000)
{ flag=1000;
t=0;
}
else
flag=0;
scan();
TH0=(65536-CYCLE)/256;
TL0=(65536-CYCLE)%256;
}
void Adjust()
{ while(1)
{ if(KEY2==0)
{ for(i=40;i>0;i--) /*248*2us*5=2480=2.5ms 软件延时*/
for(j=248;j>0;j--);
if(KEY2==0)
{
sec++;
for(count=200;count>0;count--)
{
BEEP=~BEEP;
dely250();
}
if(sec==60)
{ sec=0;
}
a[0]=(sec%10);
a[1]=(sec/10);
while(KEY2==0);
}
}
if(KEY3==0)
{ for(i=16;i>0;i--) /* 软件延时*/
for(j=248;j>0;j--);
if(KEY3==0)
{
min++;
for(count=200;count>0;count--)
{
BEEP=~ BEEP;
dely250();
}
for(count=200;count>0;count--)
{
BEEP =~ BEEP;
dely250();
dely250();
}
if(min==60)
{
min=0;
}
a[2]=(min%10);
a[3]=(min/10);
while(KEY3==0);
}
}
if(KEY4==0)
{ for(i=40;i>0;i--) /* 软件延时*/ for(j=248;j>0;j--);
if(KEY4==0)
{
hour++;
for(count=200;count>0;count--)
{
BEEP =~BEEP;
dely250();
dely250();
}
if(hour==24)
{
hour=0;
}
a[4]=(hour%10);
a[5]=(hour/10);
while(KEY4==0);
}
}
}
}
㈡ 单片机实验
1、
MOV R0,#20H
MOVX A,@R0
MOV 20H,A
2、
MOV DPTR,#2000H
MOVX A,@DPTR
MOV 20H,A
3、
MOV DPTR,#2000H
CLR A
MOVC A,@A+DPTR
MOV 20H,A
4、
MOV DPTR,#2000H
CLR A
MOVC A,@A+DPTR
MOV B,A
MUL AB
MOV R7,A
MOV R6,B;(溢出部分送R6)
5、高八位?低八位?什么意思?
地址高八位DPH,地址第八位DPL
MOV DPH,#20H
MOV DPL,#00H
㈢ 单片机实验“定时/计数器及中断”的一些问题
1.1)主程序各行作用如下:
第一行:设置定时器模式
第二行:设置定时器高位寄存器初值
第三行:设置定时器低位寄存器初值
第四行:T0定时器中断使能
第五行:总中断使能
第六行:打开T0定时器
第七行:死循环(主程序停留在此行)
主程序整体实现的功能:初始化定时器T0
1.2)void Timer0_Int(void)是定时器0中断函数,每行作用如下:
第一行:重新设定定时器高位寄存器初值
第二行:重新设置定时器低位寄存器初值
第三行:如果P1_0 IO口是高电平则改为低电平,如是低电平改为高电平
整体实现的功能:P1_0 IO口高低电平1秒切换一次
妈呀,这么多问题,网上找找,应该有的
㈣ 单片机实验
没有电路,看程序,有些虚无缥缈的感觉。
㈤ 急求:单片机实验
:
ORG 0030H
MOV 30H, #34H
MOV 31H, #56H
MOV 32H, #23H
MOV 33H, #90H
MOV 34H, #32H
MOV 35H, #68H
MOV 36H, #09H
MOV 37H, #75H
CALL SORT
SJMP $
;-----------------------------------------------------
SORT: ;最简短、高效的排序程序.
MOV B, #7 ;第一轮排序时,比较7次.
S1: MOV R0, #30H ;数据区的起始地址.
MOV R7, B
CLR PSW.5 ;清除"交换"标志位.
S2: MOV A, @R0 ;取前一个数.
INC R0
CLR C
SUBB A, @R0 ;减后一个数,前<后时,Cy=1
S3: JC S4 ;有借位时,不用交换,转移.
MOV A, @R0 ;取后一个数,准备交换.
DEC R0
XCH A, @R0 ;交换到前一个.
INC R0
XCH A, @R0 ;交换到后一个.
SETB PSW.5 ;设定"交换"标志位.
S4: DJNZ R7, S2 ;继续本轮比较.
JNB PSW.5, ENDS ;如本轮没有进行过交换,可提前结束.
DJNZ B, S1 ;下一轮,比较次数少一次.
ENDS:
RET
;-----------------------------------------------------
END