试用定时器中断方式设计一个程序,使发光二极管每秒内亮400ms,灭600ms。设单片机的振荡频率为6MHz.

试用定时器中断方式设计一个程序,使发光二极管每秒内亮400ms,灭600ms。设单片机的振荡频率为6MHz.,第1张

我先贴个类似程序你改一下就可以了用AT89S51的定时/计数器T0产生2秒钟的定时,每当2秒定时到来时,更换指示灯闪烁,每个指示闪烁的频率为02秒,也就是说,开始L1指示灯以02秒的速率闪烁,当2秒定时到来之后,L2开始以02秒的速率闪烁,如此循环下去。02秒的闪烁速率也由定时/计数器T0来完成。p1口接LED。

(1. 由于采用中断方式来完成,因此,对于中断源必须它的中断入口地址,对于定时/计数器T0来说,中断入口地址为000BH,因此在中断入口地方加入长跳转指令来执行中断服务程序。书写汇编源程序格式如下所示:

ORG 00H

LJMP START

ORG 0BH ;定时/计数器T0中断入口地址

LJMP INT_T0

START: NOP ;主程序开始

INT_T0: PUSH ACC ;定时/计数器T0中断服务程序

PUSH PSW

POP PSW

POP ACC

RETI ;中断服务程序返回

END

(2. 定时2秒,采用16位定时50ms,共定时40次才可达到2秒,每50ms产生一中断,定时的40次数在中断服务程序中完成,同样02秒的定时,需要4次才可达到02秒。对于中断程序,在主程序中要对中断开中断。

(3. 由于每次2秒定时到时,L1-L4要交替闪烁。采用ID来号来识别。当ID=0时,L1在闪烁,当ID=1时,L2在闪烁;当ID=2时,L3在闪烁;当ID=3时,L4在闪烁

6. 汇编源程序

TCOUNT2S EQU 30H

TCNT02S EQU 31H

ID EQU 32H

ORG 00H

LJMP START

ORG 0BH

LJMP INT_T0

START: MOV TCOUNT2S,#00H

MOV TCNT02S,#00H

MOV ID,#00H

MOV TMOD,#01H

MOV TH0,#(65536-50000) / 256

MOV TL0,#(65536-50000) MOD 256

SETB TR0

SETB ET0

SETB EA

SJMP $

INT_T0: MOV TH0,#(65536-50000) / 256

MOV TL0,#(65536-50000) MOD 256

INC TCOUNT2S

MOV A,TCOUNT2S

CJNE A,#40,NEXT

MOV TCOUNT2S,#00H

INC ID

MOV A,ID

CJNE A,#04H,NEXT

MOV ID,#00H

NEXT: INC TCNT02S

MOV A,TCNT02S

CJNE A,#4,DONE

MOV TCNT02S,#00H

MOV A,ID

CJNE A,#00H,SID1

CPL P10

SJMP DONE

SID1: CJNE A,#01H,SID2

CPL P11

SJMP DONE

SID2: CJNE A,#02H,SID3

CPL P12

SJMP DONE

SID3: CJNE A,#03H,SID4

CPL P13

SID4: SJMP DONE

DONE: RETI

END

7. C语言源程序

#include <AT89X51H>

unsigned char tcount2s;

unsigned char tcount02s;

unsigned char ID;

void main(void)

{

TMOD=0x01;

TH0=(65536-50000)/256;

TL0=(65536-50000)%256;

TR0=1;

ET0=1;

EA=1;

while(1);

}

void t0(void) interrupt 1 using 0

{

tcount2s++;

if(tcount2s==40)

{

tcount2s=0;

ID++;

if(ID==4)

{

ID=0;

}

}

tcount02s++;

if(tcount02s==4)

{

tcount02s=0;

switch(ID)

{

case 0:

P1_0=~P1_0;

break;

case 1:

P1_1=~P1_1;

break;

case 2:

P1_2=~P1_2;

break;

case 3:

P1_3=~P1_3;

break;

}

}

}

呵呵很好改的

51单片机中,中断分高低两个优先级,高优先级的中断能打断低优先级的中断。

但同级中断是不能打断同级中断的!无论该中断函数有多长,在执行到一半这个中断又发生了,还是要等到该中断函数执行完毕,并再执行了一条主程序指令后才会再次进入该中断。

不过,若楼主恰好在这个低优先级中断服务程序中修改了该中断为高优先级,那么如果该中断函数比较长,执行到一半又触发了这个中断,则该中断函数就会被重新从头开始执行(中断嵌套)。这是因为除串口中断以外的其他中断,在 CPU 响应该中断,程序转入该中断函数前就已经将该中断的中断标志清零了。

另外,51的串口中断比较特别,因为需要软件清除串口中断标志,所以只要在未清串口中断标志前,是不会发生上述这样的中断嵌套的。

我告诉你思路,例子就不举了,很简单:

1、定义一个dword变量xxx用以存储原来的中断向量(所谓中断向量即中断发生时执行的子程序入口地址)

2、编写自己的中断处理过程(yyy proc far),该处理过程内应保存所有可能修改的寄存器,并在返回前恢复原状;一般情况下,如果还需要执行原有中断处理过程,那么调用jmp far xxx链接到原来的中断过程;如果不需要执行原有过程,那么直接以iret返回即可

3、在主程序开始时,先调用int 35h,获取指定中断号的中断向量,将返回的中断向量存储在xxx变量中

4、调用int 25h,将指定的中断号的中断向量指向自己的过程yyy

5、当前程序在退出前,应再次调用int 25h,将被修改掉的中断号的中断向量恢复为xxx变量的值

假设脉冲的周期在99S-01ms之间

;12M晶振

;测出的周期精确到01ms

;被测脉冲由外部中断0口输入

;所以,结果为小数点前两位,小数点后四位

;如果说周期不在此范围的话,通过修改定时器内程序就行

ORG 0000H

LJMP 0080H

ORG 0003H

VAR7: DS 1

ORG 0080H

MOV SP, #60H

MOV VAR1, #00H

MOV VAR2, #00H

MOV VAR3, #00H

MOV VAR4, #00H

MOV VAR5, #00H

MOV VAR6, #00H

ACALL SETTIME ;配置定时器常数

LJMP $ ;死循环,等待捕捉脉冲的第一个下降沿并起动定时器0

ORG 0030H

VAR1: DS 1

VAR2: DS 1

VAR3: DS 1

VAR4: DS 1 ;所测周期 小数点前两位

VAR5: DS 1 ;所测周期 小数点后两位

VAR6: DS 1 ;所测周期 小数点第三四位

LJMP CESHI

ORG 000BH

LJMP ZD10MS

CESHI:

MOV A, VAR1

MOV VAR4, A

MOV A, VAR2

MOV VAR5, A

MOV A, VAR3

MOV VAR6, A

;由于外部中断有可能是打断定时器0后执行的,所以需要把所有的数据清零,这样,外部中断返回后,定时器无论执行到什么地方,第一次执行完后,VAR1-3的参数仍不变

MOV VAR1, #00H

MOV VAR2, #00H

MOV VAR3, #00H

MOV A, #00H

CLR C

RETI

ZD10MS: ;01ms中断程序

MOV TH0, #0FFH

MOV TL0, #9BH

;===================

;每中断一次,依VAR3为最低位,VAR1为最高位,进行10进制带进位加1

MOV A, VAR3

SETB C

ADDC A, #00H

DA A

MOV VAR3, A

MOV A,VAR2

ADDC A, #00H

DA A

MOV VAR2, A

MOV A, VAR1

ADDC A, #00H

DA A

MOV VAR1, A

RETI

时间短,写的可能有些地方不完善

;主要有三点:1 每次的数据肯定都不一样,所以,数据在输出时,最好能进行简单的滤波,每次数据的输出间隔时间放长,这样输出的数据不会乱闪

;2 外部中断源虽然对定时器0的参数进行了清零,但如果刚好在SETB C前中断,那么本次计的时间会多出01ms

;3 如果要精确定时,那么在给定时器0的计数器填写初始数据时,亦要减掉它消耗的时间。如果它们的计算不准确,数据就会错2%,因为中断的时间太短了,

这里仅仅提供了一个大概的思路,如果要真正做项目,还有好多细节和数据补偿需要考虑。

希望你能满意!

主程序和中断没关系的,主程序是个死循环,一直执行。中断是打断主程序进入中断子程序,中断完成后继续执行主程序。中断标志要在进入中断后清除,如果不清除,下次不会再触发。主程序继续执行无影响。

TR0是启动定时器,启动以后不要再改写就好每到定时时间进入中断。进入中断后要清除中断使能标志,不是叫你关闭定时器。这两种不是一个概念。定时器控制寄存器里面有一个中断标志A,为1的时候代表进入中断,进入中断后A要清零,之后才会继续查看A是否再次为1,为1即进中断,在中断写零,如此循环进行。

关闭或者重新开启TR0,标志A都是硬件自动重新装载(初始化)0,以使中断执行。所以也能达到效果,但是每次执行都重新设置定时器会比较耗费资源,其实只需要清零标志位就ok了。

以上就是关于试用定时器中断方式设计一个程序,使发光二极管每秒内亮400ms,灭600ms。设单片机的振荡频率为6MHz.全部的内容,包括:试用定时器中断方式设计一个程序,使发光二极管每秒内亮400ms,灭600ms。设单片机的振荡频率为6MHz.、51单片机,如果中断函数比较长,执行到一半又触发了这个中断,程序会停止从头执行,还是执行结束后响应中、汇编中断程序!等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9545877.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-29
下一篇 2023-04-29

发表评论

登录后才能评论

评论列表(0条)

保存