📄 serial.asm
字号:
; Serial Communication Library (c)Copyright 2000, Radek Benedikt; benedikt@lphard.cz, http://benedikt.lphard.cz; ver. 1.20 -- Radek Benedikt 22-Feb-2002 - RD2/XRAM buffers; ver. 1.21 -- Radek Benedikt 12-Mar-2002 - timer 2 Baud Rate Generator;;*************************************************************;*** PROJECT WEB51 http://web51.hw.cz **;*************************************************************; This program is free software; you can redistribute it and/or modify; it under the terms of the GNU General Public License as published by; the Free Software Foundation, version 2.;; This program is distributed in the hope that it will be useful,; but WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License; along with this program; if not, write to the Free Software; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.; Tento program je volne programove vybaveni; muzete jej sirit a; modifikovat podle ustanoveni Obecne verejne licence GNU, vydavane Free; Software Foundation, verze 2;; Tento program je rozsirovan v nadeji, ze bude uzitecny, avsak BEZ; JAKEKOLI ZARUKY; neposkytuji se ani odvozene zaruky PRODEJNOSTI anebo; VHODNOSTI PRO URCITY UCEL.; Dalsi podrobnosti hledejte v Obecne verejne licenci GNU.;; Kopii Obecne verejne licence GNU jste mel obdrzet spolu s timto; programem; pokud se tak nestalo, napiste o ni Free Software Foundation,; Inc., 675 Mass Ave, Cambridge, MA 02139, USA.; .global getchar .global xputchar .global pchar .global putchar .global sstat .global intRITI .global rxint .global txint .global srun .global rtscts .global xonxoff .global flagxoff .global xonrq .global xoffrq .global flagtxoff .global r1point .global s1point .global sser .global rser;extrn BIT(cflag);.nolist.include "param.inc".list; .equ XON, 0x11 .equ XOFF,0x13 .bitcomm rxint, 1 .bitcomm txint, 1 .bitcomm srun, 1 .bitcomm rtscts, 1 .bitcomm xonxoff, 1 .bitcomm flagxoff, 1 .bitcomm xonrq, 1 .bitcomm xoffrq, 1 .bitcomm flagtxoff, 1.if RD2SER .comm r1point, 2 ;receive serial buffer - pointer 1 (Rd, buff->app) .comm r2point, 2 ;receive serial buffer - pointer 2 (Wr, SBUF->buff) .comm s1point, 2 ;send serial buffer - pointer 1 (Wr, app->buff) .comm s2point, 2 ;send serial buffer - pointer 2 (Rd, buff->SBUF); send buffer .xcomm sser, lngsser ;send serial buffer; receive buffer .xcomm rser, lngrser ;receive serial buffer.else .comm r1point, 1 ;receive serial buffer - pointer 1 .comm s1point, 1 ;send serial buffer - pointer 1; send buffer .icomm sser, lngsser ;send serial buffer; receive buffer .icomm rser, lngrser ;receive serial buffer.endif .text;;#########################################################; Procedura cteni znaku za serioveho kanalu;#########################################################;getchar:jnb rxint,retchar ;idioten sichr.if RD2SER push dph push dpl mov dph, r1point ; MSB mov dpl, r1point+1 ; LSB ENABLE_XRAM movx a,@dptr ; precti znak DISABLE_XRAM mov r1,a inc dptr mov a,dph ; make circle buffer from linear buffer cjne a,#HIGH(rser+lngrser),nocircle1 mov a,dpl cjne a,#LOW(rser+lngrser),nocircle1 mov dptr,#rsernocircle1: clr C mov a,dpl subb a, r2point+1 ; LSB mov r0,a mov a,dph subb a, r2point ; MSB jnb Acc.7,noadj1 add a,#HIGH(lngrser)noadj1: clr C jnz adj1 ; unused buffer space > 0xFF mov a,r0 jz adj1 ; buffer empty cjne a,#20,.+3 ; if unused buffer space < 20 then reset RTS/adj1: jnb rtscts,getchar1 mov RTS,Cgetchar1: jnb xonxoff,getchar2 jc getchar2 ; XOFF jnb flagxoff,getchar2 ;O.K. jb srun,getchr2 ; nezahajuj vysilani, vysila se clr flagxoff mov SBUF,#XON ; vysli XON setb srun sjmp getchar2getchr2:setb xonrq ; XON requestgetchar2: mov a,dpl ; LSB CLR ES ; disable serial interrupt cjne a,r2point+1,notempty mov a,dph ; MSB cjne a,r2point,notempty clr rxint ; buffer empty clear "NoEmpty flag"notempty: mov r1point,dph ; MSB mov r1point+1,dpl ; LSB SETB ES ; enable serial interrupt mov a,r1 pop dpl pop dph.else mov r0,#rser MOV A,@r0 ;precti znak mov r1,a mov r0,#LOW(rser+lngrser) CLR ES ;disable serial interruptfllp: dec r0 xch a,@r0 cjne r0,#rser,fllp dec r1point mov a,r1point cjne a,#(rser+MAXCHAR),.+3 cpl C ;if v bufferu je > MAXCHAR znaku then reset RTS/ jnb rtscts,getchar1 mov RTS,Cgetchar1: jnb xonxoff,getchar2 jc getchar2 ;XOFF jnb flagxoff,getchar2 ;O.K. jb srun,getchr2 ;nezahajuj vysilani, vysila se clr flagxoff mov SBUF,#XON ;vysli XON setb srun sjmp getchar2getchr2:setb xonrq ;XON requestgetchar2: cjne a,#rser,notempty clr rxint ;buffer empty clear "NoEmpty flag"notempty:SETB ES ;enable serial interrupt mov a,r1.endifretchar:ret;;#########################################################;;testbuffer:; mov C,rxint; mov cflag,C; ret;;#########################################################; Procedura zapis znaku do serioveho kanalu;#########################################################; .using 0.if RD2SERxputchar: push dph push dpl mov dph, s1point ; MSB mov dpl, s1point+1 ; LSB ENABLE_XRAM movx @dptr,a ; uloz znak do bufferu DISABLE_XRAM inc dptr mov a,dph ; make circle buffer from linear buffer cjne a,#HIGH(sser+lngsser),nocircle2 mov a,dpl cjne a,#LOW(sser+lngsser),nocircle2 mov dptr,#ssernocircle2: mov a,dpl CLR ES ; disable serial interrupt cjne a,s2point+1,xptchr ; neni plno, vysli znak mov a,dph cjne a,s2point,xptchr ; neni plno, vysli znak SETB ES ;enable serial interrupt pop dpl pop dph clr A ;0 char send retpchar: mov a,R7putchar: push dph push dpl mov dph, s1point ; MSB mov dpl, s1point+1 ; LSB ENABLE_XRAM movx @dptr,a ; uloz znak do bufferu DISABLE_XRAM inc dptr mov a,dph ; make circle buffer from linear buffer cjne a,#HIGH(sser+lngsser),nocircle3 mov a,dpl cjne a,#LOW(sser+lngsser),nocircle3 mov dptr,#ssernocircle3: mov a,dpl CLR ES ;disable serial interrupt cjne a,s2point+1,xptchr ; neni plno, vysli znak mov a,dph cjne a,s2point,xptchr ; neni plno, vysli znak SETB ES ;enable serial interrupt sjmp nocircle3 ; je plno cekej na uvolnenixptchr: mov s1point, dph ; MSB mov s1point+1, dpl ; LSB SETB ES ;enable serial interrupt pop dpl pop dph.elsexputchar: push Acc MOV a,s1point xrl a,#sser+lngsser jnz xptchr ;neni plno, vysli znak djnz acc,. MOV a,s1point ;1th retry xrl a,#sser+lngsser jnz xptchr ;neni plno, vysli znak djnz acc,. MOV a,s1point ;2nd retry xrl a,#sser+lngsser jnz xptchr ;neni plno, vysli znak.ifdef RETRY4 djnz acc,. djnz acc,. MOV a,s1point ;3nd retry xrl a,#sser+lngsser jnz xptchr ;neni plno, vysli znak djnz acc,. djnz acc,. MOV a,s1point ;4nd retry xrl a,#sser+lngsser jnz xptchr ;neni plno, vysli znak.endif pop Acc clr A ;0 char send retpchar: mov a,R7putchar: push Accptchr: MOV a,s1point xrl a,#sser+lngsser jz ptchr ;je plno cekej na uvolnenixptchr: pop Acc push ar0 CLR ES ;disable serial interrupt mov r0,s1point MOV @r0,A ;uloz znak do bufferu inc s1point SETB ES ;enable serial interrupt pop ar0.endif jnb rtscts, ptchr1 jb CTS,ptchrr ;nezahajuj pripadne vysilaniptchr1: jnb xonxoff,ptchr2 jb flagtxoff, ptchrr ;nezahajuj pripadne vysilaniptchr2: jb srun,ptchrr setb srun setb TIptchrr: mov a,#1 ;1 char send ret;;#########################################################; Procedura zahajeni vysilani znaku do serioveho kanalu; a vypoctu delky vysilaci fronty;#########################################################;sstat:.ifdef LEDSERIAL mov C,srun cpl C mov LED0,C.endif CLR ES ;disable serial interrupt jb xonrq,sstat2 jb xoffrq,sstat2.if RD2SER mov a,s1point+1 ; otestuj pocet znaku v bufferu xrl a,s2point+1 ; LSB jnz sstat0 mov a,s1point ; MSB xrl a,s2point jz sstatexit ; neni co vysilatsstat0:.else MOV a,s1point ;spocitej pocet znaku v bufferu xrl A,#sser jz sstatexit ;neni co vysilat.endif jnb rtscts,sstat1 jb CTS,sstatexit ;nezahajuj vysilani, obsazenosstat1: jnb xonxoff,sstat2 jb flagtxoff,sstatexit ;nezahajuj vysilani, obsazenosstat2: jb srun,sstatexit ;nezahajuj vysilani, vysila se setb srun setb TIsstatexit: SETB ES ;enable serial interrupt ret;;#########################################################; Procedura Preruseni od prijateho znaku;#########################################################; .using 0intRITI:JBC RI,INT_READ ;je preruseni od prijimace JBC TI,INT_WRITE ;je preruseni od vysilace RETIINT_WRITE: PUSH PSW PUSH ACC.if RD2SER push dph push dpl push AUXR push EECON.else PUSH AR0.endif setb txint ;nastav priznak preruseni od vyslaneho znaku jnb xoffrq, int_w1 clr xoffrq setb flagxoff MOV SBUF,#XOFF ;vysli XOFF sjmp INT_WRITE_ENDint_w1: jnb xonrq, int_w2 clr xonrq clr flagxoff MOV SBUF,#XON ;vysli XON sjmp INT_WRITE_ENDint_w2: clr srun.if RD2SER mov a,s2point+1 ; otestuj pocet znaku v bufferu mov dpl, a xrl a,s1point+1 ; LSB jnz int_w0 mov a,s2point ; MSB xrl a,s1point jz INT_WRITE_END ; neni co vysilatint_w0:.else mov a,s1point ; send serial buffer - pointer 1 xrl a,#sser jz INT_WRITE_END ; neni co vysilat.endif jnb rtscts, int_w3 jb CTS,INT_WRITE_END ;nezahajuj pripadne vysilaniint_w3: jnb xonxoff,int_w4 jb flagtxoff,INT_WRITE_END ;nezahajuj pripadne vysilaniint_w4:.if RD2SER mov dph, s2point ; MSB ;mov dpl, s2point+1 ; LSB DISABLE_EE ENABLE_XRAM movx a,@dptr ; vyjmi znak z bufferu ;.._EE, .._XRAM disabled/enabled on exit mov SBUF,a ;vysli znak setb srun inc dptr mov a,dph ; make circle buffer from linear buffer cjne a,#HIGH(sser+lngsser),nocircle4 mov a,dpl cjne a,#LOW(sser+lngsser),nocircle4 mov dptr,#ssernocircle4: mov s2point, dph ; MSB mov s2point+1, dpl ; LSB.else mov r0,#sser MOV A,@r0 ;vyjmi data z bufferu MOV SBUF,A ;vysli znak setb srun mov r0,#LOW(sser+lngsser)flls: dec r0 xch a,@r0 cjne r0,#sser,flls dec s1point ;dec send serial buffer pointer.endifINT_WRITE_END:.if RD2SER pop EECON pop AUXR pop dpl pop dph.else POP AR0.endif POP ACC POP PSW RETI;INT_READ: .using 0 PUSH PSW PUSH ACC.if RD2SER push dph push dpl push AUXR push EECON.else PUSH AR0.endif setb rxint ;nastav priznak preruseni od prijateho znaku MOV A,SBUF ;precti znak jnb xonxoff,int_r0 cjne A,#XON,noXON clr flagtxoff sjmp int_r2noXON: cjne A,#XOFF,int_r0 setb flagtxoff sjmp int_r2.if RD2SERint_r0: mov dph, r2point ; MSB mov dpl, r2point+1 ; LSB DISABLE_EE ENABLE_XRAM movx @dptr,a ; save received char to buffer ;.._EE, .._XRAM disabled/enabled on exit inc dptr ; inc temp pointer to buffer mov a,dph ; make circle buffer from linear buffer cjne a,#HIGH(rser+lngsser),nocircle5 mov a,dpl cjne a,#LOW(rser+lngsser),nocircle5 mov dptr,#rsernocircle5: mov a,dpl cjne a,r1point+1,xgtchr ; not full, update pointer mov a,dph cjne a,r1point,xgtchr ; not full, update pointer sjmp int_r9xgtchr: mov r2point, dph ; MSB mov r2point+1, dpl ; LSBint_r9: clr C mov a, r1point+1 subb a, dpl ; LSB mov dpl,a mov a, r1point subb a, dph ; MSB jnb Acc.7,noadj2 add a,#HIGH(lngsser)noadj2: clr C jnz adj2 ; unused buffer space > 0xFF mov a,dpl cjne a,#20,.+3 ; if unused buffer space < 20 then reset RTS/adj2:.elseint_r0: mov r0,r1point ; receive serial buffer cjne r0,#LOW(rser+lngrser),xgtchr sjmp int_r9xgtchr: mov @r0,a ;uloz data do bufferu inc r1pointint_r9: mov a,r1point cjne a,#(rser+MAXCHAR),.+3 cpl C ;if v bufferu je > MAXCHAR znaku then reset RTS/.endif jnb rtscts,int_r1 mov RTS,Cint_r1: jnb xonxoff,int_r2 jnc int_r2 ;XON request jb flagxoff,int_r2 ;O.K. jb srun,intr2 ;nezahajuj vysilani, vysila se setb flagxoff mov SBUF,#XOFF ;vysli XOFF setb srun sjmp int_r2intr2: setb xoffrq ;XOFF requestint_r2:.if RD2SER pop EECON pop AUXR pop dpl pop dph.else POP AR0.endif POP ACC POP PSW RETI;;#########################################################; INIT;#########################################################; .section reset_device, #allocinit_serial: orl PCON,#0x80 mov SCON,#0x52.ifdef BDT2.else orl TMOD,#0b00100000 ;timer 1, autoreload 8 bit.endif ENABLE_EE mov dptr,#flash_flow movx a,@dptr mov C,B2B(ACC,optrtscts) mov rtscts,C mov C,B2B(ACC,optxonxoff) mov xonxoff,C mov dptr,#flash_baud movx a,@dptr DISABLE_EE.ifdef BDT2 anl a,#0x07 ; may be, safety mask rl a mov r1,a mov dptr,#baudtable movc a,@a+dptr mov RCAP2H, A mov a,r1 inc a movc a,@a+dptr mov RCAP2L, A mov T2CON, #0x30.else mov R1,a ;1..7 clr A setb Cbdlp: rlc A djnz R1,bdlp mov b,#LOW(CPUCLOCK/384) mul ab cpl a inc a MOV TH1,a MOV TL1,a orl TCON,#0xC0 ;start timer1.endif.if RD2SER mov r1point,#HIGH(rser) ;receive serial buffer - MSB pointer 1 mov r1point+1,#LOW(rser) ;receive serial buffer - LSB pointer 1 mov r2point,#HIGH(rser) ;receive serial buffer - MSB pointer 2 mov r2point+1,#LOW(rser) ;receive serial buffer - LSB pointer 2 mov s1point,#HIGH(sser) ;send serial buffer - MSB pointer 1 mov s1point+1,#LOW(sser) ;send serial buffer - LSB pointer 1 mov s2point,#HIGH(sser) ;send serial buffer - MSB pointer 2 mov s2point+1,#LOW(sser) ;send serial buffer - LSB pointer 2.else mov r1point,#rser ;receive serial buffer - pointer 1 mov s1point,#sser ;send serial buffer - pointer 1.endif jnb rtscts, init_ser1 clr RTS ;povol prijem mov SBUF,#0init_ser1: jnb xonxoff, init_ser2 clr flagtxoff clr xoffrq clr xonrq mov SBUF,#XON ;direct send XON setb sruninit_ser2:.ifdef BDT2 setb TR2 orl IE,#0b00010000 ; enable serial port interrupt.else setb TR1 orl IE,#0b00010000 ; enable serial port interrupt.endif;.ifdef BDT2 .text.global baudtablebaudtable: .word 0x10000 - ((CPUFRQ+(16*384))/(32*384)) ; not used .word 0x10000 - ((CPUFRQ+(16*384))/(32*384)) ; 38400 .word 0x10000 - ((CPUFRQ+(16*192))/(32*192)) ; 19200 .word 0x10000 - ((CPUFRQ+(16* 96))/(32* 96)) ; 9600 .word 0x10000 - ((CPUFRQ+(16* 48))/(32* 48)) ; 4800 .word 0x10000 - ((CPUFRQ+(16* 24))/(32* 24)) ; 2400 .word 0x10000 - ((CPUFRQ+(16* 12))/(32* 12)) ; 1200 .word 0x10000 - ((CPUFRQ+(16* 6))/(32* 6)) ; 600.endif; ;; END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -