51单片机定时器函数分享(8051汇编)
注:本篇文章部分基于上一篇数码管的文章,如果有关于数码管显示函数不懂的可以先看一下上一篇文章:51单片机数码管显示函数
另外,关于定时器与中断系统的更多详细介绍,可以看一下我一年半前写的文章(当时讲解是基于C语言的):定时器与中断系统
目录
源代码
电路图
代码框架
代码使用
第一部分
第二部分
函数说明
功能拓展
拓展电路图
LED轮闪函数
基础配置
调用LED闪烁函数
拓展部分总代码
拓展部分实现效果
源代码
ORG 00HSMGPTR DATA 30HDISDATA DATA 31H//DISDATA: 31H - 36H (DATA Arr)SMGBIN DATA 40HTEMP1 DATA 41HTEMP2 DATA 42HTEMP3 DATA 43HSEC DATA 50HCOUNT1 DATA 51HCOUNT2 DATA 52HCOUNT3 DATA 53HLJMP START;ORG 000BH;LJMP T0M2_ISR;LJMP T0M1_ISRORG 001BH;LJMP T1M1_ISRLJMP T1M2_ISRORG 30HSTART:MOV SEC,#0MOV COUNT1,#0MOV COUNT2,#0MOV COUNT3,#0;LCALL T0M1_INIT;LCALL T1M1_INIT;LCALL T0M2_INITLCALL T1M2_INITLOOP:MOV A,SECMOV B,#10DIV ABMOV DISDATA+0,AMOV DISDATA+1,BLCALL DISPLAYSJMP LOOPSJMP START///////////////////////////////////////////////////////////TIMER0 MODE1T0M1_INIT:MOV TMOD,#01HMOV TH0,#(65535-50000)/256MOV TL0,#(65535-50000)MOD 256SETB EASETB ET0SETB TR0RETT0M1_ISR:MOV TH0,#(65535-50000)/256MOV TL0,#(65536-50000)MOD 256INC COUNT1MOV R1,COUNT1CJNE R1,#4,T0M1_NEXT //50ms*4=200msMOV COUNT1,#0INC COUNT2MOV R1,COUNT2CJNE R1,#5,T0M1_NEXT //200ms*5=1sMOV COUNT2,#0INC SECMOV R1,SECCJNE R1,#100,T0M1_NEXTMOV SEC,#0T0M1_NEXT:RETI///////////////////////////////////////////////////////////TIMER1 MODE1T1M1_INIT:MOV TMOD,#10HMOV TH1,#(65535-50000)/256MOV TL1,#(65535-50000)MOD 256SETB EASETB ET1SETB TR1RETT1M1_ISR:MOV TH1,#(65535-50000)/256MOV TL1,#(65536-50000)MOD 256INC COUNT1MOV R1,COUNT1CJNE R1,#4,T1M1_NEXT //50ms*4=200msMOV COUNT1,#0 INC COUNT2MOV R1,COUNT2CJNE R1,#5,T1M1_NEXT //200ms*5=1sMOV COUNT2,#0INC SECMOV R1,SECCJNE R1,#100,T1M1_NEXTMOV SEC,#0T1M1_NEXT:RETI///////////////////////////////////////////////////////////TIMER0 MODE2T0M2_INIT:MOV TMOD,#02HMOV TH0,#256-200MOV TL0,#256-200 SETB EASETB ET0SETB TR0RETT0M2_ISR:INC COUNT1MOV R1,COUNT1CJNE R1,#100,T0M2_NEXT //0.2ms*100 = 20msMOV COUNT1,#0INC COUNT2MOV R1,COUNT2CJNE R1,#10,T0M2_NEXT //20ms*10=200msMOV COUNT2,#0INC COUNT3MOV R1,COUNT3CJNE R1,#5,T0M2_NEXT //200ms*5=1sMOV COUNT3,#0INC SECMOV R1,SECCJNE R1,#100,T0M2_NEXTMOV SEC,#0T0M2_NEXT:RETI///////////////////////////////////////////////////////////TIMER1 MODE2T1M2_INIT:MOV TMOD,#20HMOV TH1,#256-200MOV TL1,#256-200 SETB EASETB ET1SETB TR1RETT1M2_ISR:INC COUNT1MOV R1,COUNT1CJNE R1,#100,T1M2_NEXT //0.2ms*100 = 20msMOV COUNT1,#0INC COUNT2MOV R1,COUNT2CJNE R1,#10,T1M2_NEXT //20ms*10=200msMOV COUNT2,#0INC COUNT3MOV R1,COUNT3CJNE R1,#5,T1M2_NEXT //200ms*5=1sMOV COUNT3,#0INC SECMOV R1,SECCJNE R1,#100,T1M2_NEXTMOV SEC,#0T1M2_NEXT:RETI/////////////////////////////////////////////////////////DISPLAY:MOV SMGBIN,#01111111BMOV SMGPTR,#0DIS1:MOV A,SMGBINRL AMOV SMGBIN,AMOV P2,SMGBIN //BIT CHOICEMOV A,SMGPTRADD A,#DISDATAMOV R0, AMOV TEMP1,@R0 //DATA CHOICEMOV DPTR,#TABMOV A,TEMP1MOVC A,@A+DPTRMOV P0,ALCALL DELAYINC SMGPTRMOV A,SMGPTRCJNE A,#6,DIS1RET/////////////////////////DELAY:MOV R5,#1 //1msDELAY3:MOV R6,#2DELAY2:MOV R7,#248DELAY1:DJNZ R7,DELAY1DJNZ R6,DELAY2DJNZ R5,DELAY3RET ////////////////////////TAB:DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
END
代码作用就是每1s实现让SEC+1,并且显示在数码管上,这里相较于上期文章有点修改,就是DELAY函数的时间从10ms改成了1ms,尽量使得对中断的干扰没有那么大
电路图

代码框架
讲使用之前先讲一下框架,主要框架就是
ORG 00H
//变量定义
LJMP START
//中断向量地址(四选一)
;ORG 000BH
;LJMP T0M2_ISR
;LJMP T0M1_ISR
ORG 001BH
;LJMP T1M1_ISR
LJMP T1M2_ISR
ORG 30H
START:
//初始化变量
MOV SEC,#0
MOV COUNT1,#0
MOV COUNT2,#0
MOV COUNT3,#0
//初始化定时器(四选一)
;LCALL T0M1_INIT
;LCALL T1M1_INIT
;LCALL T0M2_INIT
LCALL T1M2_INIT
LOOP:
//取出数字并且显示
MOV A,SEC
MOV B,#10
DIV AB
MOV DISDATA+0,A
MOV DISDATA+1,B
LCALL DISPLAY
SJMP LOOP
SJMP START//下面是各种函数定义
代码使用
代码使用主要配置两个部分
第一部分

这里的配置是ORG 000BH对应定时器0(包含定时器0模式1和2),然后ORG001BH对应定时器1(包含定时器1模式1和2),写完定时器起始地址之后立刻接上中断函数的名字
例如上面就是调用定时器1模式2,所以用ORG 001BH接上LJMP T1M2_ISR(定时器1模式2的中断函数)
假设我需要调用定时器1模式1,就用ORG 000BH后面接上LJMP T0M1_ISR(定时器0模式2的中断函数)
当然,要注意,如果确定了一个中断函数和模式,整段代码就只能使用这个中断函数和模式,否则定时器就没有办法正常使用
第二部分
第二部分就是在LOOP循环前的初始化部分调用一下选择的定时器及模式初始化函数

比如这里就是调用初始化定时器1模式2的函数
函数说明

这是定时器0模式1的函数,主要分为初始化函数和中断处理函数两个部分,中断处理函数就是每50ms进入这个函数,然后执行计数,这里设置的就是50ms*4*5=1s就加一次SEC,这样我们就可以在主函数中用数码管显示SEC,实现的效果就是每秒SEC+1并且显示到数码管上的效果
当然,我们也可以在中断处理函数里调用别的函数,比如我们在这里调用函数

这里调用的函数就是在200ms计数之后,就可以实现200ms执行一次这个函数,比如每200ms控制LED开关之类的作用,当然,这里的时间间隔也可以自己控制,实现更多的功能,比如下面
功能拓展
拓展电路图

如图,在P3.0和P3.1分别接了LED1和LED2,并且LED共阳极,通过控制P3.0和P3.1让LED闪烁,这里的拓展功能是使用上面的函数,用定时器1工作方式2实现两个LED轮流发光,同时保留秒表每秒+1的作用
LED轮闪函数


这里通过判断LEDMODE来判断状态,如果LEDMODE为1就执行模式1并且把LEDMODE置为0,如果LEDMODE为0就执行模式2并且把LEDMODE置为1,如此循环,实现LED的循环闪烁
基础配置
同上面讲述的时候说的,配置主要两个部分,一是选择中断地址,二是选择初始化函数

调用LED闪烁函数
要求每200ms实现LED闪烁变换,就在中断处理函数200ms位置调用LED_CHANGE函数

如此即可....
拓展部分总代码
ORG 00HSMGPTR DATA 30HDISDATA DATA 31H//DISDATA: 31H - 36H (DATA Arr)SMGBIN DATA 40HTEMP1 DATA 41HTEMP2 DATA 42HTEMP3 DATA 43HSEC DATA 50HCOUNT1 DATA 51HCOUNT2 DATA 52HCOUNT3 DATA 53HLEDMODE DATA 54HLJMP STARTORG 001BHLJMP T1M2_ISRORG 30HSTART:MOV SEC,#0MOV COUNT1,#0MOV COUNT2,#0MOV COUNT3,#0LCALL T1M2_INITLOOP:MOV A,SECMOV B,#10DIV ABMOV DISDATA+0,AMOV DISDATA+1,BLCALL DISPLAYSJMP LOOPSJMP START/////////////////////////////////////////////////////////LED_CHANGE:MOV A,LEDMODECJNE A,#1,LEDMODE2LEDMODE1://LEDMODE==1SETB P3.0CLR P3.1MOV LEDMODE,#0SJMP LED_EXITLEDMODE2://LEDMODE==0SETB P3.1CLR P3.0MOV LEDMODE,#1LED_EXIT:RET///////////////////////////////////////////////////////////TIMER1 MODE2T1M2_INIT:MOV TMOD,#20HMOV TH1,#256-200MOV TL1,#256-200 SETB EASETB ET1SETB TR1RETT1M2_ISR:INC COUNT1MOV R1,COUNT1CJNE R1,#100,T1M2_NEXT //0.2ms*100 = 20msMOV COUNT1,#0INC COUNT2MOV R1,COUNT2CJNE R1,#10,T1M2_NEXT //20ms*10=200msMOV COUNT2,#0LCALL LED_CHANGEINC COUNT3MOV R1,COUNT3CJNE R1,#5,T1M2_NEXT //200ms*5=1sMOV COUNT3,#0INC SECMOV R1,SECCJNE R1,#100,T1M2_NEXTMOV SEC,#0T1M2_NEXT:RETI/////////////////////////////////////////////////////////DISPLAY:MOV SMGBIN,#01111111BMOV SMGPTR,#0DIS1:MOV A,SMGBINRL AMOV SMGBIN,AMOV P2,SMGBIN //BIT CHOICEMOV A,SMGPTRADD A,#DISDATAMOV R0, AMOV TEMP1,@R0 //DATA CHOICEMOV DPTR,#TABMOV A,TEMP1MOVC A,@A+DPTRMOV P0,ALCALL DELAYINC SMGPTRMOV A,SMGPTRCJNE A,#6,DIS1RET/////////////////////////DELAY:MOV R5,#1 //1msDELAY3:MOV R6,#2DELAY2:MOV R7,#248DELAY1:DJNZ R7,DELAY1DJNZ R6,DELAY2DJNZ R5,DELAY3RET ////////////////////////TAB:DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
END
拓展部分实现效果
LED以200ms周期循环闪烁,定时器1s加一

