• 186.50 KB
  • 2022-04-22 11:51:05 发布

《51单片微型机原理和接口教程》(周思跃)习题解答.doc

  • 36页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'《51单片微型机原理和接口教程》(周思跃_著)课后习题答案_化学工业出版社第一章习题答案1-1请说明CPU的功能以及CPU是如何执行指令和程序的。答:CPU的功能是执行程序和统筹处理计算机系统中各类事务。CPU执行指令分为3步:取指令、分析指令、执行指令;计算机程序是由一条条指令按一定的顺序排列组成的,CPU执行程序的过程就是一条条指令累计执行的过程,其方式分为串行作业方式和流水线作业方式。1-2请说明单片机内部主要是由哪些部件组成的,并说明各部件的作用。答:CPU:由控制器和运算器构成,控制器的作用是执行指令和协调系统各部件的工作;运算器的作用是进行逻辑运算和算术运算。存储器:存储计算机工作时使用的信息,即指令代码和数据代码。I/O接口电路:具有数据缓冲、数据隔离及数据转换的功能。1-3请问对于容量位8K的存储器芯片,它的地址线是多少根?答:8K=8192=213,故地址线为13根。另附:存储器的数据线由存储器的字长决定,例如一块32K×16(存储器容量显示格式:存储单元数×存储单元的字长)的存储器,其地址线为15根,数据线为16根。1-4将十进制数78,134,分别用二进制数、十六进制数和8421BCD吗表示。答:(78)D=(1001110)B=(4E)H=(01111000)8421BCD(134)D=(10000110)B=(86)H=(000100110100)8421BCD注:8421BCD码为4位表示一个十进制数符,本质是符号不是数值,所以不可省略0。1-5将下列真值分别转化为用8位和16位二进制数表示的原码、补码和反码。X=1000100;[X]8位原=[X]8位反=[X]8位补=01000100;[X]16位原=[X]16位反=[X]16位补=0000000001000100X=-1000100 [X]8位原=11000100,[X]8位反=10111011,[X]8位补=10111100;[X]16位原=1000000001000100,[X]16位反=1111111110111011,[X]16位补=1111111110111100;X=-0111111[X]8位原=10111111,[X]8位反=11000000,[X]8位补=11000001;[X]16位原=1000000000111111,[X]16位反=1111111111000000,[X]16位补=1111111111000001;1-6将下列补码转化成二进制数的真值。[X]补=00101100;X=101100[X]补=11111111;X=-1[X]补=10000000;X=-100000001-7已知下列补码[X]补和[Y]补,分别求[X+Y]补、[X-Y]补。并判断运算结果是否出现溢出。[X]补=10011001,[Y]补=00101100;[-Y]补=11010100,[X+Y]补=[X]补+[Y]补=11000101不溢出;[X-Y]补=[X]补+[-Y]补=[X]补-[Y]补=01101101溢出;[X]补=11111111,[Y]补=10000000;[-Y]9位补=010000000,[X+Y]补=[X]补+[Y]补=01111111溢出;[X-Y]补=[X]补+[-Y]补=[X]补-[Y]补=01111111不溢出;[X]补=00110111,[Y]补=11100000;[-Y]补=00100000,[X+Y]补=[X]补+[Y]补=00010111不溢出;[X-Y]补=[X]补+[-Y]补=[X] 补-[Y]补=01010111不溢出;[X]补=10000111,[Y]补=11000000;[-Y]补=01000000,[X+Y]补=[X]补+[Y]补=01000111溢出;[X-Y]补=[X]补+[-Y]补=[X]补-[Y]补=11000111不溢出;方法提示:由于补码是按序列排列的,所以可以直接进行加和减,即[X+Y]补=[X]补+[Y]补;[X-Y]补=[X]补-[Y]补另补码减法也可用加法实现[X-Y]补=[X]补+[-Y]补。上题的第2小题,由于[Y]8位补=10000000=28,Y=-28,所以(-Y)=28,已不能用8位补码表示,可以先扩补位9位补码,然后进行运算,或直接用[X-Y]补=[X]补-[Y]补进行计算。判断结果是否溢出,可按下列方法:加法时,如果正负数相加(即两数的符号位不同),则结果肯定不溢出;如果同号数相加,结果与被加数和加数异号的则溢出(即正正相加结果为负或负负相加结果为正时)。减法时,如果同号数相减(即两数的符号位相同),则结果肯定不溢出;如果异号数相减,结果与被加数异号的则溢出(即正负相减结果为负或负正相减结果为正时)。此法比用变形补码直观,加和减都适用。第二章习题答案2-1请说明单片机89C52内部有哪些资源。答:1个8位CPU、8KB的FLASH程序存储器、256B的SRAM数据存储器、4个8位的并行I/O口(P0,P1,P2,P3)、1个全双工串行口、中断系统(5个中断源、2个中断优先级)、3个16位的定时/计数器(T0,T1,T2)、时钟电路(时钟频率6~24MHZ)。2-2为什么51系列单片机的存储器系统采用哈佛结构。答:哈佛结构指的是指令代码和数据分别存放在程序存储器和数据存储器中,两部分存储器分别采用不同的地址总线系统。单片机在工作时一般执行固定不变的应用程序代码,而作为嵌入式控制系统的核心,受限于体积要求,单片机系统一般不会带有辅助存储器(例如硬盘等),为了在断电时也能保存用户的应用程序,故需将程序固化在只读存储器中,而单片机工作时程序运行过程中的数据是变化的,所以需要放在随机访问存储器中。2-351单片机中的工作寄存器分布在存储器的哪个区域?答:分布在内部数据存储器的00H~1FH区域。2-4在51系列单片机中,工作寄存器分几个区?如何改变工作寄存器区?答:分为0、1、2、3四个区。修改特殊功能寄存器PSW的RS1和RS0位可改变当前工作寄存器区。2-5特殊功能寄存器和工作寄存器在存放信息方面有和区别? 答:特殊功能寄存器(SFR)中存放的是一些专用信息,这些信息与下列内容有关:计算机指令的执行条件及状态标志,定时/计数器的使用控制、中断系统的使用、并行I/O及串行I/O接口的使用。工作寄存器只是用于暂时存放指令执行过程中一般的被操作数据。2-6特殊功能寄存器的地址空间如何?答:特殊功能寄存器(SFR)的地址为8为二进制编码,地址范围为80H~0FFH,但各特殊功能寄存器的地址并非连续分布的。指令通过直接寻址的方式才能访问到。2-751单片机中的位寻址区在哪里?它们的地址空间如何?答:51单片机的位寻址区分布在两个地方。一部分位于内部数据存储器中字节地址为20H~2FH的16个单元中,这部分包括128个位,位地址空间为00H~7FH;另一部分位于字节地址能被8整除的特殊功能寄存器中,位地址空间为80H~0FFH。2-8请指出下列位地址所在的内部数据存储器单元的字节地址或SFR名称。答:00H内部RAM的20H单元;(20H).020H内部RAM的24H单元;(24H).00A0HP2;P2.00B0HP3;P3.064H内部RAM的2CH单元;(2CH).4E6H累加器ACC;ACC.6。提示:1)内部数据存储器内的可寻址位,其位地址(00H~7FH)与所在单元的字节地址(20H~2FH)间的关系如下:位地址=(字节地址-20H)×8+DX,DX-该位在字节单元中的位置(D0~D7)位地址÷8,商+20H=字节地址,余数=DX2)SFR中的可位寻址(位地址80H~0FFH)的寄存器,其最低位的位地址与其字节地址相同。关系如下:位地址÷8,商*8=SFR的字节地址,余数=DX,DX-该位在SFR中的位置(D0~D7)2-9若某51单片机应用系统将F000H~FFFFH地址空间分配给它外部的I/O接口,那么该单片机应用系统最多给外部数据存储器分配多少单元?地址空间如何?答:51单片机的外部I/O接口和外部数据存储器是统一编制的,占用同一个地址空间,地址空间的容量为64KB,地址范围为0000H~FFFFH。据题意,系统已将F000H~FFFFH地址空间分配给它外部的I/O接口,则只剩下0000H~EFFFH可分配给外部数据存储器,容量为60KB。2-10在图2-9中的电容C,如果它取值太小,对复位电路有何影响?答:51单片机上电复位,需要在RST引脚上保持10ms以上的高电平。如果C太小,则其充电时间变短,上电后,RST引脚上高电平保持的时间太短,则单片机内部复位将不能完全完成,有些寄存器内容将变得不确定。 2-11上电复位和人工按钮复位后对内部数据存储器具有什么不同的影响?答:上电复位后,内部数据存储器中的内容为不确定的状态。人工按钮复位后,内部数据存储器中的内容不变(因为没有断电)。2-1251应用系统中,为何要对堆栈指针SP重新设置?答:复位后(SP)=07H,则堆栈是从08H开始存放数据的。而内部数据存储器中00H~1FH单元为工作寄存器区,而20H~2FH单元为位寻址区,在实际的应用系统中,这些区域都可能使用到。故一般将堆栈设置在地址30H以后的单元中,所以需要对堆栈指针SP重新设置。2-1351单片机中的I/O接口中,那个接口在作为准双向口时需要外接电阻?若对某一接口进行读引脚的操作,必须事先对该接口做什么操作?答:P0口需外接上拉电阻(因为P0是集电极开路结构)。若需对某个接口读引脚(即读取外部输入信号的状态),需要对该接口的口锁存器写入1(例如:若需要读取P1.0、P1.1、P1.2、P1.3的引脚状态时,需要先执行MOVP1,#0FH。这也是为什么复位后(P0)=(P1)=(P2)=(P3)=0FFH的道理。)第三章习题答案3-1指令的格式是由哪些部分组成的?每部分的含义是什么?答:指令由操作码和操作数组成。在形式上操作码和操作数都是二进制代码。操作码用来表示指令的种类和功能,经由控制器中的指令译码器译码后产生控制信号。操作数是指令的操作对象,表示被操作数据或数据所在的存储单元地址。3-2什么是寻址方式?51系列指令系统有哪些寻址方式?答:指令中给出操作数的方式叫做寻址方式。51系列机给出的寻址方式一般有7中:立即寻址、直接寻址、寄存器寻址、寄存器间接寻址、变址寻址、相对寻址、位寻址(直接寻址的一个特例――地址指向位单元)。3-3对于内部数据存储器00H~1FH区域的访问有哪些寻址方式?对于外部数据存储器的访问有哪些寻址方式?对于特殊功能寄存器的访问有哪些寻址方式?答:对于内部数据存储器00H~1FH区域的访问有直接寻址、寄存器寻址、寄存器间接寻址三种方式。对于外部数据存储器的访问只有寄存器间接寻址一种方式(以DPTR或R0、R1为指针)。对于特殊功能寄存器的访问只有直接寻址一种方式。同时对于内部数据存储器80H~0FFH的128个单元的访问只有寄存器间接寻址一种方式(以R0、R1或SP为指针);借助于两种不同的寻址方式,可以将在地址上重合(80H~0FFH)的SFR和内部RAM高128字节单元的两部分空间加以区分。3-451系列单片机有哪些标志位?这些标志位存放在哪里?答:51单片机在程序运行时通常需要一下标志位:Cy,AC,OV,P,RS1,RS0,它们都存放在特殊功能寄存器PSW (程序状态字寄存器)中。3-5分析下列各指令的操作数,指出它们的寻址方式。MOVR4,38H;寄存器寻址,直接寻址ADDA,@R1;寄存器寻址,寄存器间接寻址MOVCA,@A+DPTR;寄存器寻址,变址寻址(又称基址寄存器加变址寄存器间接寻址)MOVXA,@DPTR;寄存器寻址,寄存器间接寻址DECB;直接寻址SETB24H;位寻址(直接寻址的一种,只是给出的直接地址是位地址)CJNEA,#100,NEXT;寄存器寻址,立即寻址,相对寻址ANL30H,#00H;直接寻址,立即寻址PUSHP1;寄存器间接寻址(指针为SP,只是在堆栈操作指令中省略了),直接寻址堆栈操作除了用PUSH和POP指令,完全可以用其它指令来完成,举例如下:PUSHP1可用下列程序段完成INCSPMOVR0,SPMOV@R0,P1POPP1可用下列程序段完成MOVR0,SPMOVP1,@R0DECSP提示:上题答案中按操作数先后顺序给出其对应的寻址方式。3-6下列各指令或指令组执行前有关寄存器和存储器的状态如下表,要求分析各指令或指令组执行后有关寄存器、存储器和标志位的状态。内部数据存储器和特殊功能寄存器外部数据存储器程序存储器寄存器名内容单元地址内容单元地址内容单元地址内容程序计数器内容B64H73H10H900BH12H1206H35H(PC)=1200HACC03H72H11H900AH83H1205H34HPSW80H71H00H9009HD1H1204H33H标号及标号值DPL05H70H80H9008H79H1203H32HNEXT1=0800HDPH90H9007H0CH1201H31HNEXT2=0900HSP71H36HF8H9006H23H1200H30HNEXT3=1280HR000H35H2BH9005H13HLOOP=1148HR136H34H36H9004H4DH R235H33H74H9003H2EHR3B7H32H59H9002H7FHR403H9001H54HR5F6H26H66H9000H38HR6E4H25H55HR721H24H44HP07CHP290H提示:在上表中需注意几点:(PSW)=80H,即Cy=1,AC=0,RS1=RS0=0(故当前工作寄存器区为0区)。工作寄存器区为0区时,R0~R7指向内部数据存储器的00H~07H,所以当指令中出现直接地址00H~07H中的某个时,其初始条件即为R0~R7中某个对应的寄存器的值。另,因为(DPH)=90H,(DPL)=05H,所以(DPTR)=9005H。标号值实质上是代表标号所在处的指令在程序存储器中的地址,标号往往出现在程序转移指令中,指出转移指令的目标地址。•MOVR0,#32;(R0)=32=20H•MOV25H,@R1;(25H)=0F8H•MOVXA,@DPTR;(A)=13HP=1•MOVXA,@R0;(A)=38HP=1•MOVCA,@A+PC;(A)=33HP=0•MOVA,04H;(A)=03HP=0•XCHA,34H;(A)=36H(34H)=03H•XCHDA,@R1;(A)=08H(36H)=0F3H•PUSHDPL;(SP)=72H(72H)=05H•POPDPH;(DPH)=00H(SP)=70H•SUBBA,R1;(A)=0CCHCy=1P=0AC=1OV=0•ADDA,R6;(A)=0E7HCy=0P=0AC=0OV=0•ADDCA,36H;(A)=0FCHCy=0P=0AC=0OV=0•MULAB;(A)=2CH(B)=01H•INCR0;(R0)=01H•DECA;(A)=02HP=1•ADDA,#49H;DAA;(A)=52HCy=0P=1•ANLA,R1;(A)=02H(R1)=36HP=1•ORLA,32H;(A)=5BHP=1•ORL26H,#35H;(26H)=77HP=0•XRLA,@R0;(A)=03HP=0•XRLA,ACC;(A)=0P=0•XRLA,#0FFH;(A)=0FCHP=0•CPLA;(A)=0FCHP=0•RLA;(A)=06HCy=1 •RRCA;(A)=81HCy=1•MOVC,(25H).2;Cy=1•MOVF0,C;(PSW)=0A0H•SETBRS0;(PSW)=88H•CLRC;(PSW)=0•ANLC,(24H).0Cy=0•JZNEXT1;(PC)=1202H•JCNEXT2;(PC)=0900H•CJNEA,25H,NEXT3;(PC)=1280HCy=1•DJNZR7,LOOP;(PC)=1148H(R7)=20H•LCALL1800H;(PC)=1800H(SP)=73H(72H)=03H(73H)=12H•RET;(PC)=0080H(SP)=6FH•ANLC,/32H;Cy=0(32H)=1,提示此处32H为位存储器•STOP:JBCP0.3,STOP;(PC)=1200H(P0)=74H•JNBP0.4,NEXT1;(PC)=1203H•分析下列程序段的功能。•MOVA,R3MOVR4,A功能:将R3中的内容送入R4,即(R3)→R4•MOVA,R5CPLAMOVR5,A功能:R5中的数据按位取反后送回R5•MOVA,R4MOVB,R5DIVABMOVR4,BMOVR5,A功能:R4中的数除以R5中的数,结果商送入R5,余数送入R4•MOVC,P1.1ANLC,P1.2ANLC,/P1.3MOVP1.6,C功能:P1.1P1.2→P1.6•MOVC,0ORLC,1MOVF0,CMOVC,2ORLC,3ANLC,F0MOVP1.7,C 功能:((20H).0∨(20H).1)∧((20H).2∨(20H).3)→P1.7•CLRCMOVA,R4RLCAMOVR4,AMOVA,R3RLCAMOVR3,A功能:R3、R4中的内容左移一位,R4最低位移入0,R4最高位移入R3最低位,R3最高位移出至Cy。•CLRCMOVA,R5RLCAADDA,R5MOVR5,A功能:•CLRAMOVR0,AMOVR7,ALOOP:MOV@R0,AINCR0DJNZR7,LOOPSTOP:SJMPSTOP功能:将内部数据存储器00H~0FFH256个单元全部清零。•PUSHACCPUSHBPOPACCPOPB功能:利用堆栈将ACC与B中的内容互换,即(ACC)(B)•MOVR0,#30HXCHDA,@R0SWAPAINCR0XCHDA,@R0SWAPAMOV40H,A功能:将ACC的低四位送入30H单元低四位,ACC的高四位送入31H的低四位,而原先30H单元的低四位送入40H单元的低四位,原31H单元的低四位送入40H单元的高四位。举例说明如下,设程序段运行前有(ACC)=12H,(30H)=34H,(31H)=56H;则程序段运行后有(30H)=32H,(31H)=51H,(ACC)=(40H)=64H;该程序段可用来将单字节BCD转压缩BCD.3-8指出下列指令中哪些是合法指令,哪些是非法指令。 MOVP1,R4;合法MOVR2,R4;非法CLRR3;非法RLCR5;非法MOV30H,31H;合法MOV00H,P;非法ORL40H,R7;非法PUSHR6;非法POPR0;非法INCDPTR;合法注:常见的错误还有类似:MOVR0,C;ADD30H,31H;MOVA,@R5;DECDPTR等,编程时切记勿错!3-9按要求编制下列各程序段。将内部数据存储器30H和31H单元的内容互换。法一:MOVA,30HXCHA,31HMOV30H,A法二:XCHA,30HXCHA,31HXCHA,30H比较法一、法二的优缺点,你认为哪个方法更好?将寄存器R7的内容向右循环移位一次。XCHA,R7RRAXCHA,R7将寄存器R3的内容乘以4(结果不超出8为二进制数的范围)。法一:MOVA,R3MOVB,#4MULABMOVR3,A法二:XCHA,R3RLARLAXCHA,R3将寄存器DPTR的内容减1。法一:判断DPL=0否?如是,DPL减1后,DPH也减1;否则,DPH不变。 XCHA,DPLJNZNOBDECDPHNBO:XCHA,DPLDECDPL法二:(DPH)(DPL)-1→DPH,DPL(即DPTR)CLRCXCHA,DPLSUBBA,#1XCHA,DPLXCHA,DPHSUBBA,#0XCHA,DPH法三:(DPH)(DPL)+0FFFFH→DPTRXCHA,DPLADDA,#0FFHXCHA,DPLXCHA,DPHADDCA,#0FFHXCHA,DPH比较以上各方法,其中法三利用了-1的补码是0FFFFH的原理,将减法改为了加法。将寄存器R6的内容压入堆栈(设寄存器工作在3区)PUSH1EH将R4,R5寄存器连接起来循环右移一位。(设R4为高8位,R5为低8位;执行完后R4R5中的内容右移一位,R4的最低位移入R5的最高位,同时R5的最低位移入R4的最高位)XCHA,R4;将R4中的内容送入ACC,同时将ACC的内容放入R4中暂存。RRCA;ACC中原先R4的内容右移一位,同时Cy移入最高位,而原先R4的最低位移入Cy位XCHA,R5;R5中的内容送入ACC,上一步中产生的ACC的内容送入R5暂存RRCA;ACC中原先R5的内容右移一位,Cy(即原R4的最低位)移入最高位,而原R5的最低位移入Cy位XCHA,R5;将结果送入R5(R5移位已完成),同时将第三步暂存在R5中的内容取出。MOVACC.7,C;将Cy位中存放的原R5的最低位送入ACC的最高位(即送入R4的最高位)XCHA,R4;将结果送入R4,同时取出ACC原来的值 第四章习题答案4-1用伪指令将下列常数依次定义在1600H为首地址的程序存储器中。0,1,4,9,16,25,36,49,64,81答:ORG1600HDB0,1,4,9,16,25,36,49,64,814-2用伪指令将下列常数依次定义在1700H为首地址的程序存储器中,要求数据类型一致。0,1,8,27,64,125,216,343,512,729答:提示:因为343,512,729为双字节数据(>255),所以所有数据均应以双字节存入。ORG1700HDW0,1,8,27,64,125,216,343,512,7294-3用伪指令将字节型变量X1、X2定义在内部数据存储器30H、31H单元中,将字节型变量Y1、Y2定义在外部数据存储器2000H、2001H单元中。答:X1DATA30HX2DATA31HY1XDATA2000HY2XDATA2001H4-4用伪指令将ASCII码字符串“Beijing,tjjtds!”定义在1200H为首地址的程序存储器中。答:ORG1200HDB‘Beijing,tjjtds!’4-5用伪指令将逻辑变量A1、A2定义在00H、01H位单元中答:A1BIT00HA2BIT01H4-6编一程序段,将1400H为首地址的外部数据存储器中200个单字节数据转移至1500H为首地址的外部数据存储器中。MOVDPTR,#1400H;用DRTR指向源数据块单元地址MOVP2,#15H;用P2,R0指向目标地址MOVR0,#00HMOVR7,#200;数据个数送入R7LOOP:MOVXA,@DPTRMOVX@R0,AINCDPTR;修改源数据块指针INCR0;修改目标单元地址指针 DJNZR7,LOOPSJMP$4-7编一程序段,将30H为首地址的内部数据存储器中20个单字节补码数据中的负数传送至2400H为首地址的外部数据存储器中。MOVR0,#30H;用R0指向源数据块首地址MOVDPTR,#2400H;用DRTR指向目标区首地址MOVR7,#20;数据个数送入R7LOOP:MOVA,@R0;取出源数据JNBACC.7,NEXT;若源数据最高位=0,则表示数据为非负数,无需传送,可直接取下个数据MOVX@DPTR,A;若取出的数据为负数,则传送到外部RAM,同时修改DPTRINCDPTRNEXT:INCR0DJNZR7,LOOPSJMP$4-8编一程序段,将40H为首地址的内部数据存储器中25个单字节数据,依次下移一个单元。提示:根据题意即将40H~58H中的数据依次送入41H~59H中XCHA,40H;ACC内容送入40H暂存保护,同时取出40H单元中内容MOVR0,#41H;R0指向目标单元首地址MOVR7,#25;数据长度送R7LOOP:XCHA,@R0;前一个单元数送后一个单元,同时取出后一个单元原先的数据暂存入ACCINCR0DJNZR7,LOOPMOVA,40H;恢复ACC原来的内容STOP:SJMPSTOP4-9编一程序段,完成函数y=x2+5x+6的计算。设0≤x≤10。提示:据题意6≤y≤156,即结果为单字节数据。XDATA30HYDATA31HMOVA,XMOVB,XMULABMOVY,A;X2→YMOVA,XMOVB,#5MULABADDA,Y;X2+5X→ACC ADDA,#6;X2+5X+6→ACCMOVY,A;X2+5X+6→YSTOP:SJMPSTOP讨论:有时仔细分析问题,可以将程序变得更简单,如上题中y=x2+5x+6=(x+2)(x+3),则程序为XDATA30HYDATA31HMOVA,XADDA,#2MOVB,A;(x+2)INCA;(x+3)MULABMOVY,A;X2+5X+6→YSTOP:SJMPSTOP4-10编一程序段,完成逻辑函数L=的计算。提示:此程序按照51汇编程序标准格式编写,整个程序构成一个完整结构,单片机运行时将反复执行该程序,即当输入变量发生变化时,输出逻辑函数L将立刻发生相应的变化。XBITP1.0YBITP1.1ZBITP1.2;分别定义变量X,Y,Z由P1口的低三位(P1.0,P1.1,P1.2)输入LBITP1.7;定义函数L由P1.7输出ORG0;用户程序第一条指令必须放在程序存储器0000H单元中LJMPMAIN;此处安排一条长调换指令,跳到主程序处,目的:避开03H开始的中断入口ORG200H;主程序安排在程序存储器200H单元开始MAIN:MOVC,XANLC,/YANLC,ZCPLCMOVL,CSJMPMAIN;真正的实用程序必须构成一个死循环结构,使得单片机可以反复地执行;用户设定的功能讨论一:若上列函数改为L=XY+XZ+YZ,如何编程,给两个答案,自己比较体会!MOVC,XANLC,YMOVF0,C MOVC,XANLC,ZORLC,F0MOVF0,CMOVC,YANLC,ZORLC,F0MOVL,CMOVC,XANLC,YJCOUTMOVC,XANLC,ZJCOUTMOVC,YANLC,ZOUT:MOVL,C讨论二:若上列函数改为L=(X+Y)(X+Z)(Y+Z),如何编程,给两个答案,结合讨论一自己比较体会!MOVC,XORLC,YMOVF0,CMOVC,XORLC,ZANLC,F0MOVF0,CMOVC,YORLC,ZANLC,F0MOVL,CMOVC,XORLC,YJNCOUTMOVC,XORLC,ZJNCOUTMOVC,YORLC,ZOUT:MOVL,C4-11阅读下列各程序段,并说明其功能。START:MOVDPTR,#1000H MOVR7,#10MOVXA,@DPTRMOVB,A;取出外部RAM单元1000H单元中的数送入BLOOP:INCDPTR;每次循环逐个取出外部RAM单元1001H开始的单元中的内容MOVXA,@DPTRCJNEA,B,COMP;比较(A)和(B),无论是否相等,均转向下条指令,判断Cy位COMP:JCNEXT;Cy=1,则(A)<(B),不作处理,直接进下个循环,取下个数据判断MOVB,A;若Cy=0,则(A)≥(B),将(A)→BNEXT:DJNZR7,LOOPSTOP:SJMPSTOP功能:判断外部数据寄存器1000H开始的11个单元中的最大值,将最大值送入寄存器B。START:MOVR2,#0MOVR7,#8MOVA,R3;(R3)→ACCLOOP:RLCA;8次循环,每次循环,将R3中的内容由最低位开始,逐位移入CyJNCNEXT;Cy=0,则不做任何操作,直接进入下个循环INCR2;若上句条件不成立,即R3中移出的位=1,则(R2)+1→R2NEXT:DJNZR7,LOOPSTOP:SJMPSTOP功能:统计R3中1的个数,并将统计结果送入R2。START:MOV30H,#0MOVR0,#50HLOOP:MOVA,@R0CJNEA,#0FFH,NEXTSJMPSTOPNEXT:INC30HINCR0SJMPLOOPSTOP:SJMPSTOP功能:统计存放在内部数据存储器50H开始的数据块的长度(即数据块占多少个字节),数据块以0FFH为结束标志。4-12编一子程序,将一个非压缩8421BCD码(即单字节BCD码)转换成七段显示码。设0~9的BCD码对应的七段显示码分别为3FH、06H、6BH、4FH、66H、6DH、7DH、07H、7FH、6FH。进子程序前,BCD码被放在累加器ACC中;子程序运行后,相应的七段码也放在ACC中。(即入口参数和出口参数均在ACC中)。 ;BCD码转换成显示码;入口参数:子程序名CHSEG,单字节BCD码放在累加器ACC中;出口参数:七段显示码放在ACC中CHSEG:ADDA,#1;加上偏移量,偏移量为MOVCA,@A+PC指令与数据表首间的字节数MOVCA,@A+PCRET;单字节指令DB3FH,06H,6BH,4FH,66H,6DH,7DH,07H,7FH,6FH;数据表一般紧跟着RET指令有另一法,不需计算偏移量CHSEG:ADDA,#SEGTB-SSG;用标号表达式,让编译程序计算偏移量MOVCA,@A+PCSSG:RETSEGTB:DB3FH,06H,6BH,4FH,66H,6DH,7DH,07H,7FH,6FH4-13编一子程序,将一个0~9的七段显示码转换成对应的格雷码。0~9的格雷码请参阅本书表1-2。设进子程序前,七段显示码被放在内部数据存储器40H中;子程序运行后,相应的格雷码放在内部数据存储器50H中。(即入口参数为40H,出口参数为50H)。算法一提示:根据0~9的序号依次查出对应的显示码,然后与40H中的内容比较,如果相等,则根据当前序号查表得到对应的格雷码。;显示码转换成格雷码;入口参数:子程序名CHGRY,七段显示码被放在内部数据存储器40H中,影响ACC,B,Cy位;出口参数:格雷码放在内部数据存储器50H中CHGRY:PUSHACC;保护现场PUSHBPUSHPSWMOVB,#0;用B记录0~9的序号NEXT:MOVA,B;ADDA,#SEGTB-SSG;用标号表达式,让编译程序计算偏移量MOVCA,@A+PC;根据当前序号,查取对应的显示码SSG:CJNEA,40H,NEQ;比较取得的显示码与源单元中的显示码MOVA,B;如果相等,则根据当前序号,查取对应的格雷码ADDA,#GRYTB-SGRMOVCA,@A+PCSGR:MOV50H,A;将查取的格雷码送入目标单元POPPSW;恢复现场POPBPOPACCRET;返回NEQ:INCB;如果不想等,则将序号增1 ,查取下个显示码作比较SJMPNEXTSEGTB:DB3FH,06H,6BH,4FH,66H,6DH,7DH,07H,7FH,6FH;显示码表GRYTB:DB00H,01H,03H,02H,04H,05H,07H,06H,08H,09H;格雷码表算法二提示:直接将显示码转化成格雷码,程序烦了些,但方法很简单。;显示码转换成格雷码;入口参数:子程序名CHGRY,七段显示码被放在内部数据存储器40H中,影响ACC,Cy位;出口参数:格雷码放在内部数据存储器50H中CHGRY:PUSHACC;保护现场PUSHPSWMOVA,40HCJNEA,#3FH,NEQ0MOV50H,#00H;40H单元中的内容=0的显示码,则将0的格雷码送入50HNEQ0:CJNEA,#06H,NEQ1MOV50H,#01H;40H单元中的内容=1的显示码,则将1的格雷码送入50HNEQ1:CJNEA,#6BH,NEQ2MOV50H,#03H;40H单元中的内容=2的显示码,则将2的格雷码送入50HNEQ2:CJNEA,#4FH,NEQ3MOV50H,#02H;40H单元中的内容=3的显示码,则将3的格雷码送入50HNEQ3:CJNEA,#66H,NEQ4MOV50H,#04H;40H单元中的内容=4的显示码,则将4的格雷码送入50HNEQ4:CJNEA,#6DH,NEQ5MOV50H,#05H;40H单元中的内容=5的显示码,则将5的格雷码送入50HNEQ5:CJNEA,#7DH,NEQ6MOV50H,#07H;40H单元中的内容=6的显示码,则将6的格雷码送入50HNEQ6:CJNEA,#07H,NEQ7MOV50H,#06H;40H单元中的内容=7的显示码,则将7的格雷码送入50HNEQ7:CJNEA,#7FH,NEQ8MOV50H,#08H;40H单元中的内容=8的显示码,则将8的格雷码送入50HNEQ8:CJNEA,#6FH,QUITMOV50H,#09H;40H单元中的内容=9的显示码,则将9的格雷码送入50HQUIT:POPPSW;恢复现场 POPACCRET4-14编一子程序,完成两双字节无符号数相加。设加数和被加数分别放在0区寄存器R2、R3和R4、R5中,运算结果存放在0区寄存器R6、R7中。若运算结果发生进位,使00H位单元=1;反之,使00H位单元=0。;双字节无符号数相加;入口参数:子程序名NADD,加数和被加数分别放在0区寄存器R2、R3和R4、R5中,影响ACC,位Cy;出口参数:运算结果存放在0区寄存器R6、R7中,00H位单元存放双字节相加的进位标志NADD:PUSHACC;保护现场PUSHPSWMOVA,R2;(R2)+(R4)→R6ADDA,R4MOVR6,AMOVA,R3;(R3)+(R5)→R7ADDCA,R5MOVR7,AMOV00H,C;Cy→00HPOPPSWPOPACC;恢复现场RET4-15编制一子程序,完成10ms较精确延时功能。设系统时钟频率为24MHz。提示:时钟频率为24MHz,则每个机器周期T=0.5us,10ms延时即需要10000us/0.5us=20000=500×40个机器周期T。软件延时子程序,就是用循环结构反复执行一些指令,而指令执行时都需要时间,所以执行完该子程序后,即完成了延时功能。;软件延时10ms;入口参数:子程序名DELAY,影响2区寄存器R0,R1;出口参数:无DELAY:PUSHPSW;1TMOVPSW,#18H;1TMOVR0,#40;1TDL:MOVR1,#248;1T*40DL1:DJNZR1,DL1;2T*248*40=19840TNOP;1T*40DJNZR0,DL;2T*40POPPSW;1TRET;2T,总延时3T+40T+19840T+40T+80T+3T=20006T,误差6T=3us,相当准了4-16编制一子程序,将10个非压缩BCD码转换成5个压缩BCD 码。设进子程序前,非压缩BCD码被放在40H为首地址的内部数据存储器中;子程序运行后,压缩BCD码放在50H为首地址的内部数据存储器中。功能说明:若进子程序前40H~49H单元中的内容为01H,02H,03H,04H,05H,06H,07H,08H,09H,00H,则子程序运行后50H~54H中的内容为12H,34H,56H,78H,90H;BCD码压缩;入口参数:子程序名BCDCH,非压缩BCD码被放在40H为首地址的内部数据存储器中;影响ACC,2区寄存器R0,R1,R7;出口参数:压缩BCD码放在50H为首地址的内部数据存储器BCDCH:PUSHACC;保护现场PUSHPSWMOVPSW,#10H;设定当前工作寄存器区为2区MOVR0,#40H;R0指向源数据块首地址MOVR1,#50H;R1指向目标数据块首地址MOVR7,#5;转换5次LOOP:MOVA,@R0;前一单元内的BCD码送入ACC的高四位SWAPAINCR0;R0指向下个源数据ORLA,@R0;后一单元内的BCD码送入ACC的低四位,同时并未改变源数据MOV@R1,A;压缩BCD码送入目标地址INCR1;R1指向下个目标单元DJNZR7,LOOPPOPPSW;恢复现场POPACCRET;返回4-17编制一子程序,完成15个单字节补码数据按绝对值大小从小到大进行排队。设数据放在30H为首地址的内部数据存储器中。提示:排序的基础是比较!无论是对原码、补码还是绝对值排序,基本算法都可沿用无符号数冒泡法的算法,只是在读取数据时需对数据进行一些处理,或在比较两个数的大小时改变一下方法(比如符号位的判断)。补码按绝对值排序的算法我想到了两种(当然不排除有其它方法)。一种是将补码转换成原码,由于原码是在最高位表示符号,而其余各位表示数值部分(即绝对值),这样只需比较原码的低7位即可;或者直接将其中负数的补码转换成其相反数的补码(这样所有比较的数据均为正数的补码,形式上也就是其绝对值,转换的方法是连同符号位一起取反后加1,这种方法也适用于对-128的补码进行转换)。另一种方法,判断两个待比较数的符号,同号时相减,如果差数与减数异号,则被减数绝对值<减数绝对值;两数异号时相加,如果和与被加数异号(或与加数同号),则被加数绝对值<加数绝对值;无论加减,结果为0,则两数绝对值必定相同。;绝对值排序,算法一 ;入口参数:子程序名PAIXU,影响ACC,寄存器B,2区寄存器R0,R2,R3,标志位Cy,F0;出口参数:排序后数据仍放在30H开始的15个内部数据存储器单元中PAIXU:PUSHACC;保护现场PUSHPSWMOVPSW,#10H;设定2区寄存器区,同时0→F0MOVR3,#14;暂存比较次数→R3CLRF0;进入循环前,清除交换标志F0NEXT:MOVR0,#30H;首地址→R0MOVR2,13H;当前比较次数(R3)→R2LOOP:MOVA,@R0;取出前一个数CJNEA,#80H,LOP1;判断正负LOP1:JCFPOS;如果为正数,则不转换CPLA;如果是负数,取相反数补码INCA;即得负数的绝对值FPOS:MOVB,A;前数的绝对值→BINCR0;R0指向下个数MOVA,@R0CJNEA,#80H,LOP2LOP2:JCCOMP;如果是负数,取相反数补码CPLAINCA;后数的绝对值→ACCCOMP:CJNEA,B,NEQ;比较前后两绝对值SJMPNEXCH;后=前,不交换NEQ:JNCNEXCH;后>前,不交换SETBF0;后<前,交换位置,置标志F0MOVA,@R0;后数→ACCDECR0;R0指向前单元XCHA,@R0;后数→前单元,前数→ACCINCR0;R0恢复指向后单元MOV@R0,A;前数→后单元NEXCH:DJNZR2,LOOP;判断一次冒泡是否完成DECR3;修改每次冒泡中的比较次数JBCF0,NEXT;判断冒泡中有无交换,清除F0POPPSW;若上次冒泡中无交换,则排序完成POPACCRET对上述程序稍作改动,程序的效率就高了(每次比较时执行的指令少了,速度就快了)PAIXU:PUSHACCPUSHPSW MOVPSW,#10HMOVR3,#14CLRF0;进入循环前,清除交换标志F0NEXT:MOVR0,#30HMOVR2,13HMOVA,@R0CJNEA,#80H,LOP1LOP1:JCFPOSCPLAINCAFPOS:MOVB,ALOOP:INCR0MOVA,@R0CJNEA,#80H,LOP2LOP2:JCCOMPCPLAINCACOMP:CJNEA,B,NEQNEQ:JCEXCHXCHA,B;若不交换,则后>前,将后一绝对值(较大)送入B,作为下次比较的前一个绝对值SJMPNEXCHEXCH:SETBF0;置位交换标志MOVA,@R0;借助ACC交换前后两个数DECR0XCHA,@R0INCR0MOV@R0,ANEXCH:DJNZR2,LOOPDECR3;每冒泡一次,比较次数-1JBCF0,NEXTPOPPSWPOPACCRET;绝对值排序,算法二;入口参数:子程序名PAIXU2,影响ACC,寄存器B,2区寄存器R0,R2,R3,R4,标志位Cy,F0;出口参数:排序后数据仍放在30H开始的15个内部数据存储器单元中PAIXU2:PUSHACC;保护现场PUSHPSWMOVPSW,#10H;设定2区寄存器区,同时0→F0 MOVR3,#14;暂存比较次数→R3CLRF0;进入循环前,清除交换标志F0NEXT:MOVR0,#30H;首地址→R0MOVR2,13H;当前比较次数(R3)→R2LOOP:MOVA,@R0;取出前一个数MOVR4,A;前数送R4暂存INCR0;R0指向下个数MOVB,@R0XRLA,BJBACC.7,YH;如果前后数异号,转加法TH:MOVA,R4;如果前后数同号,则执行减法,将前数重新放入ACCCLRC;SUBBA,B;前数-后数JZNEXCH;差为0,即前绝对值=后绝对值,不交换XRLA,B;差值和减数异或,判断是否同号JBACC.7,NEXCH;如果差值和减数异号,则前绝对值<后绝对值,不交换SJMPEXCH;如果同号(即上句不成立),则转前后交换YH:MOVA,R4;前后数异号,执行加法,将前数重新放入ACCADDA,B;前数+后数JZNEXCH;和为0,即前绝对值=后绝对值,不交换XRLA,B;和与加数异或,判断是否同号JNBACC.7,NEXCH;如果和与加数同号,则前绝对值<后绝对值,不交换EXCH:SETBF0;前>后,交换位置,置标志F0MOVA,@R0;后数→ACCDECR0;R0指向前单元XCHA,@R0;后数→前单元,前数→ACCINCR0;R0恢复指向后单元MOV@R0,A;前数→后单元NEXCH:DJNZR2,LOOP;判断一次冒泡是否完成DECR3;修改每次冒泡中的比较次数JBCF0,NEXT;判断冒泡中有无交换,清除F0POPPSW;若上次冒泡中无交换,则排序完成POPACCRET4-18编制一子程序,将内部数据存储器30H~39H单元的数据连起来向左移动一位,39H最低位添0。;10个单元数据块左移一位子程序;入口参数:子程序名MBRL1,数据块位于30H~39H单元,影响ACC,3区寄存器R0,标志位Cy;出口参数:移位后数据仍位于30H~39H单元中MBRL1:PUSHPSW;保护PSW内容PUSHACC;保护ACC内容 MOVPSW,#18H;设置3区为当前工作寄存器区,同时清除Cy位MOVR0,#39H;数据块尾地址送R0LOOP:MOVA,@R0;单元数据送ACCRLCA;带进位左移DECR0;R0指向前一个单元CJNER0,#2FH,LOOP;判断R0是否已指向2FH(即30H已移位完成)POPACC;恢复ACCPOPPSW;恢复PSWRET;返回END方法2:将上述子程序修改一下,可以适用m个单元左移n位的功能。;m个单元数据块左移n位子程序;入口参数:子程序名MBRLN,数据块起始地址在R0中,数据块长度m放在R6中,移位数n放在R7中;影响ACC,寄存器B,标志位Cy;出口参数:移位后R0指向数据块起始地址MBRLN:PUSHPSW;保护PSW内容PUSHACC;保护ACC内容PUSHB;保护B内容MOVB,R6;数据块长度m暂存入寄存器BNEXT:MOVR6,B;数据块长度m重新赋值给R6MOVA,R0ADDA,R6DECA;数据块首地址+m-1=数据块尾地址→ACCMOVR0,A;R0指向数据块尾地址CLRC;清除Cy位LOOP:MOVA,@R0RLCADECR0DJNZR6,LOOP;内层循环完成m个单元左移一位INCR0;使R0指向数据块首地址DJNZR7,NEXT;外层循环完成n次移一位,即移动n位POPB;恢复现场POPACCPOPPSWRET;返回END第五章习题答案5-1.中断申请信号如何才能被CPU检测到? 答:首先需中断系统开放(1→EA),然后相应的中断源需开放(即相关的标志EX0、ET0、EX1、ET1、ES、ET2需置1)5-2.中断响应时CPU需要做哪些事情?答:先将被响应的中断源所属的优先级存入优先级状态触发器;再将PC当前值(即断点)压入堆栈(先PCL,后PCH),然后将被响应中断源对应的中断入口地址送入PC。5-3.中断入口与中断服务子程序入口有什么区别?答:中断入口指的是当一个中断被响应时,由CPU自动调用的程序存储器的某个单元地址,这些地址是按不同中断源预先安排好的;而中断服务子程序入口指的是用户编制的中断服务子程序的第一条指令在程序存储器中存放的地址,两者一般来讲是不一样的,通常会在中断入口处安排一条跳转指令(LJMP或AJMP)指向中断服务子程序的入口。5-4.89C52单片机中有哪些中断源?它们的中断申请标志分别是什么?答:外部中断0,标志IE0定时器/计数器T0中断,标志TF0外部中断1,标志IE1定时器/计数器T1中断,标志TF1串行口中断,标志RI、TI定时器/计数器T2中断,标志TF2、EXF25-5.若在某一个89C52单片机应用系统中,在系统初始化中将特殊功能寄存器IE和IP分别设置为10101111B和00101100B。当该系统正在运行时,问:•如果外部中断1和定时器/计数器1同时申请中断,CPU将为哪一个中断源服务?为什么?•如果CPU正在执行外部中断0的中断服务子程序,这时CPU还能响应系统哪些中断源的中断申请?为什么?提示:根据IE,IP的内容可知,当前开放的中断源为外部中断0,T0中断,外部中断1,T1中断,T2中断;其中外部中断1,T1中断,T2中断为高级中断,外部中断0,T0中断为低级中断。答:1)如果外部中断1和定时器/计数器1同时申请中断,CPU将为外部中断1服务,因为它们同属高级中断,而在硬件查询序列中外部中断1排在T1前。2)由于外部中断0为低级中断,所以它的中断过程可以被其它任何高级中断源打断,在此处即CPU还能响应外部中断1,T1,T2的中断申请。5-6.若在某一个单片机应用系统中,有一个外部中断1,中断级别为低级中断,中断申请信号为脉冲信号,中断服务子程序的首地址为1100H,中断服务子程序的任务是将P1口的数据传递至外部数据存储器2400H单元。编制初始化程序及中断服务子程序。ORG0;主程序入口LJMPMAIN;跳转到用户程序ORG13H;外部中断1入口LJMPX1IPG;跳转到中断服务子程序入口ORG100H;用户程序入口地址MAIN:MOVSP,#60H;堆栈指针初始化 SETBIT1;外部中断1设为脉冲模式SETBEA;允许中断SETBET1;开放外部中断1CLRPT1;外部中断1设为低级中断SJMP$;主程序原地等待,等待中断发生(即表示CPU可以做任何其它事情)ORG1100H;中断服务子程序入口X1IPG:PUSHACC;保护现场(由于ACC和DPTR被使用,所以先要对其原先内容进行保护)PUSHDPLPUSHDPHMOVDPTR,#2400HMOVA,P1MOVX@DPTR,A;(P1)→2400HPOPDPH;恢复现场(即退出中断前,恢复ACC,DPTR中原来的内容)POPDPLPOPACCRETI;中断返回指令END5-7.有一个单片机实验系统,实验线路如实验八所示。要求编制一程序,当开关5发出一脉冲信号时,程序由此转入中断服务子程序,该中断服务子程序的任务是将P1口的内容取反,然后返回到主程序。分析:由实验八(105页)可知,开关5接在(P3.2)引脚上,故该实验其实是编制一个带外部中断0的程序。并且由于开关5发出的是脉冲信号,所以外部中断0必须工作在边沿触发方式。ORG0;主程序入口LJMPMAINORG3;外部中断0入口CPLP1RETI;由于中断服务子程序的内容较少(只有两条指令,占3个字节),所以直接安排在入口处ORG200HMAIN:MOVSP,#60H;堆栈指针初始化SETBIT0;外部中断0边沿触发方式SETBEA;开放外部中断0SETBEX0SJMP$;主程序在此循环等待,等待中断发生第六章习题答案6-1.单片机的定时器/计数器具有哪些功能?答:定时/计数器T0,T1 具有一般的定时和计数的功能。当它们对内部机器周期信号进行计数时,由于此信号的周期时确定的,则此时它们实现的是定时器功能;当它们对外部脉冲信号进行计数时,它们实现的是计数器的功能。另外,T1可作为串行通讯时的波特率发生器。T2是一个高级CTC,其具有四个功能:自动装入初值的定时器/计数器、捕捉外部信号、信号发生器、串行通讯的波特率发生器。6-2.请说明CTC的定时器工作方式的工作原理。答:当CTC设置成对内部信号计数时,由于该内部计数信号的周期和频率是确定的(频率为fosc/12,周期即为一个机器周期),所以其计入信号的个数就能换算成时间,在实际使用中,一般根据定时的需要,先给CTC一个初值,然后启动其计数工作,当其计数溢出时会置1溢出标志,产生一个定时信号。6-3.请说明T2捕捉工作模式的工作原理、答:略,参见113页。大致原理:外部信号(P1.1脚)每来一个下降沿,便触发一次中断,同时记录下当前定时器T2计数值,这样可通过对相邻两次中断(即两个相邻的脉冲)时记录下来的计数值相减,便可得该脉冲信号的周期。其实这种功能也可通过T0,T1实现,只不过T2功能更强,实现起来相对容易。6-4.若系统时钟的频率为fosc=6MHZ,请分析T1工作在模式1和模式2时,定时器最长的定时时间分别为多少?答:已知fosc=6MHZ,故机器周期=12/fosc=2usT1在模式1时为16位计数器,当其工作在定时方式(即作为定时器使用)时,每个机器周期加1,则其最长定时时间为216=65536个机器周期=131072(us)=131.072(ms)。T1在模式2时为自动装入初值的8位计数器,当其工作在定时方式(即作为定时器使用)时,每个机器周期加1,则其最长定时时间为28=256个机器周期=512(us)。6-5.已知系统时钟频率为fosc=6MHZ,若要求T1在模式1进行5ms定时,采用内部启动。请计算T1计数器的初值a,并对T1进行初始化编程。答:由上题计算可知,当fosc=6MHZ时,T1在模式1最大定时为131.072ms>5ms,所以T1在模式1可满足5ms定时需要。初值计算:a=216-T定时/T机器=216-T定时×fosc/12=65536-5ms×6MHz/12=65536-5000/2=63036=F63CH初始化编程INIT:MOVTMOD,#10H;T1工作在定时器方式,内部启动,模式1(即TMOD=0001XXXXB)MOVTH1,#0F6H;T1装入初值aMOVTL1,#3CHSETBTR1;启动T1计时6-6.已知系统时钟频率为fosc=6MHZ,若要求T0在模式2进行250us定时,采用外部启动。请计算T0计数器的初值a,并对T0进行初始化编程。答:由上题计算可知,当fosc=6MHZ时,T0在模式2最大定时为512us>250us,所以T0在模式2可满足250us定时需要。 初值计算:a=28-T定时/T机器=256-250us/2us=256-125=131=83H初始化编程INIT:MOVTMOD,#0AH;T0工作在定时器方式,外部启动,模式2(即TMOD=XXXX1010B)MOVTL0,#83H;T0装入初值aMOVTH0,#83H;模式2时,TH0必须和TL0装入同样的初值,以便在溢出时自动重装初值。SETBTR0;准备接收外部启动命令6-7.已知系统时钟频率为fosc=24MHZ,若要求T0在模式1计数器方式,计满500个信号,向CPU提出中断申请,采用内部启动。问该系统对外部计数信号的频率最高是多少?请计算T0计数器的初值a,并对T0进行初始化编程。答:在计数器方式下,T0每个机器周期采集一次P3.4引脚上的电平信号,当前一次采集到低电平而后一次采集到高电平(即相邻两次采集捕捉到一个上升沿)时,T0加1;因此为了有效的捕捉到外部计数信号的上升沿,对信号有如下要求:外部信号的高电平和低电平都必须维持1个机器周期以上(即高低电平的脉宽都必须不小于1个机器周期);由前一条件可知,外部计数信号的频率不得高于fosc/24(即外部计数信号的周期必须不小于2个机器周期)!由以上分析可知:外部计数信号的频率最高为fosc/24=1MHZ。计数方式下的初值计算:a=216-C所需计数=65536-500=65036=FE0CH初始化编程:ORG0LJMPINIT;转到用户编制的初始化程序起始处ORG0BH;T0中断入口地址LJMPT0IPG;转到T0中断服务子程序入口ORG100H;此处假设初始化程序从程序存储器100H处开始INIT:MOVTMOD,#05H;设置T0为内部启动,计数方式,模式1(TMOD=XXXX0101B)MOVTH0,#0FEH;装入初值MOVTL0,#0CH;SETBEA;允许T0中断SETBET0SETBTR0;启动T0计数SJMP$;原地等待(表示CPU可做其它工作),等待T0计数溢出中断发生。ORG400H;假设T0中断服务子程序从程序存储器400H处开始T0IPG:ORLTL0,#0CH;重装初值,不用MOV指令可消除误差,为什么,自己想一下。MOVTH0,#0FEH……;中断服务子程序需完成的实际动作RETI;由中断返回END 说明:既然用到了中断,就必须对中断系统进行相关的初始化操作,以上程序中粗体部分为必须完成的初始化内容。6-8.已知系统时钟频率为fosc=24MHZ,若要求T2工作在初值自动装入的定时/计数器工作模式0,进行50ms定时,每隔50ms向CPU申请一次中断。请计算T2计数器的初值a,并对T2进行初始化编程。分析:T2工作在初值自动装入的定时/计数器模式0,即16位初值自动装入计数器,由于fosc=24MHZ时,其最大定时时间为65536*0.5us=32.768ms<50ms,所以本题出错了,无解。若fosc=12MHZ,可参见书上例6-6。6-9.若有某51系列的单片机应用系统,试编制程序,分别采用三种方式使得P1.0上产生周期为200us的方波。方法1是将T1设置在模式1的定时器方式;方法2是将T1设置在模式2的定时器方式;方法3是将T2设置在信号发生器模式。设时钟频率为fosc=12MHZ。分析算法:方波周期200us,即每过100us后,P1.0的状态变化一次。方法1:初值a=65536-100us×12MHz/12=65436=FF9CHORG0LJMPMAINORG1BHLJMPT1IPGORG200HMAIN:MOVTMOD,#10H;T1内部启动,定时方式,模式1MOVTL1,#9CH;装入初值MOVTH1,#0FFHMOVSP,#60H;堆栈指针初始化SETBEA;允许T1中断SETBET1SETBTR1;启动T1定时SJMP$;等待中断发生,也表示CPU可以去做任何其它事情!ORG400HT1IPG:CPLP1.0;取反P1.0ORLTL1,#9CH;重装T1初值MOVTH1,#0FFHRETI;中断返回END方法2:初值a=256-100us×12MHz/12=9CH,在此例中不采用中断,用软件查询完成定时,同学们可比较一下它们的区别。ORG0LJMPMAINORG200HMAIN:MOVTMOD,#20H;T1内部启动,定时方式,模式2MOVTL1,#9CH;模式2下,TL1、TH1必须装入相同的初值。MOVTH1,#9CH SETBTR1WAIT:JNBTF1,WAIT;等待T1溢出(TF1=1)CPLP1.0;T1溢出后(即100us到),取反P1.0CLRTF1;清除溢出标志TF1SJMPWAIT;返回WAIT处,等待下次溢出END方法2的程序中有以下几点需要注意:•如果使用T1中断,则溢出标志TF1在中断响应时由硬件自动清零,而当使用软件查询方法(即用指令JNB或JB来判断TF1状态)时,必须由程序清零(即CLRTF1)。•模式2为自动装入初值模式,故在溢出产生后,不必用指令重新装入初值!•使用查询方式,占用了CPU资源,CPU不能再执行其它功能,如果一定要执行其它功能的指令,则将不能及时地对TF1进行判断,一定会影响到方波输出的精度,所以用T0或T1产生定时时,一般总是使用其溢出中断。方法3:因为T2工作在信号发生器模式下,由f信号=fosc/(4*(216-a)),所以初值a=216-fosc/4f信号因为方波周期为200us,即f信号=0.005MHz所以a=65536-12/(4*0.005)=64936=FDA8HORG0LJMPMAINORG200HMAIN:MOVT2CON,#00HMOVT2MOD,#02H;将T2设置为信号发生器方式,不需要T2中断即可完成信号发生功能MOVTL2,#0A8H;设置计数器初值MOVTH2,#0FDHMOVRCAP2L,#0A8H;设置重装寄存器初值MOVRCAP2H,#0FDHSETBTR2;启动T2定时SJMP$;等待,也表示CPU可以去做任何其它事情!END6-10.若有某51系列单片机应用系统,要求其利用T0的定时,编一个程序使得P1.2上产生周期为1S,脉冲宽度为100ms的脉冲波。设时钟频率为fosc=12MHZ。分析:脉冲宽度指的是高电平的时间,即P1.2输出1,保持100ms,然后P1.2输出0,保持900ms。已知fosc=12MHZ,则机器周期=1us,所以T0在模式1和模式2下分别可定时的最大时间为65536us和256us。无论何种模式都不能在一次定时中完成100ms的定时,故可采用模式1产生50ms(即50000us)定时中断,连续两次中断即完成了100ms定时,然后再连续18次中断即完成了900ms定时。计算初值:a=65536-T定时×12/fosc=65536-50000=3CB0H程序:ORG0;用户程序入口 LJMPMAIN;转到主程序入口ORG0BH;T0中断入口LJMPT0IPG;转到T0中断服务子程序入口ORG200HMAIN:MOVTMOD,#01H;T0工作在内部启动,定时方式,模式1MOVTL0,#0B0H;装入初值3CB0HMOVTH0,#3CHMOVIE,#82H;允许T0中断,此处假定其它中断均被禁止MOVSP,#60H;堆栈指针初始化SETBP1.2;设定P1.2的初始状态为高电平输出MOVR0,#2;设置连续中断次数计数器R0(由于P1.2初始为高电平,所以R0=2);以上两条指令也可这样CLRP1.2P1.2初始为低电平,所以R0=18;MOVR0,#18SETBTR0;启动T0计时SJMP$;原地等待T0中断ORG400H;中断服务子程序入口T0IPG:DJNZR0,QUIT;判断连续中断次数到否,若未到,则直接返回JBP1.2,LOW;若已到连续中断次数,则判断P1.2当前状态SETBP1.2;若P1.2当前状态为0,则1→P1.2MOVR0,#2;将R0设为P1.2输出高电平时的连续中断次数(2)SJMPQUIT;由中断返回LOW:CLRP1.2;若P1.2当前状态为1,则0→P1.2MOVR0,#18;将R0设为P1.2输出低电平时的连续中断次数(18)QUIT:ORLTL0,#0B0H;返回前重装计数初值MOVTH0,#3CHRETI;由中断服务子程序返回END注:可将T0IPG优化如下ORG400H;中断服务子程序入口T0IPG:DJNZR0,QUIT;判断连续中断次数到否,若未到,则直接返回CPLP1.2;连续计数到后,先对P1.2取反JNBP1.2,LOW;若P1.2取反后为0,则转到LOW,对R0赋值18MOVR0,#2;若P1.2取反后为1(即上条指令条件不成立),则对R0赋值2SJMPQUIT;由中断返回LOW:MOVR0,#18;将R0设为P1.2输出低电平时的连续中断次数(18)QUIT:ORLTL0,#0B0H;返回前重装计数初值MOVTH0,#3CHRETI;由中断服务子程序返回END附加题1:用T0测量外部正脉冲的宽度,脉冲信号由(P3.2)输入,假设系统fosc=12MHZ,待测脉冲宽度<65.536ms,将测量结果送入R2R3。 分析:测量脉冲宽度可借助于T0的外部启动定时方式,因为T0的外部启动信号就是(P3.2)上的高电平,故可将T0初值设为0,当外部启动信号到来后,T0开始计时;而当(P3.2)上信号变为低电平时T0停止计时,同时此信号的下降沿可触发外部中断0,用外部中断0的中断服务程序读取T0的当前值。ORG0LJMPMAINORG3LJMPX0IPGORG200HMAIN:MOVSP,#50H;堆栈指针初始化MOVTMOD,#09H;T0外部启动,定时器方式,模式1MOVTH0,#0;TH0、TL0初值为0MOVTL0,#0SETBIT0;外部中断0边沿触发模式SETBEA;开放中断SETBEX0;允许外部中断0SETBTR0;T0内部启动信号置1,准备好接收外部启动信号(即P3.2引脚上的高电平)SJMP$;等待中断发生ORG400HX0IPG:MOVR3,#TL0;将刚过去的那个高电平的宽度送入R2,R3MOVR2,#TH0MOVTH0,#0;TH0、TL0重装初值为0,为下次测量作好准备MOVTL0,#0RETIEND若上题中被测信号的宽度大于65.536ms,即可能超过两个字节,我们假定其结果不超过3个字节(即在fosc=12MHZ的条件下,被测信号宽度小于16777.216ms),这时为正确记录整个宽度,必须借助一个高位字节寄存器记录第三字节的内容,当T0计时溢出时,该寄存器加1。程序修改如下(设结果放入R1,R2,R3)ORG0LJMPMAINORG3;外部中断0入口LJMPX0IPGORG11;T0中断入口INC30H;T0每溢出一次,高位字节寄存器30H加1RETI;由T0中断返回ORG200HMAIN:MOVSP,#50H;堆栈指针初始化MOVTMOD,#09H;T0外部启动,定时器方式,模式1MOV30H,#0;清除高位字节寄存器 MOVTH0,#0;TH0、TL0初值为0MOVTL0,#0SETBIT0;外部中断0边沿触发模式SETBEA;开放中断SETBEX0;允许外部中断0SETBET0;允许T0中断SETBTR0;T0内部启动信号置1,准备好接收外部启动信号(即P3.2引脚上的高电平)SJMP$;等待中断发生ORG400HX0IPG:MOVR3,#TL0;将刚过去的那个高电平的宽度送入R1,R2,R3MOVR2,#TH0MOVR1,30HMOVTH0,#0;TH0、TL0重装初值为0,为下次测量作好准备MOVTL0,#0MOV30H,#0;清除高位字节寄存器RETI附加题2:用T0测量外部脉冲信号的周期,脉冲信号由(P3.2)输入,假设系统fosc=12MHZ,待测脉冲周期<65.536ms,将测量结果送入R2R3。分析:测量信号周期可借助T0的内部定时方式来完成,当外部脉冲信号的第一个下降沿到来时,触发中断,中断服务子程序启动T0计时(T0的初值预设为0);当第二个下降沿再次触发中断时,中断服务子程序将T0当前值寄存器(TH0,TL0)的内容送入结果单元R2,R3,同时清零TH0,TL0,作为下一次测量的起点;当第三个下降沿触发中断时,中断服务子程序重复第二次中断的动作,即输出结果,清零TH0,TL0。依此类推,子子孙孙无穷匮矣。ORG0LJMPMAINORG3LJMPX0IPGORG200HMAIN:MOVSP,#50H;堆栈指针初始化MOVTMOD,#01H;T0内部启动,定时器方式,模式1MOVTH0,#0;TH0、TL0初值为0MOVTL0,#0SETBIT0;外部中断0边沿触发模式SETBEA;开放中断SETBEX0;允许外部中断0SJMP$;等待中断发生ORG400HX0IPG:JBTR0,OUT;TR0=1,标志T0已开始计时动作,所以可将结果输出 SETBTR0;若上式不成立,则TR0=0,表示这是第一次进入中断,开启T0计时,然后返回SJMPQUITOUT:MOVR3,#TL0;将刚过去的那个信号周期送入R2,R3MOVR2,#TH0MOVTH0,#0;TH0、TL0重装初值为0,为下次测量作好准备MOVTL0,#0QUIT:SETBTR0RETI第八章习题答案8-1.如将例8-1图(P155,图8-4)中存储器芯片27128上CE引脚接8031单片机的P2.7,请分析其地址空间?答:该27128有两个地址空间,分别是0~3FFFH和4000~7FFFH。8-2.如将例8-4图(P161,图8-8)中三块存储器芯片上CE引脚接译码器Y1,Y2,Y3,请分析其地址空间?答:I:2000H~3FFFHII:4000H~5FFFHIII:6000H~7FFFH8-3.用8KB×8的EPROM和SRAM芯片扩展16KB容量的程序存储器和数据存储器,问各需要几块;如要求程序存储器地址范围为8000~BFFFH,数据存储器地址范围为C000H~FFFFH,画出连线图。答:需要两块8KB的EPROM和两块8KB的SRAM芯片。因为扩展的存储器地址范围为连续分布的,故只能用码选法扩展。下图说明:1、2为8KBEPROM(程序存储器),1的地址为8000~9FFFH,2的地址为A000~BFFFH,3、4为8KBSRAM(数据存储器),3的地址为C000~DFFFH,4的地址为E000~FFFFH由于外部程序存储器的起始地址为8000H,故必须使用内部程序存储器,所以单片机EA端需接高电平。另74LS138的接法也可以很灵活,可将P2.7接G1,C端接地,则可将Y0,Y1,Y2,Y3分别接1,2,3,4芯片。74LS138 +5VG1Y7G2AY6G2BY5Y4CY3BY2AY1Y0P2.7P2.6P2.5P2.4~P2.0 ALEP0.7~P0.0PSENWREARD答:I:2000H~3FFFHII:4000H~5FFFHIII:6000H~7FFFH74LS373+5V4321A12~A0CEOEWED7~D0O7~O0GED7~D0GNDA11~A0CEOEWED7~D0A12~A0CEOEWED7~D0A12~A0CEOED7~D0A12~A0CEOED7~D0'