Define CONF_WORD = 0x3f42

Define CLOCK_FREQUENCY = 20  'se seleciona 4 Mhz de velocidad de reloj
'**************************************************************************************************
'DESCRIPCION: Primero: Uso del Timer1 para ser usado en reeplazo del WAITMS
'la variable pause es cargada con el tiempo que se desea pausar el programa en mseg
'Segundo: se a implementado un bufer para el puerto serie(usart_bufer)en el cual se van cargando los
'datos que van entrando por el puerto usart(fisico) y una variable, tambien tipo array(usart_imagen)
'la cual se encarga de indicar si en usart_bufer tiene o no datos en cada una de sus posiciones(31)
'FECHA/AUTOR: Eduardo Ipanaque, Mayo 25 del 2010
'version 1.0
'**************************************************************************************************
'--------------------------------PUERTOS DEL LCD---------------------------------------------------
'Defino puerto del lcd para ser usado en el prototipo de comunicacion de rf(RB6 y 7 a 6 y 7 de RA)
Define LCD_BITS = 4  'indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA  'el bus de datos sera el puerto A
Define LCD_DBIT = 0  'el bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB  'el bit de control RS sera del puerto B
Define LCD_RSBIT = 6  'se usara el RB7 como RS
Define LCD_EREG = PORTB  'el bit de control E sera del puerto B
Define LCD_EBIT = 7  'se usara el RB6 como E
Define LCD_COMMANDUS = 2000  'Tiempo de espera despues de ejecutar un comand del lcd en uSeg.
Define LCD_DATAUS = 50  'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 5  'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'------------------------------ Variables del Timer -------------------------------------------------
Dim pause As Word  'contiene el valor para simular el comando waitms
Dim aux_pause As Word  'variable auxiliar del pause que lleva la cuenta de los ms
Dim timer_1ms As Byte  'base de tiempos que se incrementa cada 1 mseg, timer del PAUSE
Dim timer_100ms As Byte  'base de tiempo que se incrementa cada 100 mseg
Dim timer_base As Byte  'valor referencial para el timer_100ms
'------------------------------ Variables del puerto serie ------------------------------------------

Dim assi As Byte  'variable que contendra el valor de lectura del puerto serie
Dim n_usart As Byte  'numero de datos del usart
Dim usart As Byte
Dim aux_usart As Byte
Dim bufer As Byte  'estado = 0:no hay datos,estado = 1: hay datos por leer, estado = 2: bufer lleno borrar
Dim c_serial As Byte  'variable para borrar el bufer serie
Dim trash As Byte
Dim usart_bufer(31) As Byte  'variable tipo array que contendra los datos entrantes(bufer soft)
Dim usart_imagen(31) As Byte  'variable tipo array de control del bufer soft
'------------------------------------ Variables del Programa ----------------------------------------
Dim flash_led_verde As Bit
Dim led_verde As Bit
Dim n As Byte
Dim clave As Byte
Dim r_clave As Byte
'----------------------------- Asignación de valores de las variables -------------------------------
assi = 0
n_usart = 50
usart = 0
aux_usart = 0
bufer = 0
trash = 0
c_serial = 0
'_____________
pause = 0
aux_pause = 0
timer_1ms = 0  'contador de un milisegundo
timer_100ms = 0
timer_base = 0
'_____________
flash_led_verde = 1
led_verde = 0
n = 0
clave = "@"
r_clave = 0
'-------------- ASIGNACION DE I/O Y VALORES DE INICIO A LAS SALIDAS ---------------------------------
CCP1CON = 0x00  'modulo CCPP a off
CMCON = 0x07  'modulo comparador a off
VRCON = 0x00  'VRF a off
'_____________
TRISA = 0x00  'puerto A como salida
TRISB = 0x00  'puerto B como salida
TRISA.5 = 1  'RA5 como entrada(SW1)
TRISB.2 = 1  'entrada de la usart(RX)
RB0 = 0  'led verde a off
Symbol sw1 = RA5
'--------------------------INICIO DEL PUERTO SERIE,TIMER E INTERRUPCIONES---------------------------
Hseropen 1200  'velocidad del puerto serie
T1CON.TMR1CS = 0  'asigna el reloj nterno al timr1.Se incrementa con cada ciclo de instruccion
T1CON.T1CKPS0 = 0  'factor del preescaler del timer1,0
T1CON.T1CKPS1 = 0  'factor del preescaler del timer1,0     El factor del prescaler es 1:1
TMR1H = 0xec  'carga el byte alto del registro del trm1
TMR1L = 0x78  'carga el byte bajo del registro del tmr1     cuenta 5000 cilcos de instruccion(1ms)
T1CON.TMR1ON = 1  'habilita al timer1.Comienza a incrementarse
PIE1.TMR1IE = 1  'activa las interrupciones del timer1
PIE1.RCIE = 1  'activa las interrupciones de la usart en modo RX
INTCON.PEIE = 1  'Bit de habilitacion de las interrupciones de perifericos
Enable
'--------------------------- Programa principal -----------------------------------------------------
Lcdinit
pause = 1000
Gosub pause_ms
Hserout "prueva de RS 232 con PIC 16f648-A", CrLf, "by Meledu", CrLf, CrLf, "_____________________________________", CrLf, CrLf,
Lcdout "Prueva de RS 232"
Lcdcmdout LcdLine2Home
Lcdout "Con PIC 16f648A"
pause = 2000
Gosub pause_ms
Lcdcmdout LcdClear
Gosub clear_bufer
'____________________
main:
If RCSTA.OERR = 1 Then  'testea posible bloqueo del puerto fisico en modo Rx
Gosub clearbufer  'borra el bufer por soft del puerto serie de entrada
Endif
Gosub recibo_comando
Goto main
End                                               

'************* Subutinas del programa ***************************************
Return                                            
readserial:
'RUTINA DE LECTURA DEL BUFFER DEL PUERTO SERIE (ASSI)
''Gosub pause_ms_rx  'valor de entrada en mSeg de espera definido por w_posrx
assi = 0  'se borra el valor de assi, no se debe de utilizar cero como un valor de control
If bufer = 1 Then  'si bufer tiene datos
assi = usart_bufer(c_serial)  'se lee el valor del bufer y se asigna assi
usart_imagen(c_serial) = 0  'se marca como leida para que pueda ser llenada de nuevo
c_serial = c_serial + 1  'se incrementa el indice del bufer
If c_serial >= n_usart Then c_serial = 0  'se verifica si se llego al final del bufer(posicion 31)
If usart_imagen(c_serial) = 0 Then bufer = 0  'si no quedan mas datos en el bufer se marca como vacio
Endif
Return                                            

clearbufer:
For n = 0 To 1  'desbloquea el puerto serie fisico en caso de bloqueo por exceso de entrada de datos
T1CON.TMR1ON = 0  'bloquea timer1
PIE1.RCIE = 0  'deshabilita la interrupcion del modulo serie
RCSTA.CREN = 0  'protocolo de desbloqueo puerto serie
RCSTA.CREN = 1  'protocolo de desbloqueo puerto serie
RCSTA.OERR = 0  'protocolo de desbloqueo puerto serie
Next n
Gosub clearbufer  'borra el bufer por soft de los datos recibidos por el puerto serie
PIR1.TMR1IF = 0  'borra el flag de salto del tmr1
PIR1.RCIF = 0  'borra el flag de salto de la usart
PIE1.RCIE = 1  'activa la interrupcion de la USART en modo rx
T1CON.TMR1ON = 1  'habilitacion del TMR1
Return                                            

clear_bufer:  'inicializa el bufer imagen y borra error del puerto fisico en modo Rx
'_________________________Borra el error del puerto serie
RCSTA.OERR = 0
RCSTA.CREN = 0
RCSTA.CREN = 1
'_________________________Borra e inicializa el bufer imagen del puerto serie
c_serial = 0
While c_serial <= n_usart  'se ejecuta tantas veces como variables tiene el bufer(31 posiciones = 31 veces)
usart_imagen(c_serial) = 0  'borra el indicador de variable del bufer con datosfer
c_serial = c_serial + 1
Wend
c_serial = 0  'variables de control del bufer
usart = 0
bufer = 0
assi = 0
Return                                            
pause_ms:  'rutina de espera, rutina que reemplaza al WAITMS ,pause establece el tiempo que se va a esperar
aux_pause = 0  'variable auxiliar que lleva la cuenta de los ms
timer_1ms = 0
While aux_pause <= pause  'pause determina el tienmpo maximo a contar,en mseg
aux_pause = aux_pause + 1
If timer_1ms > 0 Then timer_1ms = 0  'al borrar el contador se activa y cuenta 1 mseg
While timer_1ms < 1
Wend
Wend
Return                                            

'* * * * * * * * * * * * * * * * Subrrutinas Especiales * * * * * * * * * * * * * * * * * * * * * *
On Interrupt  'Comienzan las rutinas de las interrupciones, desactiva las interrupciones
Save System  'Guarda los valores del sistema

'-------------------------------------- bases de tiempos y flash diodos---------------------------
If PIR1.TMR1IF = 1 Then  'comprueba que es esta la interrupción activa
timer_base = timer_base + 1
If timer_1ms < 1 Then timer_1ms = timer_1ms + 1  'contador para el control de 1 mseg
If timer_base >= 100 Then
timer_100ms = timer_100ms + 1
timer_base = 0  'reset al timer
Endif
If timer_100ms = 5 Then  ''cuenta 500 milisegundos
If flash_led_verde = 1 Then  ''verifica si el flash del led verde esta habilitado
If led_verde = 0 Then
RB0 = 1  ''activa el led verde
led_verde = 1  ''indica que el led verde esta activo
Else
RB0 = 0  ''apaga el led verde
led_verde = 0  ''indica que el led verde esta desactivado
Endif
Endif
timer_100ms = 0
Endif
Endif
'----------------------------- Bufer Puerto serie -----------------------------------------------------------
If PIR1.RCIF = 1 Then  'comprueba que es esta la interrupcion activa del modulo USAR
If usart < n_usart Then  'comprueba que el bufer de entrada no esta lleno(si aun no esta en la posicion 90)
If usart_imagen(usart) = 0 Then  'comprueba que la posicion del bufer esta vacia
aux_usart = usart  'retiene la posicion antigua del bufer
usart = usart + 1  'indica cual sera la siguiente posicion  del bufer
usart_imagen(aux_usart) = 1  'indica que hay dato en el bufer de entrada
bufer = 1  'indica que el bufer tine datos
Hserget usart_bufer(aux_usart)  'carga el dato en el bufer
Else
Hserget usart_bufer(n_usart)  'descarga la usart para que no se bloquee porque el bufer de entrada esta lleno
Endif
Else
If usart_imagen(0) = 0 Then  'comprueba que esta vacia la primera posicion del bufer
usart_imagen(0) = 1  'marca que hay dato en esa posicion del bufer
bufer = 1  'marca que el bufer tiene datos
usart = 1  'establece la proxima posicion del bufer
Hserget usart_bufer(0)  'lee la usart y guarda el dato en el bufer(posicion 0)
Else
Hserget usart_bufer(n_usart)  'descarga la usart porque el bufer esta lleno
Endif
Endif
Endif
'_________________________Borra el error del puerto serie en Rx
If RCSTA.OERR = 1 Then
RCSTA.OERR = 0
RCSTA.CREN = 0
RCSTA.CREN = 1
Endif

TMR1H = 0xec  'carga el registro del timer1, para que desborde cada 1mSeg.
TMR1L = 0x78
PIR1.TMR1IF = 0  'borra el flag de salto del tmr1
PIR1.RCIF = 0  'borra el bit de salto del Rx
Resume  'activa las interrupciones y retorna al programa


lcd_control:  'rutina que imprime los valores recibidos por el puerto serie en el display
'parte 1 de la rutina, sincroniza e imprime los caracteres recibidos por el puerto serie
''If bufer = 1 Then  'la rutina se ejecuta si hay datos en el bufer
''timer1_100ms = 0  'hay datos hace reset al timer1_100ms
''Gosub readserial  'salta a la rutina de lectura del bufer serie
''If assi = "@" Then  'caracter de sincronismo de la trama
''n = 0  'possicion del display
''Lcdcmdout LcdClear  'borra el display y posiciona el cursor superior izquierda
''Endif
''If assi > 31 And assi < 128 And assi <> "@" Then  'filtra los caracteres a imprimir(investigar: And assi <> "@")
''Lcdout assi  'escribe el caracter del bufer en el display
''Endif
''n = n + 1  'incrementa la posicion para escribir el siguiente caracter en le display
''If n = 16 Then  'detecta fin de la linea primera del LCD
''Lcdcmdout LcdLine2Home  'situa el cursor al principio de la siguiente linea
''Endif
''If n >= 32 Then  'detecta fin de la segunda linea del LCD
''n = 0  'inicializa la posicion del proximo caracter a imprimir en el display
''Lcdcmdout LcdHome  'a inicio de linea
''Endif
''Endif
''Return

hyper:
If bufer = 1 Then
Gosub readserial
If assi = "@" Then Hserout CrLf  'caracter de sincronismo de la trama
If assi > 31 And assi < 128 And assi <> "@" Then Hserout assi
Endif
Return                                            
'-------------------------------Lectura de la trama de datos recibida por el bufer serie------------------
recibo_comando:  'confecciona la trama
Gosub readserial  'lee un byte almacenado en el bufer del puerto serie
If assi = clave Then  'establece la cabecera y sincroniza la trama
r_clave = assi
Hserout "   OH YEAH  ", CrLf
Endif
''rd_grupo = assii
''Gosub readserial
''rd_n_placa = assii
''Gosub readserial
''rd_estado = assii
''Gosub readserial
''rd_checsum = assii
''checsum = rd_grupo + rd_n_placa + rd_estado 'calculo el checsum con los valores recibidos
''If rd_checsum = checsum Then 'actualizo los valores de las salidas si el checsum recibido es correcto
''If rd_estado >= 8 Then estado = 1 'se pasa a estado de espera
''If rd_n_placa = n_placa Then estado = rd_estado 'se establece el estado recibido
''If rd_n_placa = 16 Then estado = 0 'se pasa a estado cero
''timer4_100ms = 0 'se activa la base de tiempos que nos modificara el parpadeo
'del led para indicar que se recibio una trama correctamente
''Endif
''Endif
Return                                            
End                                               

