ORG 1100H ;中断服务子程序入口 X1IPG: PUSH ACC ;保护现场(由于ACC和DPTR被使用,所以先要对其原先内容进行保护) PUSH DPL PUSH DPH MOV DPTR,#2400H MOV A, P1 MOVX @DPTR , A ;(P1)→2400H POP DPH ;恢复现场(即退出中断前,恢复ACC,DPTR中原来的内容) POP DPL POP ACC RETI ;中断返回指令 END
5-7.有一个单片机实验系统,实验线路如实验八所示。要求编制一程序,当开关5发出一脉冲信号时,程序由此转入中断服务子程序,该中断服务子程序的任务是将P1口的内容取反,然后返回到主程序。 分析:由实验八(105页)可知,开关5接在
(P3.2)引脚上,故该实验其实是编制一个带外部中断0的
程序。并且由于开关5发出的是脉冲信号,所以外部中断0必须工作在边沿触发方式。 ORG 0 ;主程序入口 LJMP MAIN ORG 3 ;外部中断0入口 CPL P1 RETI ; 由于中断服务子程序的内容较少(只有两条指令,占3个字节),所以直接安排在入口处 ORG 200H
MAIN: MOV SP, #60H ;堆栈指针初始化 SETB IT0 ;外部中断0边沿触发方式 SETB EA ;开放外部中断0 SETB EX0 SJMP $ ;主程序在此循环等待,等待中断发生
第六章习题答案
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=2us
T1在模式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定时需要。
1616
初值计算:a=2- T定时/T机器=2- T定时×fosc/12=65536-5ms×6MHz/12=65536-5000/2=63036=F63CH 初始化编程
INIT: MOV TMOD,#10H ;T1工作在定时器方式,内部启动,模式1(即TMOD=0001XXXXB) MOV TH1, #0F6H ;T1装入初值a MOV TL1, #3CH SETB TR1 ;启动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: MOV TMOD,#0AH ;T0工作在定时器方式,外部启动,模式2(即TMOD=XXXX1010B) MOV TL0, #83H ;T0装入初值a MOV TH0, #83H ; 模式2时,TH0必须和TL0装入同样的初值,以便在溢出时自动重装初值。 SETB TR0 ;准备接收外部启动命令
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=2-C所需计数=65536-500=65036=FE0CH
初始化编程: ORG 0 LJMP INIT ;转到用户编制的初始化程序起始处 ORG 0BH ;T0中断入口地址 LJMP T0IPG ;转到T0中断服务子程序入口 ORG 100H ;此处假设初始化程序从程序存储器100H处开始
INIT: MOV TMOD, #05H ;设置T0为内部启动,计数方式,模式1(TMOD=XXXX0101B) MOV TH0, #0FEH ;装入初值 MOV TL0, #0CH ; SETB EA ;允许T0中断 SETB ET0
16
SETB TR0 ;启动T0计数 SJMP $ ;原地等待(表示CPU可做其它工作),等待T0计数溢出中断发生。 ORG 400H ;假设T0中断服务子程序从程序存储器400H处开始
T0IPG: ORL TL0, #0CH ;重装初值,不用MOV指令可消除误差,为什么,自己想一下。 MOV TH0, #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=FF9CH ORG 0 LJMP MAIN ORG 1BH LJMP T1IPG ORG 200H
MAIN: MOV TMOD, #10H ;T1内部启动,定时方式,模式1 MOV TL1, #9CH ;装入初值
MOV TH1, #0FFH
MOV SP, #60H ;堆栈指针初始化
SETB EA ;允许T1中断
SETB ET1 SETB TR1 ;启动T1定时 SJMP $ ;等待中断发生,也表示CPU可以去做任何其它事情! ORG 400H T1IPG: CPL P1.0 ;取反P1.0 ORL TL1, #9CH ;重装T1初值 MOV TH1, #0FFH RETI ;中断返回 END
方法2:初值a=256-100us×12MHz/12=9CH,在此例中不采用中断,用软件查询完成定时,同学们可比较一下它们的区别。 ORG 0 LJMP MAIN ORG 200H
MAIN: MOV TMOD, #20H ;T1内部启动,定时方式,模式2 MOV TL1, #9CH ;模式2下,TL1、TH1必须装入相同的初值。
MOV TH1, #9CH
SETB TR1
WAIT: JNB TF1, WAIT ;等待T1溢出(TF1=1)
CPL P1.0 ;T1溢出后(即100us到),取反P1.0 CLR TF1 ;清除溢出标志TF1 SJMP WAIT ;返回WAIT处,等待下次溢出 END
方法2的程序中有以下几点需要注意:
1) 如果使用T1中断,则溢出标志TF1在中断响应时由硬件自动清零,而当使用软件查询方法(即用指令
JNB或JB来判断TF1状态)时,必须由程序清零(即CLR TF1)。
2) 模式2为自动装入初值模式,故在溢出产生后,不必用指令重新装入初值!
3) 使用查询方式,占用了CPU资源,CPU不能再执行其它功能,如果一定要执行其它功能的指令,则将
不能及时地对TF1进行判断,一定会影响到方波输出的精度,所以用T0或T1产生定时时,一般总是使用其溢出中断。
方法3:因为T2工作在信号发生器模式下,由f信号=fosc/(4*(216-a)),所以初值a=216-fosc/4 f信号 因为方波周期为200us,即f信号=0.005MHz 所以a=65536-12/(4*0.005)=64936=FDA8H ORG 0 LJMP MAIN ORG 200H
MAIN: MOV T2CON, #00H MOV T2MOD, #02H ;将T2设置为信号发生器方式,不需要T2中断即可完成信号发生功能
MOV TL2, #0A8H ;设置计数器初值 MOV TH2, #0FDH
MOV RCAP2L, #0A8H ;设置重装寄存器初值 MOV RCAP2H, #0FDH
SETB TR2 ;启动T2定时 SJMP $ ;等待,也表示CPU可以去做任何其它事情! END
6-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 程序:
ORG 0 ;用户程序入口 LJMP MAIN ;转到主程序入口 ORG 0BH ;T0中断入口 LJMP T0IPG ;转到T0中断服务子程序入口 ORG 200H
MAIN: MOV TMOD, #01H ;T0工作在内部启动,定时方式,模式1 MOV TL0, #0B0H ;装入初值3CB0H MOV TH0, #3CH MOV IE, #82H ;允许T0中断,此处假定其它中断均被禁止 MOV SP, #60H ;堆栈指针初始化 SETB P1.2 ;设定P1.2的初始状态为高电平输出 MOV R0, #2 ;设置连续中断次数计数器R0(由于P1.2初始为高电平,所以R0=2) ;以上两条指令也可这样CLR P1.2 P1.2初始为低电平,所以R0=18 ; MOV R0, #18
SETB TR0 ;启动T0计时
相关推荐: