Sunteți pe pagina 1din 8

;*************************************************************************

;
; ** PROGRAMA 7 **
;
;*************************************************************************
PAGE 60, 132
TITLE POS_ASM
PUBLIC START,INIT_PORT,RX_BYTE,TX_BYTE,SCR_BYTE
PUBLIC RX_MESSAGE, TX_RESP
;-------------------------------------------------------------------------
;EJEMPLO DE UN PROGRAMA DE COMUNICACION SERIE PROGRAMANDO EL UART
; MANEJA EL PROTOCOLO DE COMUNICACION DEL POS
;-------------------------------------------------------------------------
;
; SIMBOLOS
;
STX EQU 02H
ETX EQU 03H
EOT EQU 04H
ENQ EQU 05H
ACK EQU 06H
NAK EQU 15H
RX_GOOD EQU 0000H
ST_TIMEOUT EQU 1000H
LRC_BAD EQU 2000H
BYTE_ERR EQU 3000H
BYTE_RDY EQU 4000H
BYTE_NORDY EQU 5000H
TIMEOUT EQU 05H ;DEFINE TIEMPO DE TIME OUT
RETARDO EQU 03H ;DEFINE DELAY
;
;--------------------------------------------------------------------------
; SEGMENTO DE STACK
;--------------------------------------------------------------------------
;
STACKSG SEGMENT PARA STACK 'STACK'
DB 256 DUP (0) ;256 BYTES - ESPACIO DE STACK
STACKSG ENDS
;
;--------------------------------------------------------------------------
; SEGMENTO DE DATOS
;--------------------------------------------------------------------------
;
DATASG SEGMENT PARA 'DATA'
TEXTO01 DB 'INICIO DEL PROGRAMA',0AH,0DH,'$'
TEXTO02 DB 'ENVIA ENQ ' ,0AH,0DH,'$'
TEXTO03 DB 'VA A RECIBIR MENSAJE ',0AH,0DH,'$'
TEXTO04 DB 'VA A TRANSMITIR EL MENSAJE',0AH,0DH,'$'
TEXTO05 DB 'VA A RECIBIR ACK O NAK',0AH,0DH,'$'
TEXTO06 DB 'ENVIA EL EOT',0AH,0DH,'$'
TEXTO07 DB 'LRC_BAD',0AH,0DH,'$'
TEXTO08 DB 'TIMEOUT',0AH,0DH,'$'
RX_BUFF DB 300 DUP (?)
TX_BUFF DB 'MENSAJE DE PRUEBA DE TRANSMISION',00H
DATASG ENDS
;
;--------------------------------------------------------------------------
; SEGMENTO DE CODIGOS
;--------------------------------------------------------------------------
;
CODESG SEGMENT PARA PUBLIC 'CODE'
START PROC FAR
;
;PARTE STANDAR DEL PROGRAMA, PARA SALVAR DIRECCION DE RETORNO
;
ASSUME CS:CODESG, SS:STACKSG, DS:DATASG
;
PUSH DS ;SAVE PSP SEG ADDR
MOV AX,0
PUSH AX ;SAVE RET ADDR OFFSET (PSP+0)
MOV AX,DATASG ;PARA INICIALIZAR EL SEGMENTO DE DATOS
MOV DS,AX ;DS CON DATASG
;
; PROGRAMA PRINCIPAL
;
LEA DX,TEXTO01
CALL B10PRMP
CALL INIT_PORT
LAZO:
LEA DX,TEXTO02
CALL B10PRMP
MOV AL,ENQ ;PARA ENVIAR EL ENQ
CALL TX_BYTE ;ENVIANDO EL ENQ
REC_MENS:
LEA DX,TEXTO03
CALL B10PRMP
LEA DI,RX_BUFF ;PUNTERO DEL BUFFER DE RX DEL MENSAJE
CALL RX_MESSAGE ;RECIBIENDO EL MENSAJE
CMP AX,ST_TIMEOUT ;CHEQUEA SI OCURRIO UN TIMEOUT
JNE CHK_LRC00
LEA DX,TEXTO08
CALL B10PRMP
JMP LAZO
CHK_LRC00:
CMP AX,LRC_BAD
JNE TRANS_MENS
LEA DX,TEXTO07 ;PARA ENVIAR MENSAJE DE ERROR DEL LRC
CALL B10PRMP ;ENVIANDO MENSAJE DE ERROR DEL LRC
MOV AL,NAK ;PARA ENVIAR EL NAK
CALL TX_BYTE ;ENVIADO EL NAK
JMP REC_MENS ;VA A RECEPCIONAR DENUEVO EL MENSAJE
TRANS_MENS:
LEA DX,TEXTO04
CALL B10PRMP
LEA SI,TX_BUFF ;PUNTERO DEL BUFFER DE TX DEL MENSAJE
CALL TX_RESP ;ENVIANDO EL MENSAJE
LEA DX,TEXTO05
CALL B10PRMP
CALL RX_BYTE ;RECIBIENDO CONFIRMACION DEL MENSAJE TX
CMP AX,ST_TIMEOUT ;PARA VER SI OCURRIO UN TIMEOUT
JE TRANS_MENS ; SI TIMEOUT TRANSMITE DENUEVO
CMP AL,NAK ;PARA CHEQUEAR SI POS REPONDIO CON NAK
JE TRANS_MENS ;SI POS ENVIO NAK RE-ENVIA EL MENSAJE
CMP AL,ACK ;PARA CHEQUEAR SI EL POS RESPONDIO CON ACK
JNE TRANS_MENS ;SALTA A TRANS_MENS SI RECIBIO UN BAD_ACK
LEA DX,TEXTO06
CALL B10PRMP
MOV AL,EOT ;PARA ENVIAR EL EOT
CALL TX_BYTE ;ENVIANDO EL EOT
JMP LAZO ;VA A ENVIAR ENQ DENUEVO
;

;
START ENDP
;--------------------------------------------------------------------------
; RUTINA PARA INICIALIZAR EL PORT SERIAL
;--------------------------------------------------------------------------
;
;INIT_PORT: INICIALIZA EL UARTE 8250 UART PARA:
; 7 DATA BITS, 1 STOP BIT , ODD PARITY, Y 1200 BAUD
; SETEA OPCION DE LOOPBACK
;
INIT_PORT PROC NEAR
MOV DX,3FBH ;ADDRESS OF LINE CONTROL REGISTER
MOV AL,80H
OUT DX,AL ;TO ADDRESS BAUD RATE DIVISOR REGISTER
MOV DX,3F8H ;ADDRESS OF BAUD RATE DIVISOR LSB
MOV AL,60H ;LSB VALUE FOR 1200 BAUD
OUT DX,AL
MOV DX,3F9H ;ADDRESS OF BAUD RATE DIVISOR MSB
MOV AL,0 ;MSB VALUE FOR 1200 BAUD
OUT DX,AL
;THE BAUD RATE HAS NOW BEEN INITIALIZED
;NOW INITIALIZE THE LINE CONTROL REGISTER
MOV DX,3FBH ;ADDRESS OF THE LINE CONTROL REGISTER
MOV AL,0AH ;ODD PATITY, 1 STOP BIT , 7 DATA BITS
OUT DX,AL
;NOW INITIALIZE THE MODEM CONTROL REGISTER FOR :
; REQUEST TO SEND AND DATA TERMINAL READY SIGNALS
; AND SET THE LOOPBACK FEATURE
;
MOV DX,3FCH ;ADDRESS OF MODEM CONTROL REGISTER
MOV AL,03H ;SET LOOPBACK AND MODEM CNTL SIGNALS
OUT DX,AL
;NOW DISABLE ALL FOUR CLASSES OF INTERRUPS
MOV DX,3F9H ;ADDRESS OF INTERRUPT ENABNLE REGISTER
MOV AL,0
OUT DX,AL
;THE INITIALIZATION OF THE 8250 IS NOW COMPLETE
RET
INIT_PORT ENDP
;--------------------------------------------------------------------------
; RUTINA QUE ENVIA UN BYTE AL PORT
; INPUT : EL AL = EL BYTE A ENVIAR
; PROCESO : ENVIA EL BYTE QUE ESTA EN EL REG AL POR EL PORT
; OUTPUT : NINGUNO
;--------------------------------------------------------------------------
TX_BYTE PROC NEAR
;
; CHEQUEANDO SI EL BUFFER DE TX ESTA LIBRE PARA TRANSMITIR
;
; JMP SCR_BYTE ; CUANDO ENVIA BYTE POR PANTALLA
PUSH DX
PUSH AX
TX_WAIT: MOV DX,3FDH ;ADDRESS OF LINE STATUS REGISTER
IN AL,DX ;LINE STATUS REGISTER IN AL
TEST AL,20H ;TEST FOR TRANSMITTER DATA FREE
JZ TX_WAIT
;
; EL REG. AL TIENE EL CARACTER A TRANSMITIR
;
POP AX
MOV DX,3F8H ;ADDRESS OFF TRANSMITTER HOLDING REGISTER
OUT DX,AL ;TRANSMIT THE CHARACTER
POP DX
RET
SCR_BYTE: ; ENVIA EL BYTE A LA PANTALLA
PUSH BX
MOV BX,0
MOV AH,14 ;DISPLAY FUNCTION CODE
INT 10H ;BIOS CALL
POP BX
RET
TX_BYTE ENDP

;-----------------------------------------------------------------------------
; RUTINA PARA IMPRIMIR UN STRING POR PANTALLA
; INPUT : DX = TIENE LA DIRECCION DE INICIO DEL STRING A ENVIAR
; PROCESO : ENVIA UN STRING POR PANTALLA, EL DELIMITADOR ES '$'
; OUTPUT : NINGUNO
;-----------------------------------------------------------------------------
B10PRMP PROC NEAR
MOV AH,09
INT 21H
RET
B10PRMP ENDP
;
;----------------------------------------------------------------------------
; RUTINA DE RECEPCION DE MENSAJE
; INPUT : DI = DIRECCION DEL BUFFER DE RECEPCION DEL MENSAJE
; PROCESO : RECIBE EL MENSAJE ENVIADO POR EL POS, DETECTA AL STX Y
; EL ETX, ADEMAS CALCULA EL LRC Y LO COMPARA CON EL
; RECIBIDO PARA CHEQUEAR SI OCURRIO ALGUN ERROR
; OUTPUT : AX = CONTIENE EL ESTADO DE LA RECEPCION
; AX = RX_GOOD SI NO HAY ERROR
; AX = LRC_BAD SI HAY ERROR DE LRC
; AX = TIMEOUT SI OCURRE UN TIME OUT
;----------------------------------------------------------------------------
RX_MESSAGE PROC NEAR
;
; RECIBIENDO EL STX
WAIT_STX:
CALL RX_BYTE
CMP AX,ST_TIMEOUT ;CHEQUEA SI OCURRIO UN TIMEOUT
JE RX_TIMEOUT ;SI OCURRIO TIMEOUT
CMP AL,STX
JNE WAIT_STX
; CUANDO SE RECIBIO EL STX
SUB BL,BL ; BL = 0 PARA ALMACENAR EL LRC
RX_LAZO:
CALL RX_BYTE
CMP AX,ST_TIMEOUT ;CHEQUEA SI OCURRIO UN TIMEOUT
JE RX_TIMEOUT ;SI OCURRIO TIMEOUT
CMP AL,ETX
JZ FIND_ETX
XOR BL,AL ;CALCULANDO EL LRC
MOV [DI],AL ;ALMACENANDO BYTE RECIBIDO
INC DI ;INCREMENTANDO EL PUNTERO
JMP RX_LAZO
FIND_ETX:
XOR BL,AL ;CALCULANDO EL LRC
MOV AL,'$'
MOV [DI],AL
; PARA RECIBIR EL LRC
CALL RX_BYTE
CMP BL,AL
JZ LRC_GOOD
MOV AX,LRC_BAD
RET
LRC_GOOD:
MOV AX,RX_GOOD
RET
RX_TIMEOUT:
MOV AX,ST_TIMEOUT
RET
RX_MESSAGE ENDP
;---------------------------------------------------------------------------
; RUTINA DE TRANSMISION DE MENSAJE
; INPUT : SI = DIRECCION DEL BUFFER DEL MENSAJE A ENVIAR
; PROCESO : ENVIA UN MENSAJE POR EL PORT, PONIENDO EL STX Y ETX,
; ADEMAS CALCULA EL LRC Y LO ENVIA
; USA EL VALOR 00 COMO DELIMITADOR DEL MENSAJE PERO
; NO LO ENVIA
; OUTPUT : NINGUNO
;---------------------------------------------------------------------------
TX_RESP PROC NEAR
;
; ENVIANDO EL STX
MOV AL,STX
CALL TX_BYTE
; ENVIANDO EL MENSAJE
SUB BL,BL ;BL = 0 PARA ALMACENAR EL LRC
TX_LAZO:
MOV AL,[SI] ;OBTIENE EL BYTE A ENVIAR
INC SI ;INCREMENTANDO EL PUNTERO
CMP AL,00 ;CHEQUEA SI ES EL DELIMITADOR
JE FIND_NULL
XOR BL,AL ;CALCULA EL LRC
CALL TX_BYTE ;ENVIA EL BYTE
JMP TX_LAZO
FIND_NULL:
MOV AL,ETX ;PARA ENVIAR EL ETX
XOR BL,AL ;CALCULANDO EL LRC
CALL TX_BYTE ;ENVIANDO EL ETX
MOV AL,BL ;PARA ENVIAR EL LRC
CALL TX_BYTE ;ENVIADO EL LRC
RET
TX_RESP ENDP
;-----------------------------------------------------------------------------
; RUTINA QUE RECIBE UN BYTE DEL PORT
; INPUT : NINGUNO
; PROCESO : LEE EL BYTE O INDICA SI OCURRIO UN TIMEOUT
; OUTPUT : EN AL = BYTE LEIDO
; AX = ST_TIMEOUT SI OCURRIO TIMEOUT
;-----------------------------------------------------------------------------
RX_BYTE PROC NEAR
;
CALL RX_STAT
CMP AX,BYTE_ERR
JE ERROR ;CUANDO SE DETECTO UN ERROR
CMP AX,ST_TIMEOUT
JNE RECEIVED
RET
RECEIVED: CALL GET_BYTE ; VA A LEER BYTE
RET
;
ERROR: CALL GET_BYTE ; LEE BYTE ERRADO
MOV AL,00 ; CONVIERTE EN NULL A BYTE ERRADO
RET
RX_BYTE ENDP

;-----------------------------------------------------------------------------
; RUTINA QUE CHEQUEA EL STATUS DEL PORT
; RESPECTO A LA RECEPCION DE UN BYTE
; INPUT : NINGUNO
; PROCESO: LEE EL ESTADO DEL PUERTO RESPECTO A LA RECEPCION
; MANEJANDO EL TIMEOUT
; OUTPUT : EN AX INDICA EL ESTADO DEL PORT
; SI AX = BYTE_RDY SE HA RECEPCIONADO UN BYTE
; AX = ST_TIMEOUT SI OCURRIO UN TIMEOUT
; AX = BYTE_ERR SE HA RECEPCIONADO UN BYTE CON ERROR
;-----------------------------------------------------------------------------
RX_STAT PROC NEAR
;
PUSH CX
MOV CX,TIMEOUT ;SETEA EL TIEMPO DE TIMEOUT
RX_WAIT0:
PUSH CX
MOV CX,0B7D3H
RX_WAIT1:
CALL GET_STAT
CMP AX,BYTE_RDY
JE RX_OUT ;SI SE RECIBIO UN CARACTER
CMP AX,BYTE_ERR
JE RX_OUT ;SI SE RECIBIO CARACTER CON ERROR
LOOP RX_WAIT1
POP CX
LOOP RX_WAIT0
MOV AX,ST_TIMEOUT ;SI OCURRIO EL TIMEOUT
POP CX
RET
RX_OUT: ; PARA SALIR DE LA RUTINA SIN VARIAR EL ESTADO DADO POR GET_STAT
POP CX
POP CX
RET
RX_STAT ENDP
;-----------------------------------------------------------------------------
; RUTINA QUE INDICA EL ESTADO DEL PUERTO ( O TECLADO)
; RESPECTO A LA RECEPCION DE UN BYTE
; INPUT : NINGUNO
; PROCESO: LEE EL ESTADO DEL PUERTO RESPECTO A LA RECEPCION
; OUTPUT : EN AX INDICA EL ESTADO DEL PUERTO
; SI AX = BYTE_RDY SE HA RECEPCIONADO UN BYTE
; AX = BYTE_NORDY NO SE HA RECEPCIONADO UN BYTE
; AX = BYTE_ERR SE HA RECEPCIONADO UN BYTE CON ERROR
;-----------------------------------------------------------------------------
GET_STAT PROC NEAR
PUSH DX
;
; OBTENIENDO STATUS DEL PORT
;
; JMP GET_KEY ; **SI SE DESEA EL STATUS DEL TECLADO**
;
MOV DX,3FDH ;ADDRESS OF LINE STATUS REGISTER
IN AL,DX ;LINE STATUS REGISTER IN AL
TEST AL,1EH ;TEST FOR A RECEPTION ERROR
JNZ GET_ERROR ;RECEIVE ERROR HANDLING
TEST AL,01H ;TEST FOR RECEIVED DATA READY
JNZ GET_RDY ;SI SE RECIBIO UN CARACTER
JMP GET_NORDY ;SI NO RECIBIO UN CARACTER
;
; OBTENIENDO ELK STATUS DEL TECLADO
;
GET_KEY:
MOV AH,1 ;CHECK KEYBOARD BUFFER CODE
INT 16H ;BIOS CALL
JNZ GET_RDY ;SI SE RECIBIO UN CARACTER
JMP GET_NORDY ;SI NO RECIBIO UN CARACTER
GET_RDY: ;CUANDO SE RECIBIO UN CARACTER
MOV AX,BYTE_RDY
POP DX
RET
GET_NORDY: ;CUANDO NO SE RECIBIO UN CARACTER
MOV AX,BYTE_NORDY
POP DX
RET
GET_ERROR: ;CUANDO SE RECIBIO UN CARACTER CON ERROR
MOV AX,BYTE_ERR
POP DX
RET
GET_STAT ENDP
;
;-----------------------------------------------------------------------------
; RUTINA QUE LEE UN BYTE DEL PUERTO (0 EL TECLADO)
; INPUT : NINGUNO
; PROCESO : LEE EL BYTE DEL PORT O EL TECLADO
; OUTPUT : REG. AL CON EL BYTE LEIDO
;-----------------------------------------------------------------------------
GET_BYTE PROC NEAR
;
; JMP KEY_RX ;CUANDO LEE DEL TECLADO
;
; LEYENDO EL BYTE DEL PORT
PUSH DX
MOV DX,3F8H ;ADDRESS OF THE RECEIVED DATA REGISTER
IN AL,DX ;AL HAS THE RECEIVED CHARACTER
AND AL,7FH ;LIMPIANDO EL BIT DE PARIDAD
POP DX
RET

KEY_RX: ;LEYENDO EL BYTE DEL TECLADO


MOV AH,0 ;GET KEYBOARD INPUT CODE
INT 16H ;BIOS CALL
RET
GET_BYTE ENDP

;--------------------------------------------------------------------------
;
CODESG ENDS
END START

S-ar putea să vă placă și