秒表程序设计摘要:本课程设计旨在设计一个秒表计时并储存计时的程序,可控制秒表的计时开始及结束,实现秒表的准确计时,存储计时数据,翻阅计时数据,清除计时数据等功能。本程序是基于8086微机系统设计,在MasmforWindows软件下采用汇编语言编写,通过选择8253定时器0,工作方式3,输出周期为10ms的方波,产生稳定延时,调用各种中断完成程序各逻辑模块设计,通过键盘扫描得到输入的值,执行对应功能。每10ms计时一次,每60秒一次循环,存储数据设定为最多20组,可随时存入数据,操作自由度极高,经测试,60秒计时误差不超过1.2%,可实现准确计时及存储功能。关键字:秒表、显示计时、存储计时、汇编1设计任务分析与方案选择本设计需实现秒表稳定计时,并显示,需要存储计时数据时可立即将当前计时数据存入缓冲区,暂停计时时立即结束并可复位或者继续计数或者查看存储数据,在查看数据时可前后翻阅存储数据,并可清除,当退出查看数据后可使秒表继续计数或复位。1.1方案选择1.1.1系统硬件设计选择本设计采用8253定时器0,工作方式3获得周期为10ms的稳定计时单位,使用8086CPU进行译码,当定时到1s的时候产生一个中断信号,在中断服务程序进行秒的计数,并送入相应的存储单元,8259芯片提供中断,并用8255的A口接七段数码管的段选信号,B口接七段数码管的位选信号。1.1.2系统软件设计选择在代码实现上,对于按键的输入上可以直接读取或是先扫描键盘再读取,本设计只存在各逻辑功能之间的转换,因此选择先扫描键盘再读取的方法,可提高代码的容错率及可操作性;使用宏定义及光标定位的方法,并配合各种中断设计界面图形及字体颜色,宏定义可以减少代码的重复度,且便于修改功能,可任意调用,通过定位光标可确定输出位置,可实现同一位置的动态输出;对于时间的扫描,可以选择直接读取系统当前的时间或是读取系统时钟的计时单位,前者的读取直接是BCD码非常便于输出显示,后者需要不停的读取计时单位读取次数非常多,而且结果不是BCD码,需要做判断转换输出,此设计采用读取系统时钟的计时单位,虽然需要不停的读取计时单位读取次数非常多,而且结果不是BCD码,需要做判断转换输出,但是经过与实际情况比较,后者的计时更为准确,区分度更大。2详细设计2.1理论分析与计算此设计需要实现单位为1秒的秒表稳定计时,8253定时器0工作方式3,外部提供一个时钟作为CLK信号,频率f=1.1931816MHz,为得到周期为10ms的方波,应对8253定时器设置计数初值为1.1932×10×10^-3=11932。因此,8259A每隔10ms向CPU申请一次中断。可用10作为基本计时单位,此设计的毫秒每一个计时单位改变一次,要达到1秒的计时,需要的计时单位为:1000ms/10=100,则计数满足100个计时单位时,即毫秒计时到100时,秒位加1,完成1秒稳定计时。2.2算法设计本设计的算法包括键盘检测及读取、秒表计时及输出,数据存储、数据操作、界面及提示词设计。2.2.1键盘检测及读取使用21H中断的0BH中断检测是否有键盘按下,如果没有键盘按下则继续检测,如果有键盘按下使用21H中断的08H中断判断是否为所设定的值,如果不是,继续检测输入,如果是便按逻辑进行。2.2.2秒表计时及输出使用8253定时器0,工作方式3获得的周期为,10ms的方波作为计时单位,调用1CH中断,读取1CH原中断向量,并设置中断向量,取计时处理程序偏移地址及段地址,计时处理程序中毫秒加一直到100ms,秒位便加一,毫秒清零,继续计时。定位光标,在光标位置输出计时,显示格式为00:00:00,计时显示采用高位低位分开显示,将计时数值除以10,得到商和余数,商作为高位,余数作为低位,当计时单位满1后,毫秒位加1毫秒,毫秒计时到100,秒位加1并动态显示。2.2.3数据存储在数据段中定义一个大小为40字的全为0的缓冲区用于存储计时数值,在代码段中合适位置取缓冲区的偏移地址给寄存器,存储方式采用高位低位分开存储的方式,将秒数值除以10,商存前一个字节,余数存后一个字节,存完高位后寄存器指向下一个字节存低位,低位存完之后寄存器再指向下一字节,用于存储毫秒计时的高位。2.2.4数据操作定义光标,取缓冲区的偏移地址给寄存器,在合适位置从第一次存储的数据开始显示,此时寄存器指向第一个字节,调用21H的0BH检测键盘输入,如有键盘输入,调用21H的08H检测键入值,当接收操作为查看下一个存储数据时,寄存器加2,指向下一组数据的高位,并调用21H的09H中断显示当前数值,寄存器加一,调用21H的09H中断显示当前所指数据;当接收操作为查看上一个存储数据时,寄存器减二,指向上一组数据的高位,并调用21H的09H中断显示当前数值,寄存器加一,调用21H的09H中断显示当前所指数据;当接收操作为清除当前数据时,将0存入当前寄存器所指字节及下一字节,并调用21H的09H中断显示当前数值:00:00;当接收操作为返回计时时,判断键入,跳转到相应操作。2.2.5界面及提示词设计在数据段定义提示语句字符串,使用10H的02H中断定位光标,在代码段中相应位置取代码段的偏移地址,使用21H的09H中断显示字符串,使用宏定义,拥有两个参数,一个是光标位置,所在行数和列数,调用10H的02H中断置光标,调用21H的09H显示字符,可实现在任意位置显示任意字符,用此宏定义绘制计时区及记忆区图形,搭配10H的06H中断可在任一区域进行显示,为使各区域鲜明区分,改变10H的06H中断中出口参数BH的值,设置各字符串为不同颜色,实现彩色输出,增强观赏性。2.3硬件电路设计图1,硬件电路设计在整个电子钟的设计中。我们使用8253用于定时功能,由于8259的中断只能是电平与电缘触发,所以我们选择电缘触发。由于我们选择一次写入计数初值后的能循环进行,所以我们选择工作方式0在每次的计数初值的N-1是产生一个脉冲。在CLK0引脚接入1.1932MHZ的时钟周期,而将计数初值写为11932,继而在OUT0会在每1ms产生脉冲,在控制字的时候采用二进制计数,所以其控制字为00110110B,所以8253能产生准确的计时功能。8255A芯片,将8255A的A,B口均工作在工作方式0的下,且为输1.193MHZ出控制LED的位选与片选,而C口用于修改时间用,同样工作于方式0低四位输出。所以其控制字为81H。8259A芯片用于产生中断信号去自动修改秒针。所以只需将8259的IR0产生中断,其他未屏蔽,单片8259,上升沿中断,要写ICW4,中断号为20H,工作在8086方式。2.4软件设计在软件实现上,对于按键的输入上采用DOS系统功能,通过功能号0BH对应功能扫描键盘判断是否有按键被按下,如果有则通过功能号08H对应功能读取键盘缓冲区得到按键输入信息。1S定时采用8253定时器0,工作方式3获得10ms稳定计时单位,设置1CH中断向量,程序进行时,不断读取1CH中断服务程序是否计数到1个计时单位。计时储存采用高位低位分开存储到DW类型的缓冲区中方法,读取存储也采用高低位分别读取的方法。界面设计采用定义宏定义的方法,参数包括光标定位位置及需要输出的字符串,调用INT10H的06H中断设置每个区域的显示及字符串的颜色。软件代码流程图:图2:设计流程图图2为设计流程图,程序运行时会等待输入,当输入为S,便开始计时,开始计时时可输入E或者R,输入R,存储当前计时;输入E,暂停计数,程序在此等待输入,当输入为C,继续计数;当输入为D,重新计数;当输入为W,查看存储区所存储数据,存储区显示第一次存储的数据,等待输入,当输入为N,查看下一组存储数据;当输入U,查看上一组存储数据;当输入D,清除当前组数据;当输入B,返回计时区,等待输入。3系统调试与效果分析运行效果图:图3为程序开始界面,按下S开始计时图3:程序开始界面图4为程序开始计时界面,按下R存储当前计时,按下E暂停计时图4:程序运行界面图5为存储区显示界面,按下N,查询下一组存储数据,按下U查看上一组存储数据,按下D清除当前组数据,按下B返回计时区重新等待操作。图5:存储区显示界面图6,为当前存储清零,按下U,显示上一组,按下N,显示下一组,按下B,返回计时。图6:清除当前存储区4问题解决4.1计时精度初版设计采用1AH的00H中断读取系统时钟进行直接计时判断,在程序开始的地方判断是否满足18个计时单位,满足则加1秒,此程序是在所有后面判断键盘输入、存储数据等操作之后才清零计时单位,重新计数判断,在循环设计中,由于每行指令的执行都会消耗一定的时间,这就造成了在执行其他代码时计时单位没有继续计数,使本来计时周期为1秒变为不止一秒,经测试,60秒计时产生误差超过25%,完全达不到秒表计时标准,未解决计时单位计数与代码执行的同步问题,为解决此问题采用了更改中断向量1CH的办法,使用8253定时器0,工作方式3,设置计数初值为11932,并在任意代码执行的同时读取计时单位计数数值,这就避免了其他代码执行时计数并不进行的问题,经测试,60秒计时产生误差不超过1.2%,达到秒表计时标准。4.2各逻辑之间的相互跳转在对键入值进行判断后会有各逻辑之间的跳转,使用JZ,JNZ等条件转移指令时会出现错误,导致程序跳转到非理想位置,由于这个设计主要是各逻辑之间的跳转,因此我将各逻辑转移绘制成流程图,并标明所需的跳转转移指令,解决各逻辑之间错误转移的问题。使用条件转移指令跳转时可能会发生跳转指令错误,是因为这些跳转指令的跳转范围是有限的,当跳转范围在128B之内时才能使用这些指令,超过了需要使用长跳转指令。4.3对数据的存储数据存储的缓冲区的类型为DW,有两个字节,在存储时采用的是高低位分开存储的方式,存储低位时使用的是MOV[DI+1],DL,这个指令可实现将DL中的值存入DI+1这个字节,存下一组数据时只INCDI了一次,造成存储错误,后来经查阅资料发现即便执行了MOV[DI+1],DL,DI实际指向的单位仍然是高位字节,因此在程序结束后应INCDI四次才能指向下一组数据的高位。参考文献[1]黄玉清,刘双虎,杨胜波,微机原理与接口技术,2015,8(2):170-187.附件清单程序:;----设置图形显示宏定义-----DISMACROLOCAT,CODEPUSHDXPUSHBXPUSHAXMOVDX,LOCAT;设置光标位置MOVBH,00MOVAH,02HINT10HMOVDL,CODE;输出字符串MOVAH,02HINT21HPOPAXPOPBXPOPDXENDMDATASEGMENTMSDB0SECDB0MSECDB0MINDB0FLAGDB0SFLAGDB0INIEDW0INIBDW0MIDB'00:$'MEMDW40DUP('0')SPACEDB'$'NULINEDB3DUP(0),'$'WSTRDB00:00:00,'$'TITDB'********CurriculumDesign********$'OPERATIONDB'Operation:$'PROMPT1DB'1.timezone:InputSStart,RRemember,CContinue,Ddiaplasis,EExit$'PROMPT2DB'2.memoryzone:InputNNext,UUp,DDelete,BBack$'TIP1DB'OperatingTimeZone$'TIP2DB'OperatingMemoryZone$'NAMDB'---ByCaiLiqiang$'DATAENDSSTACKSEGMENTSTADB256DUP(0)TOPEQU$-STASTACKENDSCODESEGMENTASSUMECS:CODE,DS:DATASTART:MAINPROCFAR;;;;;;;;;;;;XORAX,AXMOVAX,DATAMOVDS,AXMOVAX,STACKMOVSS,AXMOVAX,TOPMOVSP,AXMOVDI,OFFSETMEMCALLCLRTIP;