12M晶震 0.1s =100ms =100000US 因为51单片机T0 T1作为16位定时器最大65535 那么 我们用一个16位的T0或者T1 定时50000US 既是50ms 65535-50000=13335 换成16进制3CAF 那么定时器的高字节和低字节位 TH0=3CH TL0=0AFH 这样T0的溢出时间就是50MS 那么在程序中 我们要用到1S的时间怎么办呢? 我们定义一个延时中间变量 MS 在T0中段程序中 检测MS的值 比如 我们要延时1S 那么 1S/50MS=20 则在主程序中定义 MS值为20
在T0的中断程序中 用 DJNZ MS exit 检测 MS是否运行了20次 也就是是否延时了1S 没有到1S 就退出 到了1S 了 就干其他事情 以此类推 要延时 1-99S比如 20S 那么 MS 的值为 400 即400X50MS=20000MS=20S 下面是 示例代码
;---------------------------------------------- ;名称:用定时计器T0实现任意秒数延时程序 ;主频 12M晶震 51系列单片机 ;入口参数 MS T0溢出中断定义为 50MS 程序中要用到延时时 开T0中断 并且给MS ;附值 MS=20 时 为1S 以此类推 延时完成后 关T0中断 ;编译环境:keil c51编译通过 ;WWW.51HEI.COM 原创 可以任意修改和作为学习测试用途 ;备注 :在T0的中断程序中 指令的执行也占用了时间 因此 此程序的定时 并不精确 ;2009-3-31 ;---------------------------------------------
;内存分配定义 T0CZG EQU 3CH ;定时器0初值高字节 T0CZD EQU 0AFH ;定时器0初值低字节 ms EQU 59H yszt bit 7fh ;延时状态 ;--------------------------------------------
ORG 0000H aJMP MAIN org 0003h ;lJMP in0zd org 000bh lJMP t0zd org 0013h ;lJMP in1zd org 001bh ; ljmp t1zd org 0030h ;---------------------------- MAIN: setb yszt clr tr0 ;关T0 setb ea ;CPU开中断 ;---------------- ;程序段 ;------------------ mov ms, #20 setb tr0 ; 这里运行了指令 延时时间应该+1 jb yszt, $ ;原地踏步 等待延时完成 YSZT 延时状态标志位 在T0的中断程序里面控制 为1则没有延时完 为0则表示延时完毕 CLR TR0 ;延时完毕 关T0 ; ------------------------------------ ; 延时完毕 ,要放的程序段 ; ;------------------------------- ;--------------------- ;程序段 ;------------------- ajmp main ;------------------------------------------------- ;定时器T0中断服务子程序 ;入口参数 MS ;出口参数 YSZT 延时状态标志位 ;------------------------------------------------- t0zd:
MOV TH0, #T0CZG ;重装初始值 MOV TL0, #T0CZD PUSH ACC PUSH PSW DJNZ ms, exit ; MS未到0 退出 clr yszt ; 延时完成 MS里面的值已经剪到0 清延时状态标志位 退出 exit: POP PSW POP ACC RETI END
代码写完了 不过在T0的中断程序的执行中 判断是否延时时间到的过程中 其实也占用了时间 LZ 如果只是 去抖动 或者是 显示部分动态扫描要用到延时的话 完全可以用标准的 2重循环 就够了 比如 延时1MS DELAY1ms: MOV R0,#2 Y1: MOV R1,#250 DJNZ R1,$ DJNZ R0,Y1 RET
[此贴子已经被作者于2009-4-2 13:42:25编辑过]
|