这是源程序
N年前做的产品
;光电笔程序
;压力值为设定值
;带看门狗
;带8点平均滤波算法
;结束点判断个数为1个
;new要改变pointnum到4,over不改变pointnum
;版本信息改到了0f00h
;t0定时中断改到20ms
;增加t0intnum1中断,定时100ms检查是否有光电信号输出,若没有了就清除新笔画
;结束笔画,笔画点标志,防止在没有信号时按下笔尖再有信号时会随机出现一个笔划
;*******************************************************************
addata equ p1.0
adclk equ p1.1
adcs equ p1.2
upkey equ p1.3
downkey equ p1.4
usbcheck equ p3.3
blue equ p3.4
red equ p3.5
cs1 equ p3.6
cs2 equ p3.7
;*******************************************************************
initflag EQU 00h ;;初始化标志
toutflag EQU 01h ;;通信超时标志,0为不超时,1超时
newflag EQU 02h ;;笔画头标志,0非,1是
overflag EQU 03h ;;笔画尾标志,0非,1是
penmouse EQU 04h ;为0时是笔画点,为1时是鼠标点
usbok EQU 05h ;0为usb正常,1不正常
;*******************************************************************
time1 EQU 40h
time2 EQU time1+1
time3 EQU time2+1
dba EQU time3+1 ;;dba
s1 EQU dba+1 ;;s1
dbb EQU s1+1 ;;dbb
s2 EQU dbb+1 ;;s2
pointnum EQU s2+1
zt0 EQU pointnum+1 ;;数据头0ffh
b7 EQU zt0+1 ;数据包类型
b0 EQU b7+1
b1 EQU b0+1
b2 EQU b1+1
b3 EQU b2+1
b4 EQU b3+1
b5 EQU b4+1
b6 EQU b5+1
zw0 EQU b6+1 ;;数据尾0f0h
xyh EQU zw0+1 ;;前10个字节的校验和
sendnum EQU xyh+1 ;;发送次数
cout EQU sendnum+1
cout1 EQU cout+1
cout2 EQU cout1+1
cout3 EQU cout2+1
cout4 EQU cout3+1
t0intnum EQU cout4+1 ;t0中断次数
t0intnum1 EQU t0intnum+1 ;100ms检查是否有光电信号
overnum EQU t0intnum1+1
adresult EQU overnum+1
mouseupkeynum EQU adresult+1 ;为1时才是一次有效的按键
mousedokeynum EQU mouseupkeynum+1 ;为1时才是一次有效的按键
setpress0 EQU mousedokeynum+1 ;设定的落笔压力值高
setpress1 EQU setpress0+1 ;设定的落笔压力值低
commbuf0 EQU setpress1+1
commbuf1 EQU commbuf0+1
commbuf2 EQU commbuf1+1
commbuf3 EQU commbuf2+1
ramcheck EQU commbuf3+1
temp0 EQU ramcheck+1
temp1 EQU temp0+1
xy EQU 80h ;间接寻址
;*******************************************************************
wdtrst EQU 0a6h
;*******************************************************************
;pc机控制指令和回应字
divchk EQU 10h ;设备检测命令
setpress EQU 12h ;设置落笔压力值命令
wakeup EQU 16h ;激活命令
vercheck EQU 17h ;读版本命令
cmdok EQU 20h
cmdfail EQU 21h
;*******************************************************************
org 0000h
ljmp main
org 0003h
ljmp int_0
org 000bh
ljmp t0_int ;;定时器0中断(20ms)
org 0013h
reti
org 001bh
reti
org 0023h
ljmp ser_int
;----------------------------------------------------------------------------
;
;
;
org 0100h
main:
clr ea
mov sp,#28h
clr initflag ;初始化开始
lcall sys_init
lcall timestart ;起动定时器
lcall adcov0 ;开始时ad转换是假值,把它放掉
setb initflag ;初始化完成
main1:
mov wdtrst,#1eh ;清看门狗
mov wdtrst,#0e1h
ljmp main1
;*******************************************************************
sys_init:
MOV TMOD,#21H
MOV TH1,#0ffH ;57600b/s(11.0592M)
MOV TL1,#0ffH
mov th0,#0b8h ;定时20ms
mov tl0,#00h
MOV SCON,#50H ;格式n81
MOV PCON,#80H
mov ip,#00000011b ;int0中断和t0中断优先
setb it0 ;int0下降沿中断
setb ex0
setb et0
clr ex1
clr et1
setb es
clr ie0
clr tf0
clr ie1
clr tf1
CLR TI
CLR RI
setb p3.0
setb p3.1
setb adcs
setb adclk
setb addata
setb upkey
setb downkey
setb usbcheck
setb cs1
setb cs2
clr psw.3
clr psw.4
clr newflag
clr overflag
setb penmouse ;鼠标点
mov t0intnum,#50 ;1s
mov t0intnum1,#5 ;100ms
mov overnum,#1
setb usbok ;usb不正常
mov mouseupkeynum,#0 ;上按键次数清零
mov mousedokeynum,#0 ;下按键次数清零
mov setpress0,#00h ;设定的落笔压力值初始值为15
;mov setpress1,#15
mov pointnum,#0 ;点数为0
setb ea
ret
;*******************************************************************
timestart:
SETB TR0
setb tr1
ret
;*******************************************************************
dt20ms:
mov r6,#37
dt1:
mov r7,#250
djnz r7,$
djnz r6,dt1
ret
;*******************************************************************
rev_bytes:
mov r0,#commbuf1
rev_bytes1:
lcall rev
jb toutflag,rev_bytes2 ;是否3秒超时?
mov @r0,sbuf
inc r0
djnz sendnum,rev_bytes1
rev_bytes2:
ret
;----------------------------------------------------------------------------
;接收一字节子程序
rev:
mov time1,#5
rev1:
mov time2,#100
rev2:
jnb ri,rev3 ;;jsflag=1?
clr ri ;;clear jsflag
clr toutflag ;;清超时标志
ljmp rev4
rev3:
djnz time2,rev2
djnz time1,rev1
setb toutflag ;;置超时标志
rev4:
ret
;----------------------------------------------------------------------------
ser_int:
push acc
push b
push psw
setb psw.3
setb psw.4
clr ri ;;clear jsflag
mov a,sbuf
mov b,a
mov commbuf0,a
mov sendnum,#3
lcall rev_bytes
jb toutflag,ser_int1 ;是否5秒超时?
mov r0,#commbuf0
inc r0
mov a,@r0
add a,b
mov b,a
inc r0
mov a,@r0
add a,b
mov b,a
inc r0
mov a,@r0
cjne a,b,ser_int1
ljmp ser_int2 ;命令是否正确?
ser_int1:
clr ri
clr ti
pop psw
pop b
pop acc
reti
ser_int2:
mov a,commbuf0
cjne a,#divchk,ser_int3 ;是设备检测命令吗?
ljmp devicecheck1
ser_int3:
ljmp ser_int4
devicecheck1: ;设备检测
mov xyh,#0ffh
mov sbuf,#0ffh ;发应答数据‘0ffH’
lcall send
mov a,xyh
add a,#divchk
mov xyh,a
mov sbuf,#divchk ;发应答数据‘10H’
lcall send
mov ramcheck,#55h ;检查内存
mov a,ramcheck
cjne a,#55h,devicecheck2
mov ramcheck,#0aah
mov a,ramcheck
cjne a,#0aah,devicecheck2
ljmp devicecheck3
devicecheck2:
mov a,xyh
add a,#cmdfail
mov xyh,a
mov sbuf,#cmdfail ;发应答数据‘21H’
lcall send
mov a,xyh
add a,#00h
mov xyh,a
mov sbuf,#00h ;发应答数据‘00H’
lcall send
mov a,xyh
add a,#7fh
mov xyh,a
mov sbuf,#7fh ;发应答数据‘7fH’
lcall send
ljmp devicecheck4
devicecheck3:
mov a,xyh
add a,#cmdok
mov xyh,a
mov sbuf,#cmdok ;发应答数据‘20H’
lcall send
mov a,xyh
add a,#00h
mov xyh,a
mov sbuf,#00h ;发应答数据‘00H’
lcall send
mov a,xyh
add a,#00h
mov xyh,a
mov sbuf,#00h ;发应答数据‘00H’
lcall send
devicecheck4:
mov a,xyh
add a,#0f0h
mov xyh,a
mov sbuf,#0f0h ;发应答数据‘0f0H’
lcall send
mov a,xyh
mov sbuf,a ;发校验和
lcall send
ljmp ser_int7
ser_int4:
cjne a,#wakeup,ser_int5 ;是激活命令吗?
mov xyh,#0ffh
mov sbuf,#0ffh ;发应答数据‘0ffH’
lcall send
mov a,xyh
add a,#wakeup
mov xyh,a
mov sbuf,#wakeup ;发应答数据‘16H’
lcall send
mov a,xyh
add a,#cmdok
mov xyh,a
mov sbuf,#cmdok ;发应答数据‘20H’
lcall send
mov a,xyh
add a,#00h
mov xyh,a
mov sbuf,#00h ;发应答数据‘00H’
lcall send
mov a,xyh
add a,#0f0h
mov xyh,a
mov sbuf,#0f0h ;发应答数据‘0f0H’
lcall send
mov a,xyh
mov sbuf,a ;发校验和
lcall send
ljmp ser_int7
ser_int5:
cjne a,#vercheck,ser_int6 ;是读生产模式,日期,版本命令吗?
mov xyh,#0ffh
mov sbuf,#0ffh ;发应答数据‘0ffH’
lcall send
mov a,xyh
add a,#vercheck
mov xyh,a
mov sbuf,#vercheck ;发应答数据‘17H’
lcall send
mov dptr,#vertab
mov sendnum,#14 ;发14字节
vercheck1:
clr a
movc a,@a+dptr
mov sbuf,a
add a,xyh
mov xyh,a
lcall send
inc dptr
djnz sendnum,vercheck1
mov a,xyh
add a,#0f0h
mov xyh,a
mov sbuf,#0f0h ;发应答数据‘0f0H’
lcall send
mov a,xyh
mov sbuf,a ;发校验和
lcall send
ljmp ser_int7
ser_int6:
cjne a,#setpress,ser_int8 ;是设置落笔压力值命令吗?
mov a,commbuf1
mov setpress1,a ;保存设定的落笔压力值
mov a,commbuf2
mov setpress0,a
mov xyh,#0ffh
mov sbuf,#0ffh ;发应答数据‘0ffH’
lcall send
mov a,xyh
add a,#setpress
mov xyh,a
mov sbuf,#setpress ;发应答数据‘12H’
lcall send
mov a,xyh
add a,#cmdok
mov xyh,a
mov sbuf,#cmdok ;发应答数据‘20H’
lcall send
mov a,xyh
add a,#00h
mov xyh,a
mov sbuf,#00h ;发应答数据‘00H’
lcall send
mov a,xyh
add a,#0f0h
mov xyh,a
mov sbuf,#0f0h ;发应答数据‘0f0H’
lcall send
mov a,xyh
mov sbuf,a ;发校验和
lcall send
ljmp ser_int7
ser_int8:
nop ;pc的其它命令
nop
nop
ser_int7:
clr ri
clr ti
pop psw
pop b
pop acc
reti
;*******************************************************************
;定时器0中断
;功能:20ms定时检测是否抬笔
t0_int:
push acc
push b
push psw
clr psw.3
setb psw.4
jnb initflag,t0_int3
djnz t0intnum,t0_int2 ;到一秒了吗?
mov t0intnum,#50 ;1s
jb usbcheck,t0_int1 ;usb正常吗?
setb blue ;兰灯熄灭
clr ex0 ;关中断
clr es
cpl red ;红灯闪烁
setb usbok ;usb不正常
ljmp t0_int2
t0_int1:
clr ti
clr ri
setb ex0 ;开中断
setb es
jnb usbok,t0_int2
clr blue ;点亮兰灯
setb red ;红灯熄灭
clr usbok ;usb正常
t0_int2:
djnz t0intnum1,t0_int3 ;到100ms了吗?
mov t0intnum1,#5 ;100ms
clr newflag
clr overflag
setb penmouse ;鼠标点
mov pointnum,#0 ;点数为0
t0_int3:
mov th0,#0b8h ;定时20ms
mov tl0,#00h
clr tf0
pop psw
pop b
pop acc
reti
;*******************************************************************
;int0中断
;功能:数据处理
int_0:
push acc
push b
push psw
setb psw.3
clr psw.4
jnb initflag,int_11
mov t0intnum1,#5 ;100ms
clr red ;点亮红灯
lcall adcov
mov a,adresult
cjne a,setpress1,int_01 ;笔尖压力值>=设定压力吗?
ljmp int_02
int_01:
jc int_04 ;有落笔吗?
int_02:
jnb penmouse,int_03 ;是笔画点吗?
setb newflag ;起始点
clr penmouse ;笔画点
mov pointnum,#4 ;点数为4
int_03:
mov overnum,#1
ljmp int_05
int_04:
jb penmouse,int_05 ;是笔画点吗?
jb newflag,int_05 ;起始点处理完了吗?
djnz overnum,int_05 ;起始点处理完了才能处理结束点
setb overflag ;结束点
int_05:
lcall getdat ;读取CPLD的数据
mov a,pointnum
cjne a,#8,int_07 ;大于8点吗?
ljmp int_08
int_07:
inc pointnum
mov a,pointnum
cjne a,#8,int_10 ;到new后第4点了吗?
int_08:
lcall pjz ;求8点平均
int_09:
lcall datcov ;组织数据
lcall txy ;向PC机发X,Y
int_10:
lcall newtoold ;保存上一次的坐标
setb red ;熄灭红灯
int_11:
clr ie0
pop psw
pop b
pop acc
reti
;*******************************************************************
;发送一字节子程序
send:
mov time1,#200
send0:
mov time2,#200
send1:
jnb ti,send2 ;;ti=1?
clr ti ;;clear ti
clr toutflag ;;清超时标志
ljmp send3
send2:
mov wdtrst,#1eh ;清看门狗
mov wdtrst,#0e1h
djnz time2,send1
djnz time1,send0
setb toutflag ;;置超时标志
send3:
ret
;*******************************************************************
;向PC机发数据
txy:
clr es ;禁止串口中断
mov zt0,#0ffh ;帧头
mov zw0,#0f0h ;帧尾
mov sendnum,#1
txy1:
mov xyh,#0
mov cout,#11
mov r0,#zt0
txy2:
mov sbuf,@r0
lcall send
djnz cout,txy3
ljmp txy4
txy3:
mov a,@r0
add a,xyh
mov xyh,a ;校验和
inc r0
ljmp txy2
txy4:
djnz sendnum,txy1
clr ti ;清串口中断标志
clr ri
setb es ;允许串口中断
ret
;*******************************************************************
;ad转换值在adresult中,ad转换器用的tlc549
adcov:
nop ;送第8个clk脉冲将启动ad转换
setb adclk ;adclk=1
nop
nop
clr adclk ;adclk=0
nop
nop
nop
nop
nop
nop
nop
setb adcs ;adcs=1
mov r7,#20 ;ad转换时间大于17us
djnz r7,$
adcov0:
clr adclk ;adclk=0
nop
nop
clr adcs ;adcs=0
nop
nop
mov r3,#7
adcov1:
mov c,addata
rlc a
nop
setb adclk ;adclk=1
nop
nop
clr adclk ;adclk=0
nop
djnz r3,adcov1
mov c,addata
rlc a
mov adresult,a
ret
;*******************************************************************
;在CPLD取得原始数据
;输出:s1, s2, dba, dbb
getdat:
clr cs1 ;select s2
nop
nop
nop
nop
nop
mov a,p0
anl a,#00111111b
mov s2,a
clr cs2 ;select dbb
nop
nop
nop
nop
nop
mov a,p0
anl a,#00111111b
mov dbb,a
setb cs1 ;select dba
nop
nop
nop
nop
nop
mov a,p0
anl a,#00111111b
mov dba,a
setb cs2 ;select s1
nop
nop
nop
nop
nop
mov a,p0
anl a,#00111111b
rlc a
rlc a
mov s1,a
mov a,dba
rrc a
mov dba,a
mov a,s1
rrc a
mov s1,a
mov a,dba
rrc a
mov dba,a
mov a,s1
rrc a
mov s1,a
mov a,dba
anl a,#00001111b
mov dba,a
mov a,s2
rlc a
rlc a
mov s2,a
mov a,dbb
rrc a
mov dbb,a
mov a,s2
rrc a
mov s2,a
mov a,dbb
rrc a
mov dbb,a
mov a,s2
rrc a
mov s2,a
mov a,dbb
anl a,#00001111b
mov dbb,a
mov r0,#xy
mov @r0,dba
inc r0
mov @r0,s1
inc r0
mov @r0,dbb
inc r0
mov @r0,s2
ret
;*******************************************************************
;求8点平均值,dbas1=(x+x1+x2+x3+x4+x5+x6+x7)/8,dbbs2=(y+y1+y2+y3+y5+y6+y7)/8
pjz:
mov a,#xy
add a,#5 ;指到x1l
mov r0,a
mov a,#xy
add a,#7 ;指到y1l
mov r1,a
mov cout,#7
pjz1:
mov a,s1
add a,@r0
mov s1,a
dec r0 ;指到x?h
mov a,dba
addc a,@r0
mov dba,a
mov a,s2
add a,@r1
mov s2,a
dec r1 ;指到y?h
mov a,dbb
addc a,@r1
mov dbb,a
mov a,r0
add a,#5 ;指到下一个x?l
mov r0,a
mov a,r1
add a,#5 ;指到下一个y?l
mov r1,a
djnz cout,pjz1
mov a,dba ;dbas1=dbas1/8
rrc a
mov dba,a
mov a,s1
rrc a
mov s1,a
mov a,dba
rrc a
mov dba,a
mov a,s1
rrc a
mov s1,a
mov a,dba
rrc a
mov dba,a
mov a,s1
rrc a
mov s1,a
anl dba,#00001111b
mov a,dbb ;dbbs2=dbbs2/8
rrc a
mov dbb,a
mov a,s2
rrc a
mov s2,a
mov a,dbb
rrc a
mov dbb,a
mov a,s2
rrc a
mov s2,a
mov a,dbb
rrc a
mov dbb,a
mov a,s2
rrc a
mov s2,a
anl dbb,#00001111b
ret
;*******************************************************************
newtoold:
mov cout,#28
mov a,#xy
add a,#31 ;指到y7l
mov r0,a
clr c
subb a,#4 ;指到y6l
mov r1,a
newtoold1:
mov a,@r1
mov @r0,a
dec r0
dec r1
djnz cout,newtoold1
ret
;*******************************************************************
;按协议组织数据并清除和设置一些标志
;输入:newflag,overflag,adresult,s1,dba,s2,dbb
;输出:b0-b6
datcov:
mov b7,#7fh ;普通数据包
mov b0,#60h
jnb overflag,datcov0 ;是否为结束笔画?
orl b0,#00000100b
clr overflag ;清结束笔画标志
setb penmouse ;鼠标点标志
clr blue ;点亮兰灯
ljmp datcov2
datcov0:
jnb newflag,datcov1 ;是否为新笔画?
orl b0,#00000001b
clr newflag ;清新笔画标志
clr penmouse ;笔画点
setb blue ;兰灯熄灭
ljmp datcov2
datcov1:
jnb penmouse,datcov2 ;是鼠标点吗?
orl b0,#00000010b ;加鼠标点标志
clr blue ;点亮兰灯
datcov2:
jb upkey,datcov3 ;鼠标上键按下吗?
mov a,mouseupkeynum
jz datcov4
orl b0,#00001000b
ljmp datcov5
datcov3:
mov a,mouseupkeynum
jz datcov5
dec mouseupkeynum
ljmp datcov5
datcov4:
inc mouseupkeynum
datcov5:
jb downkey,datcov6 ;鼠标下键按下吗?
mov a,mousedokeynum
jz datcov7
orl b0,#00010000b
ljmp datcov8
datcov6:
mov a,mousedokeynum
jz datcov8
dec mousedokeynum
ljmp datcov8
datcov7:
inc mousedokeynum
datcov8:
mov a,adresult
cjne a,setpress1,datcov9
ljmp datcov10
datcov9:
jnc datcov10
mov a,#0
ljmp datcov11
datcov10:
subb a,setpress1 ;由于落笔时的最小压力值是setpress1,故要减setpress1
datcov11:
mov b2,a
rlc a
mov a,b1
rlc a
anl a,#00000001b ;8位ad转换
orl a,#01111000b
mov b1,a
anl b2,#01111111b
mov a,s1
mov b4,a
rlc a
mov a,dba
rlc a
mov b3,a
anl b3,#00011111b
anl b4,#01111111b
mov a,s2
mov b6,a
rlc a
mov a,dbb
rlc a
mov b5,a
anl b5,#00011111b
anl b6,#01111111b
ret
;*******************************************************************
org 0efdh
ljmp main ;软件陷阱
;*******************************************************************
org 0f00h
vertab:
db '0','0','0','0' ;生产模式
db '0','3','0','9','2','8' ;日期
db '1','0','3','6' ;版本
;*******************************************************************
org 1ffdh
ljmp main ;软件陷阱
;*******************************************************************
end |