El codigo:
'********************************** PIC Entrenadora BASIC ***************************************
'NOMBRE: 16F88_Pic_EBasic_LCD_RS232_Menu_10
'VERSION: 1.0
'MICRO: PIC16F88
'Fecha/Autor: 4/07 By COS
'DESCRIPCION: Control de los led de la EBasic por medio de un menu en el Hyperterminal
'programar el hyperterminal del Windows:
'Bits por segundo: 4800
'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_RWREG = PORTA 'el bit de control RW sera del puerto A (si se suprime el compilador no protesta)
'Define LCD_RWBIT = 5 'se usara el RA5 como RW (si se suprime el compilador no protesta)
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 '50 'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'--------------------------------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
'--------------------------------------Declaracion DE VARIABLES-------------------------------------
'-------------------------------------Variables sub_rutinas del puerto serie---------------------
Dim assi 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
'------------------------------------Variables tipo array puerto serie----------------------------------
Dim usart_imagen(91) As Byte 'Componen el bufer IMAGEN para control del bufer USART
Dim usart_bufer(91) As Byte 'Componen el bufer de la USART de bajo nivel
'-----------------------------------------------ASIGNACIONES----------------------------------------
'-------------------------------------Asignacion de valores del TIMER1----------------------------
pause = 0 'genera una pausa en MSeg
timer_1ms = 0 'en mSeg
'-------------------------------------Asigna valores a las variables de la rutina del puerto serie--
usart = 0
aux_usart = 0
c_serial = 0
bufer = 0
n_usart = 90
assi = 0
n_aux = 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 = 1 'como entrada (RA4, adc)
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 4800 '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
'PIE1.TMR1IE = 1 'activa las interrupciones del timer1
'PIE1.RCIE = 1 'Activa la interrupcion de la USART en modo rx
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 = 0 '1000 'prepara una pausa de 1Seg
Gosub pause_ms 'espera el tiempo que indica pause
Lcdout "16F88_RS232_MENU" 'imprime en el LCD el literal
Lcdcmdout LcdLine2Home 'selecciona linea y cursor al principio
Lcdout "4800 Baud.--1.0" 'escribe la cadena de literales en el lcd
Hserout ff, CrLf, CrLf, "VER. 1.0 - TX/RX", CrLf, "TX -> MENU POR RS232", CrLf, "By COS", CrLf, CrLf 'envia presentacion al RS232
Gosub clear_bufer 'Borra el BUFFER IMAGEN y por lo tanto tambien al USART, OBLIGATORIO POR LO MENOS UNA VEZ
pause = 0 '3000 'prepara una pausa de 3Seg
Gosub pause_ms 'hace una pausa de tiempo indicado por pause
'Lcdcmdout LcdClear 'borra el display
'--------------------------------------Main Programa----------------------------------------------------
Gosub print_menu 'envia el menu principal al hyperterminal
main:
Gosub readserial 'lee un caracter del puerto serie, salto con retorno
If assi >= 0x30 And assi <= 0x31 Then 'filtro de caracteres, "0" y el "1"
Hserout bell 'señal sonora
Hserout assi 'envia al hyperterminal
pause = 0 '1000 'carga la base de tiempos
Gosub pause_ms 'espera el tiempo indicado por pause
If assi = "0" Then Gosub control_led_amarillo 'salta a la rutina de control del led amarillo
If assi = "1" Then Gosub control_led_verde 'salta a la rutina de control del led verde
Endif
Goto main
End
'--------------------------------------FIN DEL MAIN-------------------------------------------
'--------------------------------------Rutinas Programa-----------------------------------------------
print_menu:
Hserout ff 'Paguina en blanco
Hserout " Menu de Control de los Led de la Pic EBasic ", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "------------------------------------------------", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "0 - Para menu Led amarillo", CrLf 'implime la cadena literal y salta a la siguiente linea
Hserout "1 - Para menu Led verde", CrLf 'implime la cadena literal y salta siguiente linea
Hserout "------------------------------------------------", CrLf 'implime la cadena literal y salta siguiente linea
Hserout "->" 'cursor
Hserout bell 'señal sonora
Return
control_led_verde:
Hserout ff 'pagina en blanco
Hserout " Menu control del Led Verde ", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "---------------------------------", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "0 - Led verde a Off", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "1 - Led verde a On", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "2 - Para Salir", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "---------------------------------", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "->" 'cursor
assi = 0 'borra el ultimo caracter leido del bufer serie
While assi <> "2" 'controla el menu
Gosub readserial 'lee caracter del bufer serial (retorna en assi)
If assi >= 0x30 And assi <= 0x32 Then 'filtro de opciones o teclas
Hserout bell 'señal sonora
Hserout assi 'caracter leido del bufer serie
pause = 0 '1000 'prepara una pausa de 1Seg.
Gosub pause_ms 'pausa indicada por pause
Hserout bell 'señal sonora
Gosub retrocede_caracter 'salto a la rutina de borra caracter
If assi = "0" Then led_verde = 1 'led verde a off
If assi = "1" Then led_verde = 0 'led verde a on
If assi = "2" Then Gosub print_menu 'reimprime el menu principal
Endif
Wend
Return
control_led_amarillo:
Hserout ff 'pantalla en blanco
Hserout " Menu control del Led Amarillo ", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "------------------------------------", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "0 - Led Amarillo a Off", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "1 - Led Amarillo a On", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "2 - Para Salir", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "------------------------------------", CrLf 'implime la cadena literal y salta a una nueva linea
Hserout "->" 'cursor
assi = 0 'borra el ultimo caracter leido del bufer serie
While assi <> "2" 'controla el menu
Gosub readserial 'lee caracter del bufer serial (retorna en assi)
If assi >= 0x30 And assi <= 0x32 Then 'filtro de opciones o teclas
Hserout bell 'señal sonora
Hserout assi 'caracter leido del bufer serie
pause = 0 '1000 'prepara una pausa de 1Seg.
Gosub pause_ms 'pausa indicada por pause
Hserout bell 'señal sonora
Gosub retrocede_caracter 'salto a la rutina de borra caracter
If assi = "0" Then led_amarillo = 1 'led amarillo a off
If assi = "1" Then led_amarillo = 0 'led amarillo a on
If assi = "2" Then Gosub print_menu 'reimprime el menu principal
Endif
Wend
Return
retrocede_caracter: 'borra caracter
Hserout bksp, sp, bksp
Return
pause_ms: 'rutina de espera, rutina tipo Waitms, pause establese el tiempo total en mSeg
timer_1ms = 0 'al borrar el contador se activa y comienza la cuenta de mSeg
While timer_1ms < pause '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 (ASSI)
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
If usart_imagen(c_serial) = 0 Then bufer = 0 'si no quedan mas datos en el bufer se marca como vacio
Else
assi = 0
Endif
Return
clear_bufer: 'inicializa el bufer imagen y borra error del puerto fisico en modo Rx
'_________________________Borra e inicializa el bufer imagan del puerto serie
c_serial = 0
While c_serial <= n_usart 'se ejecuta tantas veces como variables tiene el bufer
usart_imagen(c_serial) = 0 'borra el indicador de variable del bufer con datos
c_serial = c_serial + 1
Wend
c_serial = 0 'variables de control del bufer
usart = 0
bufer = 0
assi = 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 < pause 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
End
PD. las rutinas de tiempo fueron suprimidas para el Simulador