// 假设所有的数据存放在XDATA中
//
// 在发送数据的时候将pSend设置好,指向要发送的数据
// 数据包的格式
// START_F + CMD + DATAS + CHECKSUM + END_F
// 定义 START = 0X7E, END_F = 0X7F, ESC_F = 0X7D
// 当数据中包含以上3个字符时, 转义, 方法是
// 转义后的字符 = 转移前的字符 ^ 0x20
// eg : 30, 40, 7e, 55, 7f ---> 30, 40, 7d, 5e, 55, 7d, 5f
// --- --- ------- ------
//
// lenglianxi@tom.com
SerProc() interrupt 4 using 2
{
static char xdata * pRcv;
static uchar cCheckSum;
static bit bEsc, bRcving;
uchar cTemp;
if(TI){
TI = 0;
if(bSendFin){
bSendFin = 0;
REN = 1;
}
else{
cTemp = *pSend;
pSend++;
SBUF = cTemp;
if(cTemp == END_F)
bSendFin = 1;
}
}
// recived some data
else{
RI = 0;
cTemp = SBUF;
switch(cTemp){
case START_F:
pRcv = SerBuf+1;
SerBuf[0] = START_F;
cCheckSum = START_F;
bEsc = 0;
bRcving = 1;
break;
case END_F:
ES = 0;
cCheckSum += END_F;
bSerRcved = 1;
bCheckSumErr = cCheckSum == 0 ? 0 : 1;
bRcving = 0;
break;
case ESC_F:
bEsc = 1;
break;
default:
if(bRcving){
if(bEsc)
*pRcv = cTemp ^ 0x20;
else
*pRcv = cTemp;
cCheckSum += *pRcv;
pRcv ++;
bEsc = 0;
}
}
}
}
CSEG AT 23H
JMP SERPROC
RSEG BITS
PUBLIC SER_RCVED
SEND_FINISH: DBIT 1
SER_RCVED: DBIT 1
ESC_FLAG: DBIT 1
IS_RCVING: DBIT 1
RSEG DATAS
PUBLIC R_PNT
R_PNT : DS 2
S_PNT : DS 2
RSEG CODES
PUBLIC INIT_SER_SEND
INIT_SER_SEND:
USING 0
MOV S_PNT, #HIGH(0A000H)
MOV S_PNT+1, #LOW(0A000H)
SETB SEND_DIR
CLR SEND_FINISH
SETB TI
RET
RSEG CODES
SERPROC:
USING 2
PUSH ACC
PUSH B
PUSH PSW
MOV PSW, #10H
JBC TI, SER_SEND
; ser recive proc
CLR RI
MOV A, SBUF
MOV B, A
CJNE A, #START_F, SER_NOT_R_START
CLR A
MOV R_PNT, A
MOV R_PNT+1, A
CLR SER_RCVED
CLR ESC_FLAG
SETB IS_RCVING
JMP SER_R_DATA
SER_NOT_R_START:
JNB IS_RCVING, SER_EXIT
CJNE A, #END_F, SER_NOT_R_END
SETB SER_RCVED
CLR IS_RCVING
JMP SER_R_DATA
SER_NOT_R_END:
JBC ESC_FLAG, SER_ESC_PREV
CJNE A, #ESC_F, SER_R_DATA
SETB ESC_FLAG
JMP SER_EXIT
SER_ESC_PREV:
XRL B, #20H
SER_R_DATA:
BACKUP_HI_ADDR
PUSH DPS
PUSH DPH
PUSH DPL
MOV DPS, #0
CHANGE_RAM 1
MOV DPH, R_PNT
MOV DPL, R_PNT + 1
MOV A, B
MOVX @DPTR, A
INC DPTR
MOV R_PNT, DPH
MOV R_PNT+1, DPL
CALL CHANGECOMMLAMP
POP DPL
POP DPH
POP DPS
RESTORE_HI_ADDR
JMP SER_EXIT
SER_SEND:
JB SEND_FINISH, SER_S_FIN
BACKUP_HI_ADDR
PUSH DPS
PUSH DPH
PUSH DPL
CHANGE_RAM 1
MOV DPS, #0
MOV DPH, S_PNT
MOV DPL, S_PNT + 1
MOVX A, @DPTR
MOV SBUF, A
INC DPTR
MOV S_PNT, DPH
MOV S_PNT + 1, DPL
CJNE A, #END_F, SER_S_EXIT
SETB SEND_FINISH
SER_S_EXIT:
POP DPL
POP DPH
POP DPS
RESTORE_HI_ADDR
JMP SER_EXIT
SER_S_FIN:
CLR SEND_DIR
SER_EXIT:
POP PSW
POP B
POP ACC
RETI
END