这是频率计综合应用能对外加信号源进行测频,测频范围0.1~100K(范围可调节)演示了内部定时器,外部计数中断、数码显示,键盘输入等功能,此外如软件延时、查表、数据变换等都得到了应用。
;这是频率计的例子程序,包含:外部中断设置,中断服务程序,定时程序,定时服务程序
;以及数据处理,显示,包括两位十进制数转化为三位BCD码:
led1 bit p1.0
led2 bit p1.1
led3 bit p1.2
led4 bit p1.3
led5 bit p1.4
led6 bit p1.5
led7 bit p1.6
led8 bit p1.7
s1 bit p0.0
s2 bit p0.1
s3 bit p0.2
s4 bit p0.3
s5 bit p0.4
s6 bit p0.5
s7 bit p0.6
s8 bit p0.7
led_data equ p2 ;数码管数据定义
timer_h equ 46h ;定时器高位字节单元
timer_l equ 47h ;定时器低位字节单元
timcount equ 48h ;时间中断数
count_h equ 49h ;计数值高位
count_l equ 4ah ;计数值低位
int_h equ 45h ;中断计数缓冲单元高地址
int_l equ 44h ;中断计数缓冲单元低地址
int_data equ 43h ;用来刷新LED指示的数据单元
t_h equ 60h ;数据显示的高位
t_s equ 61h ;数据显示中位
t_m equ 62h ;数据显示低位
disstart equ 70h ;显示单元首地址
org 00h ;代码开始地址
jmp main ;主程序开始
org 03h ;外部中断EX0入口地址
jmp ex_int0 ;中断服务程序
org 0bh
jmp timer_int ;定时器T1中断服务程序
org 030h
main:mov sp,#30h ;设置sp指针
lcall pro_set ;初始化
lcall pro_int0 ;外部中断1工作设置
mlp:lcall ex_pro ;外部中断数据转换
lcall ex_display ;外部中断数据显示
cpl p1.0 ;取反 p1.0 获得外部脉冲
;我们利用它来进行中断计数操作
jmp mlp
pro_set:mov a,#00h ;初始化程序
mov b,#00h
mov p0,#0
mov p1,0ffh ;p1 = 255 (十进制,写成十六进制 0FFH )
mov p2,#255 ;p2 = 255 (十进制,写成十进制为 255 )
mov int_h,#00h
mov int_l,#00h
mov t_s,#00h
mov t_h,#00h
mov t_m,#00h
mov timcount,#00h
mov timer_h,#3ch ;定时 50 ms
mov timer_l,#0c1h ;
clr beep
ret
; ************** 定时器设置 ************************
tim_t1:mov tmod,#10h ;设置定时器,定时1s
setb et1 ;允许定时中断
mov th1,timer_h ;设置定时初值高位
mov tl1 ,timer_l ;设置定时初值低位
setb tr1 ;定时器开始工作
ret
; *********** 定时器中断服务程序 *******************
timer_int: clr tr1 ;定时器中断服务,关闭定时器
mov tl1,timer_l ;重新赋初值
mov th1,timer_h ;
inc timcount ;定时1s,时间单位
mov a,timcount ;查看数量值
cjne a,#20,t_end ;如果没有1s返回
mov timcount,#00h ;到1s则清零
mov int_l,count_l ;刷新显示部分
mov int_h,count_h ;
t_end: setb tr1 ;重新开始定时操作
reti
; ***************** 外部中断服务程序 ****************
ex_int0:mov p0,#00h ;禁止数码管显示
mov a,int_data ;取得LED显示缓冲数据
rl a ;移位
inc a
mov int_data,a ;修改 显示区数据
mov p1,a ;显示
inc count_l ;将中断缓冲区低地址加1
mov a,count_l ;判断是否有进位
jnz int_end ;没有则返回
inc count_h ;否则,将高地址加1
int_end:reti ;中断返回
;***********************************
;******* 设置中断 ****************
pro_int0:mov int_data,#01h ;LED数据单元为1
clr c ;清进位标志
setb it0 ;设置中断触发方式:脉冲触发
setb ea ;总的中断允许
setb ex0 ;允许外部中断EX0中断
clr ex1 ;禁止外部中断EX1中断
ret ;返回
;**********************************
ex_display:mov r0,#disstart ;获得显示单元首地址
mov r1,#01h ;从第一个数码管开始
mov r2,#06h ;共显示6位数码管
dislp:mov led_data,@r0 ;读取显示单元数据
inc r0 ;取下一个单元地址
mov p0,r1 ;开始显示当前位
mov a,r1 ;准备显示下一位
rl a ;
mov r1,a ;下一位
lcall delay5ms ;延时 5 ms
djnz r2,dislp ;重复显示下一个
ret ;显示完成,返回
;ex_pro 时间处理,主要为 bcd码转换,查表
ex_pro:setb psw.3 ;准备 寄存器
clr psw.4 ;
mov r6,int_h ;得到高位数据
mov r7,int_l ;得到低位数据
lcall data_pro ;开始转换
lcall bcd ;转换完成后,开始进行码型变换
mov r0,#disstart ;开始填充显示单元
mov r2,#06h ;共计填充 6 位
prlp:mov a,@r0 ;获得当前位地址
mov dptr,#tab_nu ;获得表头
movc a,@a+dptr ;获得编码数据
mov @r0,a ;保存编码数据
inc r0 ;指向下一个带转换数据
djnz r2,prlp ;继续转换,直到完成
ret ;转换完成,返回
data_pro: ;两位 十六进制 转化为 2 位 BCD 码
PUSH PSW ;高位 ->R6 低位 ->R7,转化后 从高到低
t_s,t_m,t_h
SETB PSW.3 ;设置当前寄存器
CLR PSW.4
CLR A ;清累加器
MOV t_h,A ;清除出口单元,准备转换
MOV t_m,A
MOV t_s,A
MOV R2,#10H ;共计转换 16 位
HB3:MOV A,r7 ;获得低位数据
RLC A ;带位左移,高位数据在CY中
MOV r7,A ;保存数据
MOV A,r6 ;取得高位数
RLC A ;带进位左移
MOV r6,A ;保存数据
MOV A,t_s ;得到低位数据
ADDC A,t_s ;累加
DA A ;十进制调整
MOV t_s,A ;保存数据
MOV A,t_m ;得到第二位数据
ADDC A,t_m ;累加
DA A ;十进制调整
MOV t_m,A ;保存结果
MOV A,t_h ;得到第三位
ADDC A,t_h ;累加
MOV t_h,A ;保存
DJNZ R2,HB3 ;没有转换完毕,重复转换
POP PSW ;转换完毕,恢复PSW
RET ;返回
;码型变换,将带转换的数据分成,不同的数位,并转换成单位BCD码
bcd:mov r0,#disstart ;获得首地址
mov a,t_s ;获得待转化的低位
mov b,#16 ;转化进制,如果要进行十进制转换 改为 10
div ab ;计算 A/B
mov @r0,b ;第一位转换完毕,保存低位转化后的数据
inc r0 ;自增
mov @r0,a ;保存高位
inc r0 ;取第二个数据地址
mov a,t_m ;获得第二个需要转换的数据
mov b,#16 ;十六进制
div ab ;计算
mov @r0,b ;存低位
inc r0
mov @r0,a ;存高位
inc r0 ;第三位
mov a,t_h ;获得数据
mov b,#16 ;十六进制
div ab ;计算
mov @r0,b ;存低位
inc r0
mov @r0,a ;存高位
ret ;完毕,返回
;************ 250 ms 延时 ******************
delay:push psw ;保存原来的寄存器单元
clr psw.3 ;设置新的寄存器
setb psw.4 ;
mov r0,#2 ;延时参数1
mov r1,#250 ;延时参数2
mov r2,#2 ;延时参数3
dl1:djnz r0,dl1 ;延时循环1
mov r0,#250 ;重新设置循环数据
dl2:djnz r1,dl1 ;开始第二道循环
mov r0,#240 ;
mov r1,#248 ;
dl3:djnz r2,dl1 ;第三道循环
nop ;修正定时精度
pop psw ;恢复原来的寄存器组
ret ;返回
;***********************************************
;************** 定时 5ms ************
delay5ms: ;参见上面说明
push psw
clr psw.3
setb psw.4
mov r0,#250
mov r1,#10
d20:djnz r0,d20
mov r0,#250
djnz r1,d20
pop psw
ret
;****************************************
;这是数字显示表格,其中 带小数点的数字比不带小数点的数字大16
;比如 0 的显示代码为 0;那么 0.的显示代码为 16;如此类推
tab_nu:db 0c0h,0f9h, 0a4h, 0b0h, 99h , 92h , 82h, 0f8h ; number 0 to 7 no dp..
db 80h , 90h, 88h , 83h , 0c6h, 0a1h, 86h, 8eh ; number 8 to f no dp..
db 40h , 79h, 24h , 30h , 19h , 12h , 02h, 78h ; number 0 to 7 with dp..
db 00h , 10h, 08h , 03h , 46h , 21h , 06h, 0eh ; number 8 to f with dp..
end |