Define CONF_WORD = 0x2f10
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8
'********************************** PIC Entrenadora BASIC ***************************************
'NOMBRE: 16F88_Pic_EBasic_Modulos_RF_Tx_11
'VERSION: 1.1
'MICRO: PIC16F88
'Fecha/Autor: 5/08 By COS
'DESCRIPCION: Se recibe por el teclado del pc mediante el hyperterminal caracteres que son
'reenviados al aire mediante un modulo de rf a 2400 baudios.
'programar el hyperterminal del Windows:
'Bits por segundo: 1200
'Bits de datos: 8
'Paridad: Ninguno
'Control de flujo: Ninguno
'LCD a 4 bit, sin bit de RW
'************************************************************************************************
'-------------------------------------PUERTOS DEFINIDOS POR EL SISTEMA----------------------------
'-------------------------------------Puertos del LCD---------------------------------------------
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 = 7 'se usara el RB7 como RS
Define LCD_EREG = PORTB 'el bit de control E sera del puerto B
Define LCD_EBIT = 6 '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 = 50 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'-----------------------------Define la forma de trabajo de la funcion SEROUT------------------
Define SEROUT_DELAYUS = 0 'no hay delay entre caracter y caracter enviado al puerto serie
'--------------------------------Reasignacion de nombres---------------------------------------
Symbol led_amarillo = PORTA.7 'led amarillo
Symbol led_verde = PORTB.0 'led verde
'--------------------------------Definicion de caracteres de control del Hyperterminal--------
CONST ff
= 0x0c
'FF, Avance de pagina CONST bell
= 0x07
'BELL, Señal sonora CONST sp
= 0x20
'SP, Espacio CONST bksp
= 0x08
'BKSP, Retroceso CONST cr
= 0x0d
'retorno de carro '--------------------------------------Declaracion DE VARIABLES-------------------------------------
'-------------------------------------Variables globales-------------------------
'-------------------------------------Variables rutinas del bufer puerto serie----------------------
DIM ascii
AS Byte
'Contiene el valor de lectura del puerto serie DIM n_usart
AS Byte
'Numero de datos del USART y del bufer IMAGEN de control DIM usart
AS Byte
'Variable indice que apunta al ultimo dato adquirido por la USART DIM aux_usart
AS Byte
'Auxiliar de la variable indice usart del USART DIM c_serial
AS Byte
'Como USART pero para la lectura de control del bufer IMAGEN DIM bufer
AS Byte
'Indica si hay datos por leer en el bufer USART DIM n_aux
AS Byte
'contador para borrar el bufer_soft '************************************variables de los timer****************************************
DIM pause
AS Word
'contiene el valor para simular el comando Waitms DIM timer_1ms
AS Word
'base de tiempos se incrementa cada 1mSeg, timer del PAUSE DIM timer_1ms_tiempo
AS Word
'seleciona el tiempo de la base de tiempos timer_1 '------------------------------------Variables tipo array bufer puerto serie----------------------------------
DIM usart_imagen
(80) AS Byte
'Componen el bufer IMAGEN para control del bufer USAR DIM usart_bufer
(80) AS Byte
'Componen el bufer de la USAR de bajo nivel '-----------------------------------------------ASIGNACIONES----------------------------------------
'-------------------------------------Asignacion de valores del TIMER1----------------------------
pause = 0 'genera una pausa en MSeg
timer_1ms = 0 'en mSeg
timer_1ms_tiempo = 0
'-------------------------------------Asigna valores a las variables de la rutina del puerto serie--
usart = 0
aux_usart = 0
c_serial = 0
bufer = 0
n_usart = 80
ascii = 0
n_aux = 0
'-----------------------------------Asiga valores a las variables globales--
lcd_control = 0
'**************************************DEFINICION DE PUERTOS*************************************
'----------------------ASIGNACION DE I/O y valores de inicio de las salidas---------------------
ANSEL = 0x00 'los pin I/O digitales
CMCON = 0x07 'comparador a off
OSCCON = 0x7e 'set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0x00 'Puerto A como salidas
TRISB = 0x00 'puerto B como salidas
TRISA.4 = 0 'como salida (RA4, RS232 POR SOFT)
TRISA.6 = 1 'como entrada (RA6, tecla S1)
TRISA.5 = 1 'como entrada (RA5, tecla S2)
'TRISB.5 = 0 'RB5(Tx, RS232)
TRISB.2 = 1 'RB2 (Rx, RS232)
PORTB.3 = 1 'luz lcd a on (RB3)
PORTA.7 = 1 'led amarillo a off
PORTB.0 = 1 'led verde a off
'------------------------------------INICIO DEL PUERTO SERIE, TIMER E INTERRUPCIONES------------------
Hseropen 1200 'Velocidad del puerto serie e inicializa los comandos de bajo nivel que controlan la USART
GOSUB clear_bufer 'Borra el BUFFER IMAGEN y por lo tanto tambien al USART, OBLIGATORIO POR LO MENOS UNA VEZ
T1CON.TMR1CS = 0 'asigna el reloj interno al timer1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'factor del preescales del timer1, 0
T1CON.T1CKPS1 = 0 'factor del preescales del timer1, 0
TMR1H = 0xf8 'carga el registro del contador para que desborde cada 1mSeg, byte alto
TMR1L = 0x2f 'carga el registro del contador para que desborde cada 1mSeg, byte bajo
T1CON.TMR1ON = 1 'habilitacion del TMR1, comienza a incrementarce
INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos
Enable 'INTCON.GIE habilita todas las interrupciones globales
'--------------------------------------Inicio Programa--------------------------------------------------
Lcdinit 'inicializa el LCD sin cursor
PIE1.TMR1IE = 1 'activa las interrupciones del timer1
PIE1.RCIE = 1 'Activa la interrupcion de la USART en modo rx
pause = 1000 'prepara una pausa de 1Seg
GOSUB pause_ms 'espera el tiempo que indica pause
Lcdout "RS232_Tx RF 1.1" 'imprime en el LCD el literal
Lcdcmdout LcdLine2Home 'selecciona linea y cursor al principio
Lcdout "Rx1200B-Tx2400B" 'escribe la cadena de literales en el lcd
Hserout ff, CrLf, CrLf, "VER. 1.1 - RF (TX)", CrLf, "TX -> RS232 y RF", CrLf, "By COS", CrLf, CrLf 'envia presentacion al RS232
GOSUB clear_bufer 'Borra el bufer imagen y por lo tanto tambien al USART, OBLIGATORIO POR LO MENOS UNA VEZ
pause = 3000 'prepara una pausa de 3Seg
GOSUB pause_ms 'hace una pausa de tiempo indicado por pause
Lcdcmdout LcdLine1Home
'--------------------------------------Main Programa----------------------------------------------------
main:
IF bufer > 0 THEN 'si hay datos en el bufer serie
GOSUB d_read 'salta a la rutina que procesa el dato recibido por el puerto serie
Endif
GOTO main
'--------------------------------------FIN DEL MAIN-------------------------------------------
'--------------------------------------Sub_Rutinas Programa-----------------------------------------------
d_read: '___________________rutina de lectura del teclado del pc, a travez del hyperterminal
GOSUB readserial 'lee un dato del bufer serie
Hserout ascii 'Envia el dato recibido al hyperterminal, Tx del modulo UART
Lcdout ascii 'Imprime el byte leido en el LCD
IF lcd_control = 15 THEN Lcdcmdout LcdLine2Home 'detecta que la linea 1 esta llena y pasa a la 2 del LCD
IF lcd_control = 31 THEN Lcdcmdout LcdLine1Home 'Detecta que la linea 2 esta llena y pasa a la 1 del LCD
lcd_control = lcd_control + 1 'contador que indica la proxima posicion del LDC a escribir
IF lcd_control > 31 THEN lcd_control = 0 'Cuando el LCD esta lleno hace reset al cntador
checsum = 255 + ascii 'calcuala el checsum a insertar en la trama de datos, suma de seguridad
PIE1.TMR1IE = 0 'desactiva las interrupciones del timer1
PIE1.RCIE = 0 'desActiva la interrupcion de la USART en modo rx
Serout RA4, 2400, 0, 255, ascii, checsum.LB, checsum.HB 'envia la trama a la radio de tx
PIE1.RCIE = 1 'Activa la interrupcion de la USART en modo rx
PIE1.TMR1IE = 1 'activa las interrupciones del timer1
RETURN
pause_ms: 'rutina de espera, rutina tipo Waitms, pause establese el tiempo total en mSeg
timer_1ms_tiempo = pause 'nuevo valor para contar, waitms
timer_1ms = 0 'al borrar el contador se activa y comienza la cuenta de mSeg
WHILE timer_1ms < timer_1ms_tiempo 'tiempo en mSeg maximos a contar
WEND
RETURN
'------------------------------ rutinas para el control del bufer del puerto serie-------------
readserial:
'RUTINA DE LECTURA DEL BUFFER DEL PUERTO SERIE (ascii)
IF bufer = 1 THEN 'si bufer tiene datos
ascii = usart_bufer(c_serial) 'se lee el valor del bufer y se asigna ascii
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
IF usart_imagen(c_serial) = 0 THEN bufer = 0 'si no quedan mas datos en el bufer se marca como vacio
ELSE
ascii = 0 'si se hace una lectura del bufer estando vacio devuelve 0
Endif
RETURN
clear_bufer: 'inicializa el bufer imagen y borra error del puerto fisico en modo Rx
'_________________________Borra e inicializa el bufer imagen del puerto serie
c_serial = 0 'nos indica la posicion a borrar del bufer
WHILE c_serial < n_usart 'se ejecuta tantas veces como variables tiene el bufer
usart_imagen(c_serial) = 0 'borra el indicador indice, informa que esa posicion del bufer no tiene datos
c_serial = c_serial + 1 'contador que nos indica la proxima posicion del bufer a borrar
WEND
c_serial = 0 '___variables de control del bufer
usart = 0
bufer = 0
ascii = 0 '______
'__________________________Borra el error del puerto serie en Rx
RCSTA.OERR = 0
RCSTA.CREN = 0
RCSTA.CREN = 1
RETURN
'--------------------------------------SIBRUTINAS ESPECIALES---------------------------------------------
ON Interrupt
'desactiva las interrupciones Save
SYSTEM 'Guarda los valores del sistema'*****************************base de tiempos********************************************
IF PIR1.TMR1IF = 1 THEN 'comprueba que la interrupcion la proboco el timer1
IF timer_1ms < timer_1ms_tiempo THEN timer_1ms = timer_1ms + 1 'contador para control del timer_1ms
TMR1H = 0xf8 'recarga el contador del timer1 para que desborde pasado 1mSeg, byte alto
TMR1L = 0x2f 'recarga el contador del timer1 para que desborde pasado 1mSeg, byte bajo
PIR1.TMR1IF = 0 'borra el bit de salto del timer1
Endif
'*****************************BUFFER 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
IF usart_imagen(usart) = 0 THEN 'comprueba que la posicion esta vacia
aux_usart = usart 'retiene la posicion antigua del bufer
usart = usart + 1 'indica cual sera la posicion siguiente 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
ELSE
Hserget usart_bufer(n_usart) 'descarga la usart porque el bufer esta lleno
Endif
Endif
PIR1.RCIF = 0 'borra el bit de salto del Rx
Endif
'_________________________Borra el error del puerto serie en Rx
IF RCSTA.OERR = 1 THEN
RCSTA.OERR = 0
RCSTA.CREN = 0
RCSTA.CREN = 1
Endif
RESUME 'activa las interrupciones y retorna al curso normal del programa antes del salto