;******************************************************************************
;
; Nombre: TxRx_0.asm
; Fecha: 02/09/2008
; Version: v0.90
;
; Autor: Sander
; Empresa:
;
;********************************************************************************
;
; Archivos Requeridos: P18F4550.INC
;
;********************************************************************************
; Notas: El programa muestra el uso del EUSART para realizar una comunicacion
; asincrona con la PC, para este ejemplo configuraremos el oscilador
; para que funcione a 48 MHz usando un cristal externo de 4 MHz.
;
; Para configurar la velocidad de transmision se usara el modo de 16 bits y
; el modo de alta de velocidad para el generador de baudios (BRG16=1; BRGH=1),
; para este caso tenemos que la velocidad esta dada por:
;
; Vel = Fosc/[4(n+1)] Donde n es el valor que se carga a SPBRGH:SPBRG
; n = [(Fosc/Vel)-1]/4
;
; ---------------------------------------------------------------------------
; |Velocidad |Valor n |Valor para |Valor Hex para |Velocidad | % |
; |(Baudios) | |SPBRGH:SPBRG |SPBRGH:SPBRG |real | Error |
; ---------------------------------------------------------------------------
; | 110 | 109090,66 | -------- | -------- | ------- | ----- |
; | 300 | 39999,75 | 39999 | 0x9C3F | 300 | 0 |
; | 1200 | 9999,75 | 9999 | 0x270F | 1200 | 0 |
; | 2400 | 4999,75 | 4999 | 0xC34F | 2400 | 0 |
; | 4800 | 2499,75 | 2499 | 0x09C3 | 4800 | 0 |
; | 9600 | 1249,75 | 1249 | 0x04E1 | 9600 | 0 |
; | 19600 | 611,99 | 611 | 0x0263 | 19607,84 | 0,04 |
; | 38400 | 312,25 | 312 | 0x0137 | 38338,65 | 0,16 |
; | 57600 | 208,08 | 207 | 0x00CF | 57692,30 | 0,16 |
; | 115200 | 103,91 | 103 | 0x0067 | 115384,61 | 0,16 |
; | 230400 | 51,83 | 51 | 0x0033 | 230769,23 | 0,16 |
; | 460800 | 25,79 | 25 | 0x0019 | 461538,46 | 0,16 |
; | 921600 | 12,77 | 12 | 0x000C | 923076,92 | 0,16 |
; ---------------------------------------------------------------------------
; Tabla 1
; Lo que el programa hara es recibir caracteres e ir almacenandolos en BufferRx,
; dejara de recibir caracteres si recibe el caracter enter(0x0D ), si ya han
; llegado 256 caracteres, o si se ha dejado de recibir caracteres durante 2
; segundos aproximadamente.
;
; Cuando se deja de recibir los caracteres , el microcontrolador recorrera el
; arreglo BufferRx y convertira todas las letras minusculas en mayusculas , la
; cadena modificada se ira guardando en BufferTx , durante este proceso cualquier
; caracter recibido sera descartado, una vez que BufferTx haya sido cargado con
; todos los caracteres estos seran enviados de regreso a la PC.
;
; Tanto para la recepcion como para la transmision se usran interrupciones,
; cualquier retardo que se necesite sera realizado usando el TMR0
;**********************************************************************************
LIST P=18F4550 ;Directiva para definir el procesador
#include <P18F4550.INC> ;Definicion de SFRs para el procesador
;******************************************************************************
;Bits de Configuracion
;Microchip ha cambiado el formato para definir los bits de configuracion, por favor
;revisar el archivo P18F4550.INC para informacion adicional de la notacion
;Abajo hay algunos ejemplos
;******** Configuracion del Oscilador **********
CONFIG FOSC = XTPLL_XT ;Osc XT que pasa a travez del PLL,USB usa
;el Osc XT
CONFIG PLLDIV = 1 ;La entrada del Osc de 4 MHz va directo al PLL
CONFIG CPUDIV = OSC1_PLL2 ;La salida del PLL (96 MHz) , la dividimos entre dos
;para que sea la señal del oscilador del sistema,
;Entoces tenemos 48 MHz
;******** Otros bits de configuracion **********
CONFIG PWRT = ON ;PWRT habilitado
CONFIG BOR = OFF ;Brown out resete deshabilitado
CONFIG WDT = OFF ;Watch dog deshabilitado
CONFIG MCLRE = OFF ;MCLR como entrada
CONFIG PBADEN = ON ;Todos los pines como entradas analogicas
CONFIG LVP = OFF ;programacion en bajo voltaje deshabilitado
;********* Bits de proteccion ******************
CONFIG CP0 = OFF ;los bloques del codigo de programa
CONFIG CP1 = OFF ;no estan protegidos
CONFIG CP2 = OFF
CONFIG CP3 = OFF
CONFIG CPB = OFF ;Sector Boot no esta protegido
CONFIG CPD = OFF ;La EEPROM no esta protegida
;******************************************************************************
; Definicion de variables
; Estas variables son necesarias solo si las interrupciones de baja prioridad son usadas.
; Mas variables podrian se necesarias para almacenar otros SFRs usados en las rutinas de
; interrupcion.
VelHI EQU 0x04 ;Estas constantes sirven para definir la velocidad
VelLO EQU 0xE1 ;de la comunicacion, 9600 baudios
CBLOCK 0x080
WREG_TEMP ;variable usada para salvar contexto
STATUS_TEMP ;variable usada para salvar contexto
BSR_TEMP ;variable usada para salvar contexto
ENDC
CBLOCK 0x000 ;Variables en la ACCESS RAM (Banco 0) max 96 bytes
ContT0 ;para contar las veces que TMR0 desborda
ContRx ;para contar los bytes recibidos
ContTx ;para contar los bytes transmitidos
DatoRx ;variable temporal para la recepcion
DatoTemp ;usado como variable auxiliar
Banderas
TablaOffs ;Para movernos en las tablas
ENDC
CBLOCK 0x100 ;Variables en el Banco 1
BufferRx:.256 ;Buffer para la recepcion
ENDC
CBLOCK 0x200 ;Variables en el banco 2
BufferTx:.256 ;Buffer para la transmision
ENDC
#DEFINE TimeOut Banderas,.0 ;=1 si el pasan 2 seg
#DEFINE RxOK Banderas,.1 ;=1 si se termino de recibir
#DEFINE TxOK Banderas,.2
;******************************************************************************
;Datos de la EEPROM
;Los Datos a ser programados en la EEPROM son definidos aqui
ORG 0xf00000
DE "Test Data",0,1,2,3,4,5
;******************************************************************************
; Vector de Reset.
; Este codigo comenzara a ejecutarse cuando suceda un reset
ORG 0x0000
goto Main ;Se va al inicio del codigo principal
;******************************************************************************
; Vector de interrupcion de alta prioridad
; Este codigo comenzara a ejecutarse cuando una interrupcion de alta prioridad ocurra
; o cuando cualquier interrupcion ocurra si es que las prioridades de las interrupciones
; no estan habilitadas
ORG 0x0008
bra LowInt ;cuando las prioridades estan deshabilitadas
;se salta a 0x0008 en caso de interrupcion
;******************************************************************************
; Vector de interrupcion de baja prioridad y rutina
; Este codigo comenzara a ejecutrase cuando una interrupcion de baja prioridad ocurra
; Este codigo puede ser eliminado si las interrupciones de baja prioridad no son usadas
ORG 0x0018
LowInt
movff STATUS,STATUS_TEMP ;Salva el registro STATUS
movff WREG,WREG_TEMP ;Salva el registro de trabajo
movff BSR,BSR_TEMP ;Salva el registro BSR
; *** El codigo de la interrupcion de baja prioridad va aqui ***
btfsc INTCON,TMR0IF ;Interrupcion del TMR0
bra IntT0 ;Si => vamos a IntT0
btfsc PIR1,RCIF ;No => interupcion de recepcion?
bra IntRx ;Si => vamos a IntRx
btfsc PIR1,TXIF ;No => interrupcion de transmision?
bra IntTx ;Si => vamos a IntTx
movlw .6 ;No => enviamos mensaje de error
call EnvMsg ;
sleep ;y dormimos
;**************************** IntT0 **********************************
; IntT0 atiende la interrupcion de desborde del TMR0 y controla
; cuando transcuren dos segundos sin recibir nada para producir
; el time out
;*************************************************************************
IntT0
movlw 0x61
movwf TMR0L ;recargamos TMR0L, para desbordes de 100 ms
bcf INTCON,TMR0IF ;limpiamos la bandera de interrupcion
decfsz ContT0 ;ContT0 --, ya paso 2 seg?
bra IntT0_X ;No => salimos
bsf TimeOut ;Si => indicamos que hubo un time out
bra IntT0_X
IntT0_X
bra SalirInt ;Vamos a salir de las interrupciones
;****************************************************************************
;**************************** IntRx **********************************
; IntRx se encarga de guardar los bytes recibidos en el BufferRx,
; descarta los bytes recibidos cuando se esta procesando la trama
; ademas controla cuando el buffer de recepcion desborda
;*************************************************************************
IntRx
btfsc RCSTA,OERR ;Desbordo el buffer de recepcion?
bra IntRx_Er1 ;vamos a atender el error
btfsc RxOK ;termino la recepcion?
bra IntRx_P1 ;Si => vamos a descartar el caracter recibido
movf RCREG,W,.0 ;No => guardamos el caracter
movwf DatoRx
movlw 0x0D ;Revisamos si se recibio enter
xorwf DatoRx,W,.0
btfsc STATUS,Z ;RCREG == 0x0D?, se recibio 0x0D(enter)?
bra IntRx_P0_1 ;Si => vamos a terminar la recepcion
movf DatoRx,W,.0 ;No => guardamos el caracter
movwf POSTINC0 ;Guardamos e incrementamos FSR
movlw .20
movwf ContT0 ;Reiniciamos el contador para el TimeOut
incfsz ContRx,F,.0 ;ContRx llego a 256, (desbordo?)
bra IntRx_X ;No => terminamos
;Si => tenemos 256 caracteres recibidos
IntRx_P0_1
bsf RxOK ;ponemos en 1 RxOK
bra IntRx_X
IntRx_P1
movf RCREG,W,.0 ;Descartamos el byte recibido
bra IntRx_X
IntRx_Er1
bcf RCSTA,CREN
bsf RCSTA,CREN ;Reiniciamos el EUSART
movf RCREG,W,.0 ;Descartamos el byte recibido
IntRx_X
bra SalirInt ;Vamos a salir de las interrupciones
;**********************************************************************************
;******************************* IntTx ***************************************
; IntTx Atiende la interrupcion que se produce cuando el TXREG envia su
; dato a al registro TSR, por lo aqui se copia el nuevo valor a
; transmitir a TXREG, esto mientras ContTx > 0.
;**********************************************************************************
IntTx
decfsz ContTx,F,.0 ;ContTx --, ContTx == 0?
bra IntTxP0 ;No => vamos a cargar otro caracter
bra IntTxP1 ;Si => vamos a terminar la transmision
IntTxP0
movf POSTINC1,W ;Cargamos el caracter a W e incrementamos FSR1
movwf TXREG ;Cargamos TXREG
bra $+2 ;Esperamos a que TXIF se ponga en cero
bra IntTx_X ;vamos a salir de la IntTx
IntTxP1
bsf TxOK ;Indicamos que la transmision termino
bcf PIE1,TXIE ;Deshabilitamos esta interrupcion
bra IntTx_X ;vamos a salir de la IntTx
IntTx_X
bra SalirInt ;Vamos a salir de las interrupciones
;**********************************************************************************
SalirInt
movff BSR_TEMP,BSR ;recupera el registro BSR
movff WREG_TEMP,WREG ;recupera el registro de trabajo
movff STATUS_TEMP,STATUS ;recupera el registro STATUS
retfie
;******************************************************************************
; Rutina de interrupcion de alta prioridad
; El codigo para la rutina de interrupcion de alta prioridad es colocado aqui para
; evitar conflictos con el vector de interrupciones de baja prioridad
HighInt:
; *** El codigo para las interrupciones de alta prioridad va aqui ***
retfie FAST
;******************************************************************************
; Comienzo del programa principal
; El codigo del programa principal es colocado aqui
Main:
; *** EL codigo principal va aqui ***
;************************ Inicializacion de Puertos ***********************
movlw B'00001111'
movwf ADCON1,.0 ;Todos los pines como I/O digitales
;NO ES NECESARIO MODIFICAR LOS REGISTROS
;TRIS (estan todos en 1)
;************************ Configuracion del EUSART ***********************
movlw B'00000100' ;Configuramos para una transmision de 8 bit(bit 6)
movwf TXSTA,.0 ;modo asincrono (bit 4),para ajustar los baudios
;BRGH = 1 (bit 2)
movlw B'01001000' ;Habilitamos los 16 bits del generador de baudios
movwf BAUDCON,.0 ;BRG16 = 1 (bit 3)
movlw VelHI ;Cargamos los registros SPBRGH:SPBRG con los
movwf SPBRGH,.0 ;valores de la tabla 1 para la velocidad deseada
movlw VelLO
movwf SPBRG,.0
movlw B'10010000' ;Habilitamos el puerto seria (Bit 7), modo 8 bits
movwf RCSTA ;(bit 6), y habilitamos el receptor (Bit 4).
;*********************** Configuracion del TMR0 *************************
movlw B'10010110' ;TMR0 on, modo 16 bits, cambia con las
movwf T0CON,.0 ;instrucciones, asignamos preescaler de 128
movlw 0xDB ;De acuerdo a BlinkT0.asm calculamos los valores a
movwf TMR0H,.0 ;cargar para TMR0H y TMR0L, para el oscilador
movlw 0x61 ;de 48 MHz. y un tiempo de 100 ms
movwf TMR0L,.0 ;
movlw .20 ;
movwf ContT0,.0 ;ContT0 = 20 para controlar 2 segundos
;********************** Configuracion de interrupciones **********************
bsf PIE1,RCIE,.0 ;Habilitamos la interrupcion de recepcion
bsf INTCON,TMR0IE,.0 ;Habilitamos la interruocion de desborde del TMR0
bsf INTCON,PEIE,.0 ;Habilitamos las interrupciones para los perifericos
;************************ Inicializacion de variables ***************************
clrf Banderas,.0
clrf ContRx,.0
;******************************************************************************
clrf WREG
rcall EnvMsg ;Enviamos el primer mensaje
bsf INTCON,GIE ;Habilitamos las interrupciones
MainP0
movlw HIGH BufferRx
movwf FSR0H,.0
movlw LOW BufferRx
movwf FSR0L,.0 ;FSR0 apunta al inicio de BufferRx
clrf ContRx,.0 ;para reiniciar el conteo de bytes recibidos
clrf Banderas ;reiniciamos las banderas
movlw .20 ;reiniciamos el contador del time out
movwf ContT0,.0 ;ContT0 = 20 para controlar 2 segundos
movlw .1
rcall EnvMsg
MainP1
btfsc TimeOut ;Se produjo un time out?
bra MainP2 ;Si => vamos a atender el timeout
btfsc RxOK ;No, Se termino la recepcion?
bra MainP3 ;Si => vamos a atender la recepcion
bra MainP1 ;No => continuamos esperando
MainP2
bsf RxOK ;Para detener la recepcion
movlw .4
rcall EnvMsg ;Enviamos el mensaje de timeout
tstfsz ContRx,.0 ;ContRx == 0?;
bra MainP2_P0 ;No => se recibieron caracteres y vamos a procesarlos
bcf RxOK ;Si => no se recibieron caracteres,
bra MainP0 ;asi que volvemos a empezar
MainP2_P0
movlw .2
rcall EnvMsg ;Indicamos que procesamos la trama
rcall ProcTrama ;vamos a procesar la trama
bcf TimeOut ;reiniciamos las banderas
bra MainTx ;Vamos a ennviar la nueva trama
bra MainP0 ;Volvemos a empezar
MainP3
tstfsz ContRx,.0 ;ContRx == 0?;
bra MainP3_P0 ;No => se recibio un 0x0D (enter)
movlw .5 ;Si => se lleno el buffer, y enviamos
rcall EnvMsg ;el mensaje respectivo
MainP3_P0
movlw .2
rcall EnvMsg ;Indicamos que procesamos la trama
rcall ProcTrama ;vamos a procesar la trama
bra MainTx ;Vamos a Enviar la nueva trama
bra MainP0 ;Volvemos a empezar
MainTx
movlw .3
rcall EnvMsg ;Enviamos el mensaje para transmitir
bsf TXSTA,TXEN ;Habilitamos es transmisor
movf POSTINC1,W ;leemos el dato e incrementamos FSR1
movwf TXREG ;copiamos el dato a TXREG
bsf PIE1,TXIE,.0 ;Habilitamos la interrupcion de transmision
btfss TxOK ;La transmision termino?
bra $-2 ;No => esperamos
btfss TXSTA,TRMT ;Si => esperamos a que el ultimo caracter sea enviado
bra $-2 ;
bcf TXSTA,TXEN ;cuando se envia el ultimo caracter
;deshabilitamos es transmisor
bcf RxOK ;reniciamos las banderas
bcf TxOK ;
bra MainP0 ;;Volvemos a empezar
;******************************* ProcTrama ******************************
; ProcTrama Copia los datos del buffer de recepcion al buffer de transmision
; convirtiendo las minusculas en mayusculas.
;******************************************************************************
ProcTrama
movlw HIGH BufferRx
movwf FSR0H,.0
movlw LOW BufferRx
movwf FSR0L,.0 ;FSR0 apunta al inicio del BufferRx
movlw HIGH BufferTx
movwf FSR1H,.0
movlw LOW BufferTx
movwf FSR1L,.0 ;FSR1 apunta al inicio del BufferTx
clrf ContTx,.0 ;ContTx = 0
ProcTramaP0
movf POSTINC0,W ;Cargamos el caracter a W e incrementamos FSR0
movwf DatoTemp ;guardamos el dato para procesar
movlw 'a'
cpfslt DatoTemp ;DatoTemp <'a'
bra ProcTramaP0_0 ;No => es >= 'a' vamos a ver si es menor a z
bra ProcTramaP0_2 ;Si => no es minuscula y vamos a guardar DatoTemp
ProcTramaP0_0
movlw 'z'
cpfsgt DatoTemp ;DatoTemp > 'z'
bra ProcTramaP0_1 ;No => es <= 'z' vamos a convertirlo en mayuscula
bra ProcTramaP0_2 ;Si => no es minuscula y vamos a guardar DatoTemp
ProcTramaP0_1
movlw 0x20 ;le restamos 0x20 al dato para que sea mayuscula
subwf DatoTemp,F ;
ProcTramaP0_2
movf DatoTemp,W ;
movwf POSTINC1 ;Guardamos el dato e incrementamos FSR1
incf ContTx,F,.0 ;ContTx ++
movf ContRx,W,.0
cpfseq ContTx ;ContTx == ContRx ?
bra ProcTramaP0 ;No => seguimos copiando
movlw HIGH BufferTx ;Si => volvemos a apuntar FSR1 a BufferTx, para
movwf FSR1H,.0 ;salir
movlw LOW BufferTx
movwf FSR1L,.0
return
;******************************************************************************
;*********************************** EnvMsg ********************************
; EnvMsg Recibe en WREG el numero de mensaje que se quiere enviar, luego
; realiza un "computed goto", para ir a la rutina que atiende el
; numero de mensaje recibido en WREG.
;******************************************************************************
EnvMsg
rlcf WREG,.0,.0 ;WREG = WREG*2, solo se usan posiciones pares
movwf TablaOffs,.0 ;guardamos el valor de W en TablaOffs
movlw UPPER EnvMsgP0 ;Tomamos la Parte mas alta de EnvMsgP0
movwf PCLATU,.0 ;y actualizamos PCLATU
movlw HIGH EnvMsgP0 ;Tomamos la Parte alta de EnvMsgP0
movwf PCLATH,.0 ;y actualizamos PCLATh
movlw LOW EnvMsgP0 ;Tomamos la Parte baja de EnvMsgP0
addwf TablaOffs,W,.0 ;y realizamos el calculo para el salto
btfsc STATUS,C ;el salto es mayor de 256?
incf PCLATH,F,.0 ;Si => incrementamos PCLATH
movf TablaOffs,W,.0 ;leemos el valor a saltar
addwf PCL,F ;cuando se suma TablaOffs a PCL se realiza el salto
EnvMsgP0
bra EnvMsg_0 ;Vamos a atender el mensaje respectivo
bra EnvMsg_1
bra EnvMsg_2
bra EnvMsg_3
bra EnvMsg_4
bra EnvMsg_5
bra EnvMsg_6
EnvMsg_0
movlw UPPER Msg_0 ;tomamos la parte mas alta del mensage que enviaremos
movwf TBLPTRU,.0 ;y la actualizamos TBLPTRU
movlw HIGH Msg_0 ;tomamos la parte alta del mensage que enviaremos
movwf TBLPTRH,.0 ;y la actualizamos TBLPTRH
movlw LOW Msg_0 ;tomamos la parte baja del mensage que enviaremos
movwf TBLPTRL,.0 ;y la actualizamos TBLPTRL, Aqui tenemos a TBLPTR
;apuntado al inicio del mensaje
rcall EnviarMsg ;llamamos a enviar el mensaje
return
EnvMsg_1
movlw UPPER Msg_1 ;tomamos la parte mas alta del mensage que enviaremos
movwf TBLPTRU,.0 ;y la actualizamos TBLPTRU
movlw HIGH Msg_1 ;tomamos la parte alta del mensage que enviaremos
movwf TBLPTRH,.0 ;y la actualizamos TBLPTRH
movlw LOW Msg_1 ;tomamos la parte baja del mensage que enviaremos
movwf TBLPTRL,.0 ;y la actualizamos TBLPTRL, Aqui tenemos a TBLPTR
;apuntado al inicio del mensaje
rcall EnviarMsg ;llamamos a enviar el mensaje
return
EnvMsg_2
movlw UPPER Msg_2 ;tomamos la parte mas alta del mensage que enviaremos
movwf TBLPTRU,.0 ;y la actualizamos TBLPTRU
movlw HIGH Msg_2 ;tomamos la parte alta del mensage que enviaremos
movwf TBLPTRH,.0 ;y la actualizamos TBLPTRH
movlw LOW Msg_2 ;tomamos la parte baja del mensage que enviaremos
movwf TBLPTRL,.0 ;y la actualizamos TBLPTRL, Aqui tenemos a TBLPTR
;apuntado al inicio del mensaje
rcall EnviarMsg ;llamamos a enviar el mensaje
return
EnvMsg_3
movlw UPPER Msg_3 ;tomamos la parte mas alta del mensage que enviaremos
movwf TBLPTRU,.0 ;y la actualizamos TBLPTRU
movlw HIGH Msg_3 ;tomamos la parte alta del mensage que enviaremos
movwf TBLPTRH,.0 ;y la actualizamos TBLPTRH
movlw LOW Msg_3 ;tomamos la parte baja del mensage que enviaremos
movwf TBLPTRL,.0 ;y la actualizamos TBLPTRL, Aqui tenemos a TBLPTR
;apuntado al inicio del mensaje
rcall EnviarMsg ;llamamos a enviar el mensaje
return
EnvMsg_4
movlw UPPER Msg_4 ;tomamos la parte mas alta del mensage que enviaremos
movwf TBLPTRU,.0 ;y la actualizamos TBLPTRU
movlw HIGH Msg_4 ;tomamos la parte alta del mensage que enviaremos
movwf TBLPTRH,.0 ;y la actualizamos TBLPTRH
movlw LOW Msg_4 ;tomamos la parte baja del mensage que enviaremos
movwf TBLPTRL,.0 ;y la actualizamos TBLPTRL, Aqui tenemos a TBLPTR
;apuntado al inicio del mensaje
rcall EnviarMsg ;llamamos a enviar el mensaje
return
EnvMsg_5
movlw UPPER Msg_5 ;tomamos la parte mas alta del mensage que enviaremos
movwf TBLPTRU,.0 ;y la actualizamos TBLPTRU
movlw HIGH Msg_5 ;tomamos la parte alta del mensage que enviaremos
movwf TBLPTRH,.0 ;y la actualizamos TBLPTRH
movlw LOW Msg_5 ;tomamos la parte baja del mensage que enviaremos
movwf TBLPTRL,.0 ;y la actualizamos TBLPTRL, Aqui tenemos a TBLPTR
;apuntado al inicio del mensaje
rcall EnviarMsg ;llamamos a enviar el mensaje
return
EnvMsg_6
movlw UPPER Msg_6 ;tomamos la parte mas alta del mensage que enviaremos
movwf TBLPTRU,.0 ;y la actualizamos TBLPTRU
movlw HIGH Msg_6 ;tomamos la parte alta del mensage que enviaremos
movwf TBLPTRH,.0 ;y la actualizamos TBLPTRH
movlw LOW Msg_6 ;tomamos la parte baja del mensage que enviaremos
movwf TBLPTRL,.0 ;y la actualizamos TBLPTRL, Aqui tenemos a TBLPTR
;apuntado al inicio del mensaje
rcall EnviarMsg ;llamamos a enviar el mensaje
return
;******************************************************************************
;********************************* EnviarMsg ******************************
; EnviarMsg recibe como dato el registro TBLPTR apuntando al mensaje que
; quiere ser enviado y va recorriendo el mensaje enviando
; caracter por caracter hasta que se encuentre con el caracter 0x00
;******************************************************************************
EnviarMsg
tblrd *+ ;Leemos el valor de la tabla e incrementamos
;el puntero
tstfsz TABLAT,.0 ;El valor leido es 0x000?
bra EnviarMsgP0 ;No => vamos a enviar el caracter
return ;Si => retornamos
EnviarMsgP0
bsf TXSTA,TXEN ;Habilitamos el transmisor
movff TABLAT,TXREG ;Movemos el caracter a TXREG
bra $+2 ;espera a que el dato vaya al registro TSR
btfss TXSTA,TRMT ;EL caracter fue enviado?
bra $-2 ;No => esperamos
bcf TXSTA,TXEN ;Si => apagamos el transmisor
bra EnviarMsg ;Volvemos a leer el otro caracter
;******************************************************************************
;******************************************************************************
ORG 0x800
Msg_0
DB '\n','\r'
DB 'P','r','o','g','r','a','m','a',' ','e','j','e','m','p','l','o'
DB ' ','p','a','r','a',' ','e','l',' ','u','s','o',' ','d','e','l'
DB ' ','E','U','S','A','R','T','\n','\r',0x00
Msg_1
DB '\n','\r'
DB 'I','n','t','r','o','d','u','z','c','a',' ','l','a',' ','c','a'
DB 'd','e','n','a','.','.','.','.','\n','\r',0x00
Msg_2
DB '\n','\r'
DB 'P','r','o','c','e','s','a','n','d','o','.','.','.','\n','\r',0x00
Msg_3
DB 'L','a',' ','n','u','e','v','a',' ','c','a','d','e','n','a',' '
DB 'e','s',':','\n','\r',0x00
Msg_4
DB '\n','\r'
DB 'T','i','m','e',' ','o','u','t','\n','\r',0x00
Msg_5
DB '\n','\r'
DB 'B','u','f','f','e','r',' ','d','e',' ','r','e','c','e','p','c'
DB 'i','o','n',' ','l','l','e','n','o','\n','\r',0x00
Msg_6
DB '\n','\r'
DB 'E','r','r','o','r','\n','\r',0x00
END ;Directiva fin del programa