Autor Tema: PIC BASIC del PIC Simulator IDE Oshonsoft (Índice en página 1)  (Leído 859502 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #180 en: 01 de Mayo de 2007, 17:50:58 »
Programa anterior para las pruebas con el RB0/INT, descargado a la EBasic y funcionado OK.
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #181 en: 03 de Mayo de 2007, 11:47:33 »
Dejo una version mucho mas elaborada de menu por medio del hyperterminal.
En este caso es una rutina de reconocimiento del numero entrado por el teclado del pc, a traves del hyperterminal.
La rutina permite corregir el numero en la pantalla del hyperterminal

El menu no queda muy lucido por causa de que el simulador no reconoce bien todos
Los caracteres de control.. pero funciona.

En este caso el menu pide una clave “1234”, que indicara en lcd y en el hyperterminal si es correcta o no.

Código: [Seleccionar]
'********************************** PIC Entrenadora BASIC ***************************************
'NOMBRE: 16F88_Pic_EBasic_LCD_RS232_Menu_11
'VERSION: 1.1
'MICRO: PIC16F88
'Fecha/Autor: 4/07, 5/07 By COS, PSI v7.41
'DESCRIPCION: Control de clave de acceso
'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
'VERSION: 1.1
'Implementacion de una rutina que lee digitos numericos del teclado del ordenador y los pasa
'a un unico numero, se muestra en el lcd y lo compara con otro de 4 digitos compilado en el
'programa (1234), indicando tanto por el hyperterminal como por el lcd si es correcto, clave.
'Implementacion de poder corregir los digitos tecleados en el PC
'Lectura del puerto serie mediante un buffer en anillo
'************************************************************************************************
Define CONFIG = 0x2f50  'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc  'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8  'Clock en Mhz
'Define SIMULATION_WAITMS_VALUE = 1  'Activar para simulación
'-------------------------------------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
Const cr = 0x0d  'CR, retorno de carro
'**************************************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------------------
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 incrementarse
'PIE1.TMR1IE = 1  'activa las interrupciones del timer1
'PIE1.RCIE = 1  'Activa la interrupción de la USART en modo rx
INTCON.PEIE = 1  'bit de habilitación de interrupciones de periféricos
'-------------------------------------Variables rutinas del buffer puerto serie----------------------
Dim assi As Byte  'Contiene el valor de lectura del puerto serie
Dim buffer As Byte  'Indica si hay datos por leer en el buffer USART
Dim n_usart As Byte  'Numero de datos del USART y del buffer 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 buffer IMAGEN
Dim n_aux As Byte  'contador para borrar el buffer_soft
Dim usart_imagen(10) As Byte  '91 'Componen el buffer IMAGEN para control del buffer USAR
Dim usart_buffer(10) As Byte  '91'Componen el buffer de la USAR de bajo nivel
'-------------------------------------Asigna valores a las variables de la rutina del puerto serie--
usart = 0
aux_usart = 0
c_serial = 0
buffer = 0
n_usart = 9  '90
assi = 0
n_aux = 0
'************************************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
'-------------------------------------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 lectura teclado--
Dim d_teclas As Byte  'Numero de digitos + 1 de la clave
Dim _digclave(4) As Byte  'Clave
_digclave(0) = "1"
_digclave(1) = "2"
_digclave(2) = "3"
_digclave(3) = "4"
Dim aux_digclave(5) As Byte  'Clave entrada por el teclado
d_teclas = 3  'numero de digitos +1, max. a introducir por el teclado del PC
'-----------------------------------------------
Lcdinit  'inicializa el LCD sin cursor
Hseropen 4800  'Velocidad del puerto serie e inicializa los comandos de bajo nivel que controlan la USART
Gosub clear_buffer  'Borra el BUFFER IMAGEN y por lo tanto tambien al USART, OBLIGATORIO POR LO MENOS UNA VEZ
PIE1.TMR1IE = 1  'activa las interrupciones del timer1
PIE1.RCIE = 1  'Activa la interrupcion de la USART en modo rx
Enable  'INTCON.GIE habilita todas las interrupciones globales
pause = 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.1"  'escribe la cadena de literales en el lcd
Hserout ff, CrLf, CrLf, "VER. 1.1 - TX/RX", CrLf, "TX -> MENU POR RS232", CrLf, "By COS", CrLf, CrLf  'envía presentación al RS232
Gosub clear_buffer  'Borra el BUFFER IMAGEN y por lo tanto también 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
'--------------------------------------Main Programa----------------------------------------------------
main:
Gosub print_menu  'envia el menu principal al hyperterminal
Gosub d_read  'rutina de lectura del teclado del pc
Gosub verifica_clave  'verifica la clave y lo indica por el lcd
pause = 1000  'carga la base de tiempos
Gosub pause_ms  'espera el tiempo indicado por pause
Goto main
End                                               
'--------------------------------------Rutinas Programa-----------------------------------------------
d_read:  '___________________Rutina de lectura del teclado del pc, a través del hyperterminal
Dim d_aux As Byte
Dim d_control As Byte
aux_digclave(0) = "-"
aux_digclave(1) = "-"
aux_digclave(2) = "-"
aux_digclave(3) = "-"
d_control = 0  'valor inicial
d_aux = 0  'valor inicial
Gosub hserout_cursor  'salto con retorno escribe cursor en el hyperterminal
While d_control = 0  'lee el teclado del pc, hasta que se valida el numero, enter
If buffer > 0 Then  'controla que hay datos en el buffer serie
Gosub readserial  'lee un dato del buffer serie
Gosub hserout_bell  'señal sonora
Endif
If assi >= 0x30 And assi <= 0x39 And d_aux <= d_teclas Then  'filtro de teclas validas y numero de digitos max.
Gosub hserout_assi  'envia el valor de assi al hyperterminal, tecla numerica pulsada
aux_digclave(d_aux) = assi  'Asigna la tecla a la clave auxiliar
d_aux = d_aux + 1  'incrementa la siguiente posicion del digito a recibir
assi = 0  'se borra el digito recibido
Endif
If assi = bksp Then  '___________borra el ultimo caracter
If d_aux > 0 Then  'Si se introdujo algun digito
d_aux = d_aux - 1  'Selecciona el digito a borrar
aux_digclave(d_aux) = "-"  'Borra el digito
Gosub borra_caracter  'Retrocede y borra una posicion en el hyperterminal
Endif
assi = 0  'se borra el digito recibido
Endif  '________________________
If assi = cr Then  '_______detecta el retorno de carro, o fin de entrada de datos
Gosub hserout_crlf  'envia un avance de linea y principio de linea
assi = 0  'se borra el digito recibido por el puerto serie
Return
Endif  '_____________________
Wend
Return                                           
hserout_cursor:  'cursor en el hyperterminal
Hserout "->"
Return                                           
hserout_ff:  'Pagina en blanco
Hserout ff
Return                                           
hserout_crlf:  'salta una linea y principio de linea
Hserout CrLf
Return                                           
hserout_assi:  'envia el valor al puerto serie
Hserout assi
Return                                           
hserout_bell:  'señal sonora
Hserout bell
Return                                           
borra_caracter:  'borra caracter
Hserout bksp, sp, bksp
Return                                           
print_menu:
'Gosub hserout_ff  'Pagina en blanco
Hserout "-------------------------------", CrLf  'imprime la cadena literal y salta a una nueva linea
Hserout "   Entre la Clave, 4 Digitos  ", CrLf  'imprime la cadena literal y salta a una nueva linea
Hserout "-------------------------------", CrLf  'imprime la cadena literal y salta a una nueva linea
Gosub hserout_bell  'señal sonora
Return                                           
verifica_clave:  '___________________VERIFICA LA CLAVE Y SACA DATOS POR EL LCD Y PUERTO SERIE
Lcdcmdout LcdLine1Home
Lcdout "Numero: ", aux_digclave(0), aux_digclave(1), aux_digclave(2), aux_digclave(3), "       "  'escribe en el lcd y numero reconocido por la EBasic
Lcdcmdout LcdLine2Home  'principio de linea 2 del lcd
If aux_digclave(0) = _digclave(0) And aux_digclave(1) = _digclave(1) And aux_digclave(2) = _digclave(2) And aux_digclave(3) = _digclave(3) Then  'comprueba la clave
Lcdout "Clave Correcta  "  'manada datos al lcd
Hserout CrLf, CrLf, "Clave Correcta", CrLf, CrLf  'manda datos al puerto serie
Gosub hserout_bell  'manda datos la puerto serie, señal sonora
Gosub hserout_bell  'manda datos la puerto serie, señal sonora
pause = 200  'indica la duracion de la pausa
Gosub pause_ms  'hace una pausa
Gosub hserout_bell  'manda datos la puerto serie, señal sonora
Gosub pause_ms  'hace una pausa
Gosub hserout_bell  'manda datos la puerto serie, señal sonora
Else
Lcdout "Clave Incorrecta"  'manda datos al lcd
Hserout CrLf, CrLf, "Clave Incorrecta", CrLf, CrLf  'manda datos al puerto serie
Endif
Return                                           
pause_ms:  'rutina de espera, rutina tipo Waitms, pause establece el tiempo total en mSeg
pause = 0  'deshabilita la rutina pause 0, solo simulación
timer_1ms = 0  'al borrar el contador se activa y comienza la cuenta de mSeg
While timer_1ms < pause  'tiempo en mSeg máximos a contar
Wend
Return                                           
'------------------------------ rutinas para el control del buffer del puerto serie-------------
readserial:
'RUTINA DE LECTURA DEL BUFFER DEL PUERTO SERIE (ASSI)
If buffer = 1 Then  'si buffer tiene datos
assi = usart_buffer(c_serial)  'se lee el valor del buffer 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 buffer
If c_serial >= n_usart Then c_serial = 0  'se verifica si se llego al final del buffer
If usart_imagen(c_serial) = 0 Then buffer = 0  'si no quedan mas datos en el buffer se marca como vacio
Else
assi = 0
Endif
Return                                           
clear_buffer:  'inicializa el buffer imagen y borra error del puerto físico en modo Rx
'_________________________Borra e inicializa el buffer imagen del puerto serie
c_serial = 0
While c_serial <= n_usart  'se ejecuta tantas veces como variables tiene el buffer
usart_imagen(c_serial) = 0  'borra el indicador indice, informa que esa posicion del buffer tiene o no tiene datos
c_serial = c_serial + 1
Wend
c_serial = 0  'variables de control del buffer
usart = 0
buffer = 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 provoco 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 buffer 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 buffer
usart = usart + 1  'indica cual sera la posicion siguiente del buffer
usart_imagen(aux_usart) = 1  'indica que hay dato en el buffer de entrada
buffer = 1  'indica que el buffer tiene datos
Hserget usart_buffer(aux_usart)  'carga el dato en el buffer
Else
Hserget usart_buffer(n_usart)  'descarga la usart para que no se bloquee porque el buffer de entrada esta lleno
Endif
Else
If usart_imagen(0) = 0 Then  'comprueba que esta vacía la primera posicion del buffer
usart_imagen(0) = 1  'marca que hay dato en esa posicion del buffer
buffer = 1  'marca que el buffer tiene datos
usart = 1  'establece la próxima posición del buffer
Hserget usart_buffer(0)  'lee la usart y guarda el dato en el buffer
Else
Hserget usart_buffer(n_usart)  'descarga la usart porque el buffer 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

PD: Solo correccion en las explicaciones
« Última modificación: 12 de Junio de 2016, 21:12:44 por dogflu66 »
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #182 en: 03 de Mayo de 2007, 13:30:09 »
Dejo una imagen del simulador con los modulos implicados

« Última modificación: 05 de Mayo de 2007, 08:55:59 por dogflu66 »
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #183 en: 03 de Mayo de 2007, 13:37:56 »
PD: Para entrar digitos clicar en la opcion “Send String”
Y para indicar aceptación clicar en “Send Byte (hex)”, 0d (CR, retorno de carro), o 08 (BKSP, retroceso) para corregir digitos.
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #184 en: 04 de Mayo de 2007, 16:20:52 »
Aqui dejo otro ejemplo, en este caso utilizo el TIMER1 para medir en uSeg. el tiempo en el que se ejecutan las rutinas, comandos, funciones y etc.
Con tal que no tarde mas de 32 mSeg. en completarse la rutina a comprobar. Los valores que salen son exactamente iguales en el simulador que en la EBasic.
Los valores son mostrados tanto por el LCD como por el Hyperterminal, en este caso la declaracion que utilizo no usa la UART del pic, uso la simulacion de la UART por soft.

Estos son los tiempos de algunas que probe:
(solo hay que ir habilitando unas y deshabilitando otras o añadiendo otras nuevas en esta parte del programa)

'-------------------Rutina a medir en uSeg-----------------------------------
'WaitMs 15  'Tarda 15007 uS
Lcdcmdout LcdClear  'Tarda 2020uS
Lcdout "Hola TodoPic"  'Tarda 840uS
'aux = 100  '__________Tarda 4 uSeg
'If aux = 100 Then
'Endif  '______________
'----------------------------------------------------------------------------

« Última modificación: 17 de Junio de 2007, 07:29:19 por dogflu66 »
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #185 en: 04 de Mayo de 2007, 16:22:24 »
El programa:

Código: [Seleccionar]
'********************************** PIC Entrenadora BASIC ***************************************
'NOMBRE: 16F88_Pic_EBasic_LCD_Timer1_MidiendoTiempo_10
'VERSION: 1.0
'MICRO: PIC16F88
'Fecha/Autor: 5/07 By COS, PSI v7.41
'DESCRIPCION: Midiendo el tiempo que tardan ciertas rutinas en ejecutarse
'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
'valor por el display y por el hyperterminal
'************************************************************************************************
Define CONFIG = 0x2f50  'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc  'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8  'Clock en Mhz
'Define SIMULATION_WAITMS_VALUE = 1  'Activar para simulación
'-------------------------------------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., depende del lcd (este 500)
Define LCD_DATAUS = 50  'Tiempo de espera despues de enviar un dato al LCD en uSeg., depende de la respuesta del lcd
Define LCD_INITMS = 5  '50  'Tiempo de espera despues de inicializar el Display, solo se ejecuta una vez en mSeg.
'----------------------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
'------------------------------------PROGRAMACION TIMER1---------------------------------------
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 = 0x00  'carga el registro del contador para que desborde cada 32.76 mSeg, byte alto
'TMR1L = 0x00  'carga el registro del contador para que desborde cada 32.76 mSeg, byte bajo
T1CON.TMR1ON = 0  'parado el contador del TMR1
PIE1.TMR1IE = 0  'desactiva las interrupciones del timer1
'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
'-------------------------------Reasignacion de nombres---------------------------------------
Symbol led_amarillo = PORTA.7  'led amarillo
Symbol led_verde = PORTB.0  'led verde
'**********************DECLARACION DE VARIABLES****************************************
Dim timer1 As Long  'contendra el valor de los registros del timer1 y posterior valor a uSeg.
Dim aux As Byte
aux = 0
'WaitMs 1000  'prepara una pausa de 1Seg
Lcdout "16F88_LCD_TIMER1"  'imprime en el LCD el literal
Lcdcmdout LcdLine2Home  'selecciona linea y cursor al principio
Lcdout "MidiendoTiempo10"  'escribe la cadena de literales en el lcd
'WaitMs 3000  'prepara una pausa de 3Seg
'--------------------------------------Main Programa----------------------------------------------------
main:
TMR1H = 0x00  'borro el registro alto del timer1
TMR1L = 0x00  'borro el registro bajo del timer1
T1CON.TMR1ON = 1  'activa el contador del TMR1
'****************************************************************************
'-------------------Rutina a medir en uSeg-----------------------------------
'WaitMs 15  'Tarda 14998 uS
Lcdcmdout LcdClear  'Tarda 2024uS
'Lcdout "Hola TodoPic"  'Tarda 906uS
'aux = 100  '__________Tarda 3 uSeg
'If aux = 100 Then
'Endif  '______________
'----------------------------------------------------------------------------
'****************************************************************************
T1CON.TMR1ON = 0  'Para el contador del TMR1
timer1 = 0
timer1.HB = TMR1H  'asigna registro de mas peso
timer1.LB = TMR1L  'asigna registro de menos peso
'timer1_aux = timer1  'pasa de long a word
Lcdcmdout LcdClear  'borra el lcd y cursor linea 1
Lcdout "Timer1:", #timer1  'datos por el lcd
Serout PORTB.5, 4800, CrLf, "Timer1: ", #timer1, CrLf  'puerto serie Tx, por soft
timer1 = (timer1 * 5) / 10  'en microsegundos
'timer1_aux = timer1  'paso de long a word, la rutina del display no permite variables tipo Long
Lcdcmdout LcdLine2Home  'cursor al principio de la linea 2 del lcd
Lcdout "Tiemp.:", #timer1, "uS."  'datos por el lcd
Serout PORTB.5, 4800, CrLf, "Tiempo: ", #timer1, " uSeg.", CrLf  'puerto serie Tx, por soft
End

PD. Correccion, no defini bien la longitud de las variables, y fallaba el calculo de los uSeg. a partir de cierto valor elevado del registro del Timer1
« Última modificación: 12 de Junio de 2016, 21:42:02 por dogflu66 »
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #186 en: 04 de Mayo de 2007, 16:31:22 »
Los modulos del simulador implicados:

« Última modificación: 07 de Febrero de 2018, 21:16:39 por dogflu66 »
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #187 en: 20 de Mayo de 2007, 19:59:43 »
Aqui dejo una version mejorada del Reloj Calendario con Temperatura
Ahora tambien muestra los datos por el Hyperterminal

1ª parte:
-------------
Código: [Seleccionar]
'********************************** PIC Entrenadora BASIC (PicEBasic)******************************
'NOMBRE: 16F88_Pic_EBasic_LCD_RTC_ADC_11
'MICRO: PIC16F88
'FECHA/AUTOR: 04/07, 05/07 - By COS
'VERSION 1.1
'modificacion de la rutina "pause_ms"
'modificacion de rutina de teclas, porque se veian afectadas al crecer la longitud del programa main
'Se añade salida de la temperatura, hora y fecha por el puerto serie (Soft)
'Pendiente de grafica de temperatura por el hyperterminal
'VERSION 1.0
'DESCRIPCION: Muestra en el display la fecha, hora (24h)mediante el DS1307 y temperatura (LM35)
'S1 y S2 pulsadas al mismo tiempo, entramos en programacion del reloj
'Una vez en programacion con S1 seleccionamos el dato a cambiar, este queda en modo parpadeo
'Una vez en programacion con S2 incrementamos el dato seleccionado dentro de sus cotas
'S1, pulsado al principio salida del RTC a on, 1Hz, y S2 salida a off, led off
'Se muestra la temperatura en el LCD mediante un LM35, temperatura positiva y negativa
'***************************************************************************************************
'-------------------------------------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 nrol RS sera del puerto B
Define LCD_RSBIT = 7  'se usara el RB7 como RS
Define LCD_EREG = PORTB  'el bit de nrol E sera del puerto B
Define LCD_EBIT = 6  'se usara el RB6 como E
Define LCD_COMMANDUS = 500  '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.
'-------------------------------------------------------------------------------------------------------------
Define SEROUT_DELAYUS = 0  'no hay delay entre caracter y caracter enviado al puerto serie
'-----------------------------------asignacion de nombres-----------------------------------------------------
Symbol sda = PORTB.1  'asignamos nombre al pin que hara de SDA del puerto I2C
Symbol scl = PORTB.4  'asignamos nombre al pin que hara de SCL del puerto I2C
Symbol led_amarillo = PORTA.7  'led amarillo
Symbol led_verde = PORTB.0  'led verde
Symbol luz_lcd = PORTB.3  'retroiluminacion del lcd
Symbol s1 = RA6  'se asigna nombre a la tecla
Symbol s2 = RA5  'se asigna nombre a la tecla
'***********************************DEFINICION DE VARIABLES**************************************
'-----------------------------------variables de los timer---------------------------------------
Dim aux_pause As Word  'variable auxiiar el PAUSE
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_base As Byte  'tiempo referencia para los timer por soft del programa
Dim timer_base_tiempo As Byte  'contiene el valor del tiempo del timer_base
Dim timer1_ms As Word  'base de tiempos en ms
Dim timer2_ms As Word  'base de tiempos en ms
Dim timer3_ms As Word  'base de tiempos ms
Dim timer1_100ms As Byte  'base de tiempos msx100
Dim timer2_100ms As Byte  'base de tiempos msx100
Dim timer3_100ms As Byte  'base de tiempos msx100
Dim timer_1ms_tiempo As Word  'contiene el valor del tiempo de timer_1ms
Dim timer1_ms_tiempo As Word  'contiene el valor del tiempo del timer1_ms
Dim timer2_ms_tiempo As Word  'contiene el valor del tiempo del timer2_ms
Dim timer3_ms_tiempo As Word  'contiene el valor del tiempo del timer3_ms
Dim timer1_100ms_tiempo As Byte  'contiene el valor del tiempo del timer1_100ms
Dim timer2_100ms_tiempo As Byte  'contiene el valor del tiempo del timer2_100ms
Dim timer3_100ms_tiempo As Byte  'contiene el valor del tiempo del timer3_100ms
'--------------------------------------Variables Programa RTC----------------------------------------
Dim aux_4h As Byte  'contendra el nibble alto del dato leido por el I2C
Dim aux_4l As Byte  'contendra el nibble bajo del dato leido por el I2C
Dim i As Byte  'variable indice
Dim reg(7) As Byte  'contendra los valores finales de fecha y hora en el sistema decimal
Dim flash_1 As Bit  'controla el parpadeo de los digitos del lcd, activo a 1
Dim dato As Byte  'indica la direccion del RTC a cambiar de valor
Dim flag_1 As Bit  'activa la rutina de ajuste del reloj, activo a 1
Dim s1_on As Bit  'tecla pulsada si s1_on=1
Dim s2_on As Bit  'tecla pulsada si s2_on=1
Dim aux_ajuste As Byte  'variable auxiliar para la rutina de ajuste
'-----------------------------------------------------------------------------------------------
'-------------------------------Variables del ADC y Rutina division (temperatura)------------------------------
Dim entero As Word  'parte entera
Dim decimal As Word  'los dos decimales
Dim division As Long  'almacenara el numero con los dos decimales
Dim adc_4 As Word  'contendra el valor de la entrada del ADC
Dim aux_adc_4 As Word  'auxiliar
'--------------------------------Variables temperatura-------------------------------------------
Dim factor_escala As Word  'contiene el factor de correcion para pasar el valor del ADC a voltios, max. 5V
Dim temperatura As Word  'almacena la temperatura final
Dim temp As Long  'contendra la temperatura completa sin coma
Dim signo As Bit  'indica el signo de la temperatura
'--------------------------------Variables calculo media aritmetica (temperatura)----------------------------
Dim media_temp(20) As Word  'numero de muestras para calcular la media aritmetica
Dim media_indice As Byte  'se utiliza como indice
Dim aux_media As Byte  'variable auxiliar
'------------------------------------------ASIGNACIONES------------------------------------------
'------------------------------------asignacion de valores a las variables (RTC)--------------------------
s1_on = 0
s2_on = 0
dato = 7  'fuera de ajuste o modo normal de trabajo del reloj, de 0 a 6 modo ajuste
flash_1 = 0
flag_1 = 0
timer_base = 0
timer1_ms = 0
timer2_ms = 0
timer3_ms = 0
timer1_100ms = 0
timer2_100ms = 0
timer3_100ms = 0
timer_base_tiempo = 1  '100  'temporiza 100 mSeg
timer_1ms_tiempo = 1  'temporiza 1mseg
timer1_ms_tiempo = 1  '100  'temporiza 100 mSeg., asignado a la tecla S1
timer2_ms_tiempo = 1  '500  'temporiza 500 mSeg.
timer3_ms_tiempo = 1  '100  'temporiza 100 mSeg., asignado a la tecla S2
timer1_100ms_tiempo = 1  '10  'temporiza 1 Seg.
timer2_100ms_tiempo = 1  '255  'temporiza 25.5 Seg.
timer3_100ms_tiempo = 1  'temporiza 0.1seg.
'-------------------------------------asiganacion de valores a las variables (temperatura)------
entero = 0
decimal = 0
division = 0
adc_4 = 0
factor_escala = 10  'factor de escala para un decimal
temperatura = 0
temp = 0
media_indice = 0
aux_media = 0
'**************************************DEFINICION DE PUERTOS*************************************
'----------------------ASIGNACION DE I/O y valores de inicio de las salidas---------------------
Define ADC_SAMPLEUS = 0  'el minimo, configuracion del ADC
Define ADC_CLOCK = 5  '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
'_______________registros afectados por Define ADC_CLOCK y ADCIN________________
ANSEL = %00010000  'los pin I/O digitales y RA4 analogico
ADCON0 = %01100000  'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
ADCON1 = %01000000  'voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
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)
PORTB.3 = 1  'luz lcd a on (RB3)
PORTA.7 = 1  'led amarillo a off
PORTB.0 = 1  'led verde a off
'------------------------------------Inicializacion de Interrupciones-----------------------------
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 = 0x30  '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
Serout PORTB.5, 4800, 0x0c, "MUESTRA LA TEMPERATURA MEDIA CADA 25.5 Seg.", CrLf  'alpuerto serie
Serout PORTB.5, 4800, "-------------------------------------------", CrLf, CrLf  'alpuerto serie
PIE1.TMR1IE = 1  'activa las interrupciones del timer1
pause = 1000
Gosub pause_ms  'espera el tiempo indicado en pause
Lcdout "16F88LCD_RTC/I2C"  'escribe en el lcd
Lcdcmdout LcdLine2Home  'seleciona la linea dos como proxima para escritura
Lcdout "ADC_LM35_RS232"  'escribe en el lcd
pause = 3000
Gosub pause_ms  'espera el tiempo indicado en pause
Lcdcmdout LcdClear  'borra el display y cursor a casa
'--------------------------------inicializa variable media_temperatura---------------------------
Gosub inicializa_temp
'--------------------------------inicializa los registros del RTC---------------------------------
Gosub inicaliza_rtc
« Última modificación: 20 de Mayo de 2007, 20:03:13 por dogflu66 »
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #188 en: 20 de Mayo de 2007, 20:01:23 »
2ª Parte
----------
Código: [Seleccionar]
'--------------------------------------Main Programa-----------------------------------------------
main:
If s1 = 1 And s1_on = 1 And s2 = 1 And s2_on = 1 And flag_1 = 0 Then  '________modo ajuste
flag_1 = 1  'activa la rutina de ajustes
dato = 0  'selecciono registro del RTC
pause = 200
Gosub pause_ms  'hace una pausa del valor que tenga pause en ms
s1_on = 0  'desbloquea la tecla S1
s2_on = 0  'desbloquea la tecla s2
Endif  '___________________
If flag_1 = 1 Then Gosub ajuste_reloj  '__________saltamos a la rutina de ajuste
If timer3_100ms >= timer3_100ms_tiempo Then  'actualiza datos en el lcd cada 100ms
Gosub lee_hora  'lee la fecha y hora del reloj
Gosub print_lcd  'actualiza los datos del reloj en el display
timer3_100ms = 0
Endif  '__________________
If timer2_100ms >= timer2_100ms_tiempo Then
Gosub lee_adc  'salto con retorno, rutina de lectura de la entrada ADC
Gosub temp_calculo  'salto con retorno, hace el calculo de la temperatura y guarda el valor en temperatura
Gosub media_arit  'salto con retorno, calcula la media aritmetica
division = dvsion_dcmles(temperatura, factor_escala)  'llama a la funcion dvsion_dcmles, que retorna un long
Gosub print_rs232_temperatura
Gosub print_rs232_date
timer2_100ms = 0
Endif
Goto main
End                                               
'--------------------------------------FIN DEL MAIN---------------------------------------------
'**************************************Subrrutinas**********************************************
inicaliza_rtc:  '-------------------------inicializa el reloj----------------------------------------------------
PIE1.TMR1IE = 0  'deshabilita las interrupciones del timer1
I2CRead sda, scl, 0xd0, 0, reg(0)  'leo los segundos
reg(0) = reg(0) And %01111111  'habilito bit de control que activa el reloj
I2CWrite sda, scl, 0xd0, 0, reg(0)  'escribo el registro de los segundos
I2CRead sda, scl, 0xd0, 1, reg(0)  'leo el registro de los minutos
reg(0) = reg(0) And %10111111  'habilito bit de control que activa el formato de 24h
I2CWrite sda, scl, 0xd0, 0, reg(0)  'escribo el registro de los minutos
'-------------------------------inicializa la salida del RTC-------------------------------
If s1 = 0 Then I2CWrite sda, scl, 0xd0, 7, 0x10  'salida a 1hz, a on
If s2 = 0 Then I2CWrite sda, scl, 0xd0, 7, 0x80  'salida a off, led off
PIE1.TMR1IE = 1  'habilita las interrupciones del timer1
pause = 1000
Gosub pause_ms  'espera el tiempo indicado en pause
Return                                           
ajuste_reloj:  'rutina de ajuste del reloj
'________________________Control posicion del dato a variar en el reloj
If s1 = 1 And s1_on = 1 And s2_on = 0 Then  'detecta tecla S1
dato = dato + 1  'seleciona el dato a ser modificado
If dato > 6 Then flag_1 = 0  'indica fin de rutina de ajuste
s1_on = 0  'la tecla queda desbloqueada
Endif  '_____________________________
'____________Lectura de la hora para su modificacion y posterior grabacion, rutina BCD
If s2 = 1 And s2_on = 1 And s1_on = 0 Then  'deteca tecla S2
s2_on = 0  'la tecla queda desbloqueada
If dato < 7 Then  'limita la direcciones de trabajo del reloj
Gosub lee_hora  'lee los datos de los regis. RTC y los pasa a decimal, elimina los bit de control
aux_ajuste = reg(dato)  'hace una imagen del valor del registro a modificar
aux_ajuste = aux_ajuste + 1  'incrementa el dato a modificar que fue seleccionado
If dato = 2 And aux_ajuste > 23 Then aux_ajuste = 0  'acota horas
If dato = 0 Or dato = 1 Then  'acota segundos y minutos
If aux_ajuste > 59 Then aux_ajuste = 0
Endif
If dato = 3 And aux_ajuste > 7 Then aux_ajuste = 1  'acota el dia de la semana
If dato = 4 And aux_ajuste > 31 Then aux_ajuste = 1  'acota el dia del mes
If dato = 5 And aux_ajuste > 12 Then aux_ajuste = 1  'acota el mes
If dato = 6 And aux_ajuste > 30 Then aux_ajuste = 1  'acota el año, año maximo 2030
If aux_ajuste > 49 And aux_ajuste < 60 Then  'Decimal a BCD
aux_ajuste = aux_ajuste - 50
aux_ajuste.4 = 1
aux_ajuste.6 = 1
Endif
If aux_ajuste > 39 And aux_ajuste < 50 Then  'Decimal a BCD
aux_ajuste = aux_ajuste - 40
aux_ajuste.6 = 1
Endif
If aux_ajuste > 29 And aux_ajuste < 40 Then  'Decimal a BCD
aux_ajuste = aux_ajuste - 30
aux_ajuste.4 = 1
aux_ajuste.5 = 1
Endif
If aux_ajuste > 19 And aux_ajuste < 30 Then  'Decimal a BCD
aux_ajuste = aux_ajuste - 20
aux_ajuste.5 = 1
Endif
If aux_ajuste > 9 And aux_ajuste < 20 Then  'Decimal a BCD
aux_ajuste = aux_ajuste - 10
aux_ajuste.4 = 1
Endif
If aux_ajuste < 10 Then aux_ajuste = aux_ajuste  'Decimal a BCD
If dato = 0 Then aux_ajuste.7 = 0  'restaura el bit de configracion, activa el oscilador del reloj
If dato = 2 Then aux_ajuste.7 = 0  'restaura el bit, no lo utiliza el RTC
If dato = 2 Then aux_ajuste.6 = 0  'restaura el bit de configuracion, reloj 24h
PIE1.TMR1IE = 0  'deshabilita las interrupciones del timer1
I2CWrite sda, scl, 0xd0, dato, aux_ajuste  'actualiza el dato ya modificado
PIE1.TMR1IE = 1  'activa las interrupciones del timer1
Endif
Endif  '____________
'__________Controla el parpadeo de los digitos cuando el modo selec es activo
If timer2_ms >= timer2_ms_tiempo Then  'tiempo del parpadeo
If flash_1 = 1 Then  'selecciona si el dato a modificar es visible o no
flash_1 = 0  'dato es visible
Else
flash_1 = 1  'dato no es visible
Endif
timer2_ms = 0  'recarga la base de tiempos
Endif  '______________
Return                                           
lee_hora:  'lee la hora del RTC en formato BCD y la pasa a decimal
i = 0  'variable indice, asigna los datos de forma ordenada, leidos del RTC
While i <= 6  'se repite el codigo comprendido entre while y wend, mientras i sea menor o igual a 6
PIE1.TMR1IE = 0  'deshabilita las interrupciones del timer1
I2CRead sda, scl, 0xd0, i, reg(i)  'lectura de la direccion de memoria indicada del RTC, formato BCD
PIE1.TMR1IE = 1  'activa las interrupciones del timer1
aux_4l = reg(i) And %00001111  'eliminamos los bit de configuracion del RTC y dejamos solo el nibble bajo
If i = 0 Then aux_4h = reg(i) And %01110000  'segundos, borrado de bit configuracion y almacena nibble alto
If i = 1 Then aux_4h = reg(i) And %01110000  'minutos, almacena nibble alto
If i = 2 Then aux_4h = reg(i) And %00110000  'horas, borrado de bit configuracion y almacena nibble alto
If i = 3 Then aux_4h = reg(i) And %00000000  'dia_semana, almacena nibble alto
If i = 4 Then aux_4h = reg(i) And %00110000  'dia_mes, almacena nibble alto
If i = 5 Then aux_4h = reg(i) And %00010000  'mes, almacena el nibble alto
If i = 6 Then aux_4h = reg(i) And %11110000  'año, almacena el nibble alto
aux_4h = ShiftRight(aux_4h, 4)  'convierte el nibble alto en bajo
reg(i) = (aux_4h * 10) + aux_4l  'fusiona los nibbles alto y bajo en una sola variable en formato decimal
i = i + 1  'incrementa la variable indice con cada repeticion del bucle While/Wend
Wend  'fin del bucle y salta a While
Return                                           
print_lcd:  'rutina de escritura en el lcd
Lcdcmdout LcdLine1Home  'cursor del lcd a la izquierda en la linea 1
If dato = 2 And flash_1 = 1 Then  'control final del parpadeo de los digitos de la hora
Lcdout "  "  'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(2) < 10 Then Lcdout "0"  'si horas es inferior a 10 escribe el cero delante
Lcdout #reg(2)  'escribe la hora
Endif
Lcdout ":"  'escribe el separador
If dato = 1 And flash_1 = 1 Then  'control final del parpadeo de los digitos de los minutos
Lcdout "  "  'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(1) < 10 Then Lcdout "0"  'si minutos es inferior a 10 escribe el cero delante
Lcdout #reg(1)  'escribe los minutos
Endif
Lcdout ":"  'escribe el separador
If dato = 0 And flash_1 = 1 Then  'control final del parpadeo de los digitos de los segundos
Lcdout "  "  'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(0) < 10 Then Lcdout "0"  'si segundos es inferior a 10 escribe el cero delante
Lcdout #reg(0)  'escribe los segundos
Endif
Gosub print_lcd_temp  'salto con retorno a la rutina de impresion de la temperatura
Lcdcmdout LcdLine2Home  'cursor del lcd a la izquierda en la linea 2
If dato = 3 And flash_1 = 1 Then  'control final del parpadeo de los digitos del dia semana
Lcdout "    "  'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(3) = 1 Then Lcdout "Dom."  'asigna el literal al dia de la semana
If reg(3) = 2 Then Lcdout "Lun."
If reg(3) = 3 Then Lcdout "Mar."
If reg(3) = 4 Then Lcdout "Mie."
If reg(3) = 5 Then Lcdout "Jue."
If reg(3) = 6 Then Lcdout "Vie."
If reg(3) = 7 Then Lcdout "Sab."
Endif
Lcdout " "  'escribe separador
If dato = 4 And flash_1 = 1 Then  'control final del parpadeo de los digitos del dia del mes
Lcdout "  "  'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(4) < 10 Then Lcdout "0"  'si dia del mes es inferior a 10 escribe cero
Lcdout #reg(4)  'escribe el dia del mes
Endif
Lcdout "/"  'escribe el separador
If dato = 5 And flash_1 = 1 Then  'control final del parpadeo de los digitos de los meses
Lcdout "  "  'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(5) < 10 Then Lcdout "0"  'si mes es inferior a 10 escribe cero
Lcdout #reg(5)  'escribe el mes
Endif
Lcdout "/20"  'separador y los dos primeros digitos del año de 4 digitos
If dato = 6 And flash_1 = 1 Then  'control final del parpadeo de los digitos de los años
Lcdout "  "  'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(6) < 10 Then Lcdout "0"  'si año es inferior a 10 escribe primero el cero
Lcdout #reg(6)  'escribe el año
Endif
Return                                           
'--------------------------------------Subrrutina lectura ADC, division y LCD
lee_adc:  '_______________________lee la entrada analogica
Adcin 4, adc_4  'lee el valor de la entrada analogica y lo guarda en adc_4
Return                                           
print_lcd_temp:  '____________________muestra los datos por el display
entero = division.HW  'sede el word alto a entero, parte entera
decimal = division.LW  'sede el byte alto del word bajo a decimal_1
Lcdout " "  'espacio en blanco
If signo = 0 Then Lcdout "+", #entero, "."  'muestra los datos en el lcd
If signo = 1 Then Lcdout "-", #entero, "."  'muestra los datos en el lcd
Lcdout #decimal, "C   "  'muestra los datos en el lcd
Return                                           
'________Argumentos de entrada dos variables tipo word, dividendo y divisor, argumento de salida una variable tipo long
Function dvsion_dcmles(dvdo As Word, dvsor As Word) As Long  '________Rutina funcion division con decimales
Dim f_entera As Word  'variable local, contendra la parte entera
Dim f_resto As Word  'varable local, contendra el resto
Dim f_decimal As Word  'contendra la parte decimal
f_entera = dvdo / dvsor  'obtengo la division
f_resto = dvdo Mod dvsor  'obtengo el resto
f_decimal = (f_resto * 10) / dvsor  'calculo 1 decimal, para obtener 2 decimales multiplicar por 100
dvsion_dcmles.HW = f_entera  'almacena la parte entera en el word alto
dvsion_dcmles.LW = f_decimal  'almacena la parte decimal word bajo
'Recuerda que la parte decimal tiene que ser mostrada en el display con plantilla de dos digitos siempre
End Function                                     
'___________Calculo de la media aritmetica de la temperatura, 20 muestras
media_arit:
media_temp(media_indice) = temperatura  'asigna el valor
temperatura = 0  'se inicaliza a cero
For aux_media = 0 To 19  'blucle for, se ejecuta 20 veces
temperatura = temperatura + media_temp(aux_media)  'se suman los valores
Next aux_media  'cierra for
temperatura = temperatura / 20  'termina el calculo de la media
media_indice = media_indice + 1  'controla la entrada de datos que corresponde a media_temp(x)
If media_indice > 19 Then media_indice = 0  'acota el ultimo valor del indice de media_temp
Return                                           
'___________Calculo de la temperatura
temp_calculo:  'calculo de la temperatura y del signo de la misma
If adc_4 > 112 Then  'determina si la temperatura es superior a 0ºC
aux_adc_4 = adc_4  'asigna el valor del ra4 a la variable auxiliar
aux_adc_4 = aux_adc_4 - 112  'elimina de la temperatura la parte de la escala negativa
temp = (5000 * aux_adc_4) / 1023  'calcuala el valor de la temperatura sin coma decimal
signo = 0  'temperatura positiva
Endif
If adc_4 = 112 Then  'determina si la temperatura es 0ºC
temp = 0  'temperatura 0ºC
signo = 0  'asigna signo positivo
Endif
If adc_4 < 112 Then  'determina si la temperatura es inferior a 0ºC
aux_adc_4 = adc_4  'asigna el valor del RA4 a la variable auxiliar
aux_adc_4 = 112 - aux_adc_4  'elimina de la temperatura la parte de la escala negativa
temp = (5000 * aux_adc_4) / 1023  'calcuala el valor de la temperatura sin coma decimal
signo = 1  'asigna el simbolo menos a la temperatura
Endif
temperatura = temp  'se pasa de Long a Word
Return                                           
inicializa_temp:  '__________inicializa la media aritmetica de la temperatura en el arranque
Gosub lee_adc  'salto con retorno, rutina de lectura de la entrada ADC
Gosub temp_calculo  'salto con retorno, hace el calculo de la temperatura y guarda el valor en temperatura
For media_indice = 0 To 19  'indice para rocorrer todas las direcciones de memoria que forman la variable tipo array media_temp
media_temp(media_indice) = temperatura  'se de el valor a media_temp
Next media_indice  'terminacion del bucle For
media_indice = 0  'se inicializa a cero, para un uso posterior
Gosub media_arit  'salto con retorno, calcula la media aritmetica
division = dvsion_dcmles(temperatura, factor_escala)  'llama a la funcion dvsion_dcmles, que retorna un long
Return                                           
print_rs232_temperatura:  'Envia la temperatura con decimales al puerto serie
PIE1.TMR1IE = 0  'OFF, interrupciones del timer1
Serout PORTB.5, 4800, "TEMPERATURA: "  'pagina en blanco y literal al purto serie
If signo = 0 Then Serout PORTB.5, 4800, "+"  'muestra el signo de la temperatura
If signo = 1 Then Serout PORTB.5, 4800, "-"  'muestra el signo de la temperatura
Serout PORTB.5, 4800, #entero, ".", #decimal, " "  'temperatura al rs232
PIE1.TMR1IE = 1  'ON, interrupciones del timer1
Return                                           
print_rs232_date:  'rutina de escritura de la hora y fecha por el RS232
PIE1.TMR1IE = 0  'OFF, interrupciones del timer1
If reg(2) < 10 Then Serout PORTB.5, 4800, " 0"  'si horas es inferior a 10 escribe el cero delante
Serout PORTB.5, 4800, #reg(2), ":"  'escribe la hora
If reg(1) < 10 Then Serout PORTB.5, 4800, "0"  'si minutos es inferior a 10 escribe el cero delante
Serout PORTB.5, 4800, #reg(1), ":"  'escribe los minutos
If reg(0) < 10 Then Serout PORTB.5, 4800, "0"  'si segundos es inferior a 10 escribe el cero delante
Serout PORTB.5, 4800, #reg(0), " "  'escribe los segundos
If reg(3) = 1 Then Serout PORTB.5, 4800, "Dom."  'asigna el literal al dia de la semana
If reg(3) = 2 Then Serout PORTB.5, 4800, "Lun."
If reg(3) = 3 Then Serout PORTB.5, 4800, "Mar."
If reg(3) = 4 Then Serout PORTB.5, 4800, "Mie."
If reg(3) = 5 Then Serout PORTB.5, 4800, "Jue."
If reg(3) = 6 Then Serout PORTB.5, 4800, "Vie."
If reg(3) = 7 Then Serout PORTB.5, 4800, "Sab."
If reg(4) < 10 Then Serout PORTB.5, 4800, " 0"  'si dia del mes es inferior a 10 escribe cero
Serout PORTB.5, 4800, #reg(4), "/"  'escribe el dia del mes
If reg(5) < 10 Then Serout PORTB.5, 4800, "0"  'si mes es inferior a 10 escribe cero
Serout PORTB.5, 4800, #reg(5), "/20"  'escribe el mes
If reg(6) < 10 Then Serout PORTB.5, 4800, "0"  'si año es inferior a 10 escribe primero el cero
Serout PORTB.5, 4800, #reg(6), CrLf  'escribe el año
PIE1.TMR1IE = 1  'ON, interrupciones del timer1
Return                                           
pause_ms:  'rutina de espera, rutina tipo Waitms, pause establese el tiempo total en mSeg
pause = 1  'ESTA LINEA SOLO SE ACTIVA CUANDO SE UTILIZA EL SIMULADOR
PIE1.TMR1IE = 0  'OFF, interrupciones del timer1
timer_1ms_tiempo = pause  'valor a temporizar por timer_1ms
PIE1.TMR1IE = 1  'ON, interrupciones del timer1
timer_1ms = 0  'al borrar el contador se activa y comienza la cuenta de 1mSeg
While timer_1ms < pause  'tiempo en mSeg maximos a contar
Wend
Return                                           
'***********************************Interrupciones*****************************************************
On Interrupt  'Comienzan las rutinas de las interrupciones, desactiva las interrupciones
TMR1H = 0xf8  'recarga el contador del timer1 para que desborde pasado 1mSeg, byte alto
TMR1L = 0x30  'recarga el contador del timer1 para que desborde pasado 1mSeg, byte bajo
Save System  'Guarda los valores del sistema para poder reemprender el curso normal del programa
If PIR1.TMR1IF = 1 Then  'comprueba que la interrupcion del timer1 es activa
'_________________bases de tiempos
timer_base = timer_base + 1  'contador general
If timer_1ms < timer_1ms_tiempo Then timer_1ms = timer_1ms + 1  'contador para control de la rutina Pause
If timer1_ms < timer1_ms_tiempo Then timer1_ms = timer1_ms + 1  'contador
If timer2_ms < timer2_ms_tiempo Then timer2_ms = timer2_ms + 1  'contador
If timer3_ms < timer3_ms_tiempo Then timer3_ms = timer3_ms + 1  'contador
If timer_base >= timer_base_tiempo Then  'limita el timepo de ejecucion, cada timer_base_tiempo
If timer1_100ms < timer1_100ms_tiempo Then timer1_100ms = timer1_100ms + 1  'contador
If timer2_100ms < timer2_100ms_tiempo Then timer2_100ms = timer2_100ms + 1  'condtador
If timer3_100ms < timer3_100ms_tiempo Then timer3_100ms = timer3_100ms + 1  'contador
timer_base = 0  'reset a la base de tiempos
Endif  '________________fin bases de tiempos
PIR1.TMR1IF = 0  'borra el flag de salto del tmr1
Endif
'_________________Detecta tecla pulsada
If s1 = 0 And s1_on = 0 And timer1_ms >= timer1_ms_tiempo Then  'tecla S1
s1_on = 1  'la tecla fue pulsada
s2_on = 0  'la tecla s2 a pff
If s1 = 0 And s2 = 0 Then s2_on = 1  'S2
timer1_ms = 0  'tiempo entre pulsacion y pulsacion
Endif
If s2 = 0 And s2_on = 0 And timer3_ms >= timer3_ms_tiempo Then  'tecla s2
s2_on = 1  'la tecla fue pulsada
s1_on = 0  'la tecla s1 a off
If s1 = 0 And s2 = 0 Then s1_on = 1  'S1
timer3_ms = 0  'tiempo entre pulsacion y pulsacion
Endif
If s1 = 0 Then led_verde = 0  'mestra el estado de S1
If s2 = 0 Then led_amarillo = 0  'muestra el estado de S2
If s1 = 1 Then led_verde = 1  'mestra el estado de S1
If s2 = 1 Then led_amarillo = 1  'muestra el estado de S2
'________Fin detecta tecla pulsada
Resume  'activa las interrupciones y retorna el curso normal del programa, antes del salto

PD: 03/06/08
      %1101000x (direccion de seleccion del chip %1101000) siendo "x" el bit indicador de Write/Read. Modificado por I2CWrite y I2CRead.
« Última modificación: 02 de Junio de 2008, 20:11:44 por dogflu66 »
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #189 en: 20 de Mayo de 2007, 20:05:22 »
PD. programa trucado para la simulacion
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #190 en: 26 de Mayo de 2007, 06:54:39 »
Este programa hace lo mismo que el anterior pero con dos detalles muy importantes que lo diferencian:
- El anterior ocupa 4005 Word y este ocupa 3684 Word de programa.
- El anterior va mucho mas lento que este otro.

Este es un claro ejemplo de por que se deben utilizar los modulos internos del microcontrolador siempre que se pueda.


Código: [Seleccionar]
'********************************** PIC Entrenadora BASIC (PicEBasic)******************************
'NOMBRE: 16F88_Pic_EBasic_LCD_RTC_ADC_12
'MICRO: PIC16F88
'FECHA/AUTOR: 04/07, 05/07 - By COS
'VERSION 1.2
'Se habilita el modulo usar como salida de datos serie
'se cambian todos los "Serout PORTB.5, 4800, " por Hserout
'se observa un ahorro de memoria considerable y una aceleracion del programa increible.
'VERSION 1.1
'modificacion de la rutina "pause_ms"
'modificacion de rutina de teclas, porque se veian afectadas al crecer la longitud del programa main
'Se añade salida de la temperatura, hora y fecha por el puerto serie (Soft)
'Pendiente de grafica de temperatura por el hyperterminal
'VERSION 1.0
'DESCRIPCION: Muestra en el display la fecha, hora (24h)mediante el DS1307 y temperatura (LM35)
'S1 y S2 pulsadas al mismo tiempo, entramos en programacion del reloj
'Una vez en programacion con S1 seleccionamos el dato a cambiar, este queda en modo parpadeo
'Una vez en programacion con S2 incrementamos el dato seleccionado dentro de sus cotas
'S1, pulsado al principio salida del RTC a on, 1Hz, y S2 salida a off, led off
'Se muestra la temperatura en el LCD mediante un LM35, temperatura positiva y negativa
'***************************************************************************************************
'-------------------------------------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 nrol RS sera del puerto B
Define LCD_RSBIT = 7  'se usara el RB7 como RS
Define LCD_EREG = PORTB  'el bit de nrol E sera del puerto B
Define LCD_EBIT = 6  'se usara el RB6 como E
Define LCD_COMMANDUS = 500  '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.
'-----------------------------------asignacion de nombres-----------------------------------------------------
Symbol sda = PORTB.1  'asignamos nombre al pin que hara de SDA del puerto I2C
Symbol scl = PORTB.4  'asignamos nombre al pin que hara de SCL del puerto I2C
Symbol led_amarillo = PORTA.7  'led amarillo
Symbol led_verde = PORTB.0  'led verde
Symbol luz_lcd = PORTB.3  'retroiluminacion del lcd
Symbol s1 = RA6  'se asigna nombre a la tecla
Symbol s2 = RA5  'se asigna nombre a la tecla
'***********************************DEFINICION DE VARIABLES**************************************
'-----------------------------------variables de los timer---------------------------------------
Dim aux_pause As Word  'variable auxiiar el PAUSE
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_base As Byte  'tiempo referencia para los timer por soft del programa
Dim timer_base_tiempo As Byte  'contiene el valor del tiempo del timer_base
Dim timer1_ms As Word  'base de tiempos en ms
Dim timer2_ms As Word  'base de tiempos en ms
Dim timer3_ms As Word  'base de tiempos ms
Dim timer1_100ms As Byte  'base de tiempos msx100
Dim timer2_100ms As Byte  'base de tiempos msx100
Dim timer3_100ms As Byte  'base de tiempos msx100
Dim timer_1ms_tiempo As Word  'contiene el valor del tiempo de timer_1ms
Dim timer1_ms_tiempo As Word  'contiene el valor del tiempo del timer1_ms
Dim timer2_ms_tiempo As Word  'contiene el valor del tiempo del timer2_ms
Dim timer3_ms_tiempo As Word  'contiene el valor del tiempo del timer3_ms
Dim timer1_100ms_tiempo As Byte  'contiene el valor del tiempo del timer1_100ms
Dim timer2_100ms_tiempo As Byte  'contiene el valor del tiempo del timer2_100ms
Dim timer3_100ms_tiempo As Byte  'contiene el valor del tiempo del timer3_100ms
'--------------------------------------Variables Programa RTC----------------------------------------
Dim aux_4h As Byte  'contendra el nibble alto del dato leido por el I2C
Dim aux_4l As Byte  'contendra el nibble bajo del dato leido por el I2C
Dim i As Byte  'variable indice
Dim reg(7) As Byte  'contendra los valores finales de fecha y hora en el sistema decimal
Dim flash_1 As Bit  'controla el parpadeo de los digitos del lcd, activo a 1
Dim dato As Byte  'indica la direccion del RTC a cambiar de valor
Dim flag_1 As Bit  'activa la rutina de ajuste del reloj, activo a 1
Dim s1_on As Bit  'tecla pulsada si s1_on=1
Dim s2_on As Bit  'tecla pulsada si s2_on=1
Dim aux_ajuste As Byte  'variable auxiliar para la rutina de ajuste
'-----------------------------------------------------------------------------------------------
'-------------------------------Variables del ADC y Rutina division (temperatura)------------------------------
Dim entero As Word  'parte entera
Dim decimal As Word  'los dos decimales
Dim division As Long  'almacenara el numero con los dos decimales
Dim adc_4 As Word  'contendra el valor de la entrada del ADC
Dim aux_adc_4 As Word  'auxiliar
'--------------------------------Variables temperatura-------------------------------------------
Dim factor_escala As Word  'contiene el factor de correcion para pasar el valor del ADC a voltios, max. 5V
Dim temperatura As Word  'almacena la temperatura final
Dim temp As Long  'contendra la temperatura completa sin coma
Dim signo As Bit  'indica el signo de la temperatura
'--------------------------------Variables calculo media aritmetica (temperatura)----------------------------
Dim media_temp(20) As Word  'numero de muestras para calcular la media aritmetica
Dim media_indice As Byte  'se utiliza como indice
Dim aux_media As Byte  'variable auxiliar
'------------------------------------------ASIGNACIONES------------------------------------------
'------------------------------------asignacion de valores a las variables (RTC)--------------------------
s1_on = 0
s2_on = 0
dato = 7  'fuera de ajuste o modo normal de trabajo del reloj, de 0 a 6 modo ajuste
flash_1 = 0
flag_1 = 0
timer_base = 0
timer1_ms = 0
timer2_ms = 0
timer3_ms = 0
timer1_100ms = 0
timer2_100ms = 0
timer3_100ms = 0
timer_base_tiempo = 1  '100  'temporiza 100 mSeg
timer_1ms_tiempo = 1  'temporiza 1mseg
timer1_ms_tiempo = 1  '100  'temporiza 100 mSeg., asignado a la tecla S1
timer2_ms_tiempo = 1  '500  'temporiza 500 mSeg.
timer3_ms_tiempo = 1  '100  'temporiza 100 mSeg., asignado a la tecla S2
timer1_100ms_tiempo = 1  '10  'temporiza 1 Seg.
timer2_100ms_tiempo = 1  '255  'temporiza 25.5 Seg.
timer3_100ms_tiempo = 1  'temporiza 0.1seg.
'-------------------------------------asiganacion de valores a las variables (temperatura)------
entero = 0
decimal = 0
division = 0
adc_4 = 0
factor_escala = 10  'factor de escala para un decimal
temperatura = 0
temp = 0
media_indice = 0
aux_media = 0
'**************************************DEFINICION DE PUERTOS*************************************
'----------------------ASIGNACION DE I/O y valores de inicio de las salidas---------------------
Define ADC_SAMPLEUS = 0  'el minimo, configuracion del ADC
Define ADC_CLOCK = 5  '16Tad a 8Mhz = 2uSeg, minimo permitido por el micro 1.5uSeg, configuracion ADC
'_______________registros afectados por Define ADC_CLOCK y ADCIN________________
ANSEL = %00010000  'los pin I/O digitales y RA4 analogico
ADCON0 = %01100000  'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.uSeg), channel RA4
ADCON1 = %01000000  'voltage reference (AVdd/AVss) y seleccion de escala division clock/2 ADCON1.ADCS2=1
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)
PORTB.3 = 1  'luz lcd a on (RB3)
PORTA.7 = 1  'led amarillo a off
PORTB.0 = 1  'led verde a off
'------------------------------------Velocidad de la UART-----------------------------------------
Hseropen 4800  'velocidad de trabajo del modulo UART del PIC, RB5 tiene que ser declarado como salida
'------------------------------------Inicializacion de Interrupciones-----------------------------
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 = 0x30  '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
Hserout 0x0c, "MUESTRA LA TEMPERATURA MEDIA CADA 25.5 Seg.", CrLf  'alpuerto serie
Hserout "-------------------------------------------", CrLf, CrLf  'alpuerto serie
PIE1.TMR1IE = 1  'activa las interrupciones del timer1
pause = 1000
Gosub pause_ms  'espera el tiempo indicado en pause
Lcdout "16F88LCD_RTC/I2C"  'escribe en el lcd
Lcdcmdout LcdLine2Home  'seleciona la linea dos como proxima para escritura
Lcdout "ADC_LM35_RS232"  'escribe en el lcd
pause = 3000
Gosub pause_ms  'espera el tiempo indicado en pause
Lcdcmdout LcdClear  'borra el display y cursor a casa
'--------------------------------inicializa variable media_temperatura---------------------------
Gosub inicializa_temp
'--------------------------------inicializa los registros del RTC---------------------------------
Gosub inicaliza_rtc
'--------------------------------------Main Programa-----------------------------------------------
main:
If s1 = 1 And s1_on = 1 And s2 = 1 And s2_on = 1 And flag_1 = 0 Then  '________modo ajuste
flag_1 = 1  'activa la rutina de ajustes
dato = 0  'selecciono registro del RTC
pause = 200
Gosub pause_ms  'hace una pausa del valor que tenga pause en ms
s1_on = 0  'desbloquea la tecla S1
s2_on = 0  'desbloquea la tecla s2
Endif  '___________________
If flag_1 = 1 Then Gosub ajuste_reloj  '__________saltamos a la rutina de ajuste
If timer3_100ms >= timer3_100ms_tiempo Then  'actualiza datos en el lcd cada 100ms
Gosub lee_hora  'lee la fecha y hora del reloj
Gosub print_lcd  'actualiza los datos del reloj en el display
timer3_100ms = 0
Endif  '__________________
If timer2_100ms >= timer2_100ms_tiempo Then
Gosub lee_adc  'salto con retorno, rutina de lectura de la entrada ADC
Gosub temp_calculo  'salto con retorno, hace el calculo de la temperatura y guarda el valor en temperatura
Gosub media_arit  'salto con retorno, calcula la media aritmetica
division = dvsion_dcmles(temperatura, factor_escala)  'llama a la funcion dvsion_dcmles, que retorna un long
Gosub print_rs232_temperatura
Gosub print_rs232_date
timer2_100ms = 0
Endif
Goto main
End                                               
'--------------------------------------FIN DEL MAIN---------------------------------------------
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #191 en: 26 de Mayo de 2007, 06:56:39 »
La segunda parte del programa:
Código: [Seleccionar]
'**************************************Subrrutinas**********************************************
inicaliza_rtc:  '-------------------------inicializa el reloj----------------------------------------------------
PIE1.TMR1IE = 0  'deshabilita las interrupciones del timer1
I2CRead sda, scl, 0xd0, 0, reg(0)  'leo los segundos
reg(0) = reg(0) And %01111111  'habilito bit de control que activa el reloj
I2CWrite sda, scl, 0xd0, 0, reg(0)  'escribo el registro de los segundos
I2CRead sda, scl, 0xd0, 1, reg(0)  'leo el registro de los minutos
reg(0) = reg(0) And %10111111  'habilito bit de control que activa el formato de 24h
I2CWrite sda, scl, 0xd0, 0, reg(0)  'escribo el registro de los minutos
'-------------------------------inicializa la salida del RTC-------------------------------
If s1 = 0 Then I2CWrite sda, scl, 0xd0, 7, 0x10  'salida a 1hz, a on
If s2 = 0 Then I2CWrite sda, scl, 0xd0, 7, 0x80  'salida a off, led off
PIE1.TMR1IE = 1  'habilita las interrupciones del timer1
pause = 1000
Gosub pause_ms  'espera el tiempo indicado en pause
Return                                           
ajuste_reloj:  'rutina de ajuste del reloj
'________________________Control posicion del dato a variar en el reloj
If s1 = 1 And s1_on = 1 And s2_on = 0 Then  'detecta tecla S1
dato = dato + 1  'seleciona el dato a ser modificado
If dato > 6 Then flag_1 = 0  'indica fin de rutina de ajuste
s1_on = 0  'la tecla queda desbloqueada
Endif  '_____________________________
'____________Lectura de la hora para su modificacion y posterior grabacion, rutina BCD
If s2 = 1 And s2_on = 1 And s1_on = 0 Then  'deteca tecla S2
s2_on = 0  'la tecla queda desbloqueada
If dato < 7 Then  'limita la direcciones de trabajo del reloj
Gosub lee_hora  'lee los datos de los regis. RTC y los pasa a decimal, elimina los bit de control
aux_ajuste = reg(dato)  'hace una imagen del valor del registro a modificar
aux_ajuste = aux_ajuste + 1  'incrementa el dato a modificar que fue seleccionado
If dato = 2 And aux_ajuste > 23 Then aux_ajuste = 0  'acota horas
If dato = 0 Or dato = 1 Then  'acota segundos y minutos
If aux_ajuste > 59 Then aux_ajuste = 0
Endif
If dato = 3 And aux_ajuste > 7 Then aux_ajuste = 1  'acota el dia de la semana
If dato = 4 And aux_ajuste > 31 Then aux_ajuste = 1  'acota el dia del mes
If dato = 5 And aux_ajuste > 12 Then aux_ajuste = 1  'acota el mes
If dato = 6 And aux_ajuste > 30 Then aux_ajuste = 1  'acota el año, año maximo 2030
If aux_ajuste > 49 And aux_ajuste < 60 Then  'Decimal a BCD
aux_ajuste = aux_ajuste - 50
aux_ajuste.4 = 1
aux_ajuste.6 = 1
Endif
If aux_ajuste > 39 And aux_ajuste < 50 Then  'Decimal a BCD
aux_ajuste = aux_ajuste - 40
aux_ajuste.6 = 1
Endif
If aux_ajuste > 29 And aux_ajuste < 40 Then  'Decimal a BCD
aux_ajuste = aux_ajuste - 30
aux_ajuste.4 = 1
aux_ajuste.5 = 1
Endif
If aux_ajuste > 19 And aux_ajuste < 30 Then  'Decimal a BCD
aux_ajuste = aux_ajuste - 20
aux_ajuste.5 = 1
Endif
If aux_ajuste > 9 And aux_ajuste < 20 Then  'Decimal a BCD
aux_ajuste = aux_ajuste - 10
aux_ajuste.4 = 1
Endif
If aux_ajuste < 10 Then aux_ajuste = aux_ajuste  'Decimal a BCD
If dato = 0 Then aux_ajuste.7 = 0  'restaura el bit de configracion, activa el oscilador del reloj
If dato = 2 Then aux_ajuste.7 = 0  'restaura el bit, no lo utiliza el RTC
If dato = 2 Then aux_ajuste.6 = 0  'restaura el bit de configuracion, reloj 24h
PIE1.TMR1IE = 0  'deshabilita las interrupciones del timer1
I2CWrite sda, scl, 0xd0, dato, aux_ajuste  'actualiza el dato ya modificado
PIE1.TMR1IE = 1  'activa las interrupciones del timer1
Endif
Endif  '____________
'__________Controla el parpadeo de los digitos cuando el modo selec es activo
If timer2_ms >= timer2_ms_tiempo Then  'tiempo del parpadeo
If flash_1 = 1 Then  'selecciona si el dato a modificar es visible o no
flash_1 = 0  'dato es visible
Else
flash_1 = 1  'dato no es visible
Endif
timer2_ms = 0  'recarga la base de tiempos
Endif  '______________
Return                                           
lee_hora:  'lee la hora del RTC en formato BCD y la pasa a decimal
i = 0  'variable indice, asigna los datos de forma ordenada, leidos del RTC
While i <= 6  'se repite el codigo comprendido entre while y wend, mientras i sea menor o igual a 6
PIE1.TMR1IE = 0  'deshabilita las interrupciones del timer1
I2CRead sda, scl, 0xd0, i, reg(i)  'lectura de la direccion de memoria indicada del RTC, formato BCD
PIE1.TMR1IE = 1  'activa las interrupciones del timer1
aux_4l = reg(i) And %00001111  'eliminamos los bit de configuracion del RTC y dejamos solo el nibble bajo
If i = 0 Then aux_4h = reg(i) And %01110000  'segundos, borrado de bit configuracion y almacena nibble alto
If i = 1 Then aux_4h = reg(i) And %01110000  'minutos, almacena nibble alto
If i = 2 Then aux_4h = reg(i) And %00110000  'horas, borrado de bit configuracion y almacena nibble alto
If i = 3 Then aux_4h = reg(i) And %00000000  'dia_semana, almacena nibble alto
If i = 4 Then aux_4h = reg(i) And %00110000  'dia_mes, almacena nibble alto
If i = 5 Then aux_4h = reg(i) And %00010000  'mes, almacena el nibble alto
If i = 6 Then aux_4h = reg(i) And %11110000  'año, almacena el nibble alto
aux_4h = ShiftRight(aux_4h, 4)  'convierte el nibble alto en bajo
reg(i) = (aux_4h * 10) + aux_4l  'fusiona los nibbles alto y bajo en una sola variable en formato decimal
i = i + 1  'incrementa la variable indice con cada repeticion del bucle While/Wend
Wend  'fin del bucle y salta a While
Return                                           
print_lcd:  'rutina de escritura en el lcd
Lcdcmdout LcdLine1Home  'cursor del lcd a la izquierda en la linea 1
If dato = 2 And flash_1 = 1 Then  'control final del parpadeo de los digitos de la hora
Lcdout "  "  'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(2) < 10 Then Lcdout "0"  'si horas es inferior a 10 escribe el cero delante
Lcdout #reg(2)  'escribe la hora
Endif
Lcdout ":"  'escribe el separador
If dato = 1 And flash_1 = 1 Then  'control final del parpadeo de los digitos de los minutos
Lcdout "  "  'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(1) < 10 Then Lcdout "0"  'si minutos es inferior a 10 escribe el cero delante
Lcdout #reg(1)  'escribe los minutos
Endif
Lcdout ":"  'escribe el separador
If dato = 0 And flash_1 = 1 Then  'control final del parpadeo de los digitos de los segundos
Lcdout "  "  'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(0) < 10 Then Lcdout "0"  'si segundos es inferior a 10 escribe el cero delante
Lcdout #reg(0)  'escribe los segundos
Endif
Gosub print_lcd_temp  'salto con retorno a la rutina de impresion de la temperatura
Lcdcmdout LcdLine2Home  'cursor del lcd a la izquierda en la linea 2
If dato = 3 And flash_1 = 1 Then  'control final del parpadeo de los digitos del dia semana
Lcdout "    "  'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(3) = 1 Then Lcdout "Dom."  'asigna el literal al dia de la semana
If reg(3) = 2 Then Lcdout "Lun."
If reg(3) = 3 Then Lcdout "Mar."
If reg(3) = 4 Then Lcdout "Mie."
If reg(3) = 5 Then Lcdout "Jue."
If reg(3) = 6 Then Lcdout "Vie."
If reg(3) = 7 Then Lcdout "Sab."
Endif
Lcdout " "  'escribe separador
If dato = 4 And flash_1 = 1 Then  'control final del parpadeo de los digitos del dia del mes
Lcdout "  "  'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(4) < 10 Then Lcdout "0"  'si dia del mes es inferior a 10 escribe cero
Lcdout #reg(4)  'escribe el dia del mes
Endif
Lcdout "/"  'escribe el separador
If dato = 5 And flash_1 = 1 Then  'control final del parpadeo de los digitos de los meses
Lcdout "  "  'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(5) < 10 Then Lcdout "0"  'si mes es inferior a 10 escribe cero
Lcdout #reg(5)  'escribe el mes
Endif
Lcdout "/20"  'separador y los dos primeros digitos del año de 4 digitos
If dato = 6 And flash_1 = 1 Then  'control final del parpadeo de los digitos de los años
Lcdout "  "  'borra el dato determinado para dar la sencacion de parpadeo
Else
If reg(6) < 10 Then Lcdout "0"  'si año es inferior a 10 escribe primero el cero
Lcdout #reg(6)  'escribe el año
Endif
Return                                           
'--------------------------------------Subrrutina lectura ADC, division y LCD
lee_adc:  '_______________________lee la entrada analogica
Adcin 4, adc_4  'lee el valor de la entrada analogica y lo guarda en adc_4
Return                                           
print_lcd_temp:  '____________________muestra los datos por el display
entero = division.HW  'sede el word alto a entero, parte entera
decimal = division.LW  'sede el byte alto del word bajo a decimal_1
Lcdout " "  'espacio en blanco
If signo = 0 Then Lcdout "+", #entero, "."  'muestra los datos en el lcd
If signo = 1 Then Lcdout "-", #entero, "."  'muestra los datos en el lcd
Lcdout #decimal, "C   "  'muestra los datos en el lcd
Return                                           
'________Argumentos de entrada dos variables tipo word, dividendo y divisor, argumento de salida una variable tipo long
Function dvsion_dcmles(dvdo As Word, dvsor As Word) As Long  '________Rutina funcion division con decimales
Dim f_entera As Word  'variable local, contendra la parte entera
Dim f_resto As Word  'varable local, contendra el resto
Dim f_decimal As Word  'contendra la parte decimal
f_entera = dvdo / dvsor  'obtengo la division
f_resto = dvdo Mod dvsor  'obtengo el resto
f_decimal = (f_resto * 10) / dvsor  'calculo 1 decimal, para obtener 2 decimales multiplicar por 100
dvsion_dcmles.HW = f_entera  'almacena la parte entera en el word alto
dvsion_dcmles.LW = f_decimal  'almacena la parte decimal word bajo
'Recuerda que la parte decimal tiene que ser mostrada en el display con plantilla de dos digitos siempre
End Function                                     
'___________Calculo de la media aritmetica de la temperatura, 20 muestras
media_arit:
media_temp(media_indice) = temperatura  'asigna el valor
temperatura = 0  'se inicaliza a cero
For aux_media = 0 To 19  'blucle for, se ejecuta 20 veces
temperatura = temperatura + media_temp(aux_media)  'se suman los valores
Next aux_media  'cierra for
temperatura = temperatura / 20  'termina el calculo de la media
media_indice = media_indice + 1  'controla la entrada de datos que corresponde a media_temp(x)
If media_indice > 19 Then media_indice = 0  'acota el ultimo valor del indice de media_temp
Return                                           
'___________Calculo de la temperatura
temp_calculo:  'calculo de la temperatura y del signo de la misma
If adc_4 > 112 Then  'determina si la temperatura es superior a 0ºC
aux_adc_4 = adc_4  'asigna el valor del ra4 a la variable auxiliar
aux_adc_4 = aux_adc_4 - 112  'elimina de la temperatura la parte de la escala negativa
temp = (5000 * aux_adc_4) / 1023  'calcuala el valor de la temperatura sin coma decimal
signo = 0  'temperatura positiva
Endif
If adc_4 = 112 Then  'determina si la temperatura es 0ºC
temp = 0  'temperatura 0ºC
signo = 0  'asigna signo positivo
Endif
If adc_4 < 112 Then  'determina si la temperatura es inferior a 0ºC
aux_adc_4 = adc_4  'asigna el valor del RA4 a la variable auxiliar
aux_adc_4 = 112 - aux_adc_4  'elimina de la temperatura la parte de la escala negativa
temp = (5000 * aux_adc_4) / 1023  'calcuala el valor de la temperatura sin coma decimal
signo = 1  'asigna el simbolo menos a la temperatura
Endif
temperatura = temp  'se pasa de Long a Word
Return                                           
inicializa_temp:  '__________inicializa la media aritmetica de la temperatura en el arranque
Gosub lee_adc  'salto con retorno, rutina de lectura de la entrada ADC
Gosub temp_calculo  'salto con retorno, hace el calculo de la temperatura y guarda el valor en temperatura
For media_indice = 0 To 19  'indice para rocorrer todas las direcciones de memoria que forman la variable tipo array media_temp
media_temp(media_indice) = temperatura  'se de el valor a media_temp
Next media_indice  'terminacion del bucle For
media_indice = 0  'se inicializa a cero, para un uso posterior
Gosub media_arit  'salto con retorno, calcula la media aritmetica
division = dvsion_dcmles(temperatura, factor_escala)  'llama a la funcion dvsion_dcmles, que retorna un long
Return                                           
print_rs232_temperatura:  'Envia la temperatura con decimales al puerto serie
PIE1.TMR1IE = 0  'OFF, interrupciones del timer1
Hserout "TEMPERATURA: "  'pagina en blanco y literal al purto serie
If signo = 0 Then Hserout "+"  'muestra el signo de la temperatura
If signo = 1 Then Hserout "-"  'muestra el signo de la temperatura
Hserout #entero, ".", #decimal, " "  'temperatura al rs232
PIE1.TMR1IE = 1  'ON, interrupciones del timer1
Return                                           
print_rs232_date:  'rutina de escritura de la hora y fecha por el RS232
PIE1.TMR1IE = 0  'OFF, interrupciones del timer1
If reg(2) < 10 Then Hserout " 0"  'si horas es inferior a 10 escribe el cero delante
Hserout #reg(2), ":"  'escribe la hora
If reg(1) < 10 Then Hserout "0"  'si minutos es inferior a 10 escribe el cero delante
Hserout #reg(1), ":"  'escribe los minutos
If reg(0) < 10 Then Hserout "0"  'si segundos es inferior a 10 escribe el cero delante
Hserout #reg(0), " "  'escribe los segundos
If reg(3) = 1 Then Hserout "Dom."  'asigna el literal al dia de la semana
If reg(3) = 2 Then Hserout "Lun."
If reg(3) = 3 Then Hserout "Mar."
If reg(3) = 4 Then Hserout "Mie."
If reg(3) = 5 Then Hserout "Jue."
If reg(3) = 6 Then Hserout "Vie."
If reg(3) = 7 Then Hserout "Sab."
If reg(4) < 10 Then Hserout " 0"  'si dia del mes es inferior a 10 escribe cero
Hserout #reg(4), "/"  'escribe el dia del mes
If reg(5) < 10 Then Hserout "0"  'si mes es inferior a 10 escribe cero
Hserout #reg(5), "/20"  'escribe el mes
If reg(6) < 10 Then Hserout "0"  'si año es inferior a 10 escribe primero el cero
Hserout #reg(6), CrLf  'escribe el año
PIE1.TMR1IE = 1  'ON, interrupciones del timer1
Return                                           
pause_ms:  'rutina de espera, rutina tipo Waitms, pause establese el tiempo total en mSeg
pause = 1  'ESTA LINEA SOLO SE ACTIVA CUANDO SE UTILIZA EL SIMULADOR
PIE1.TMR1IE = 0  'OFF, interrupciones del timer1
timer_1ms_tiempo = pause  'valor a temporizar por timer_1ms
PIE1.TMR1IE = 1  'ON, interrupciones del timer1
timer_1ms = 0  'al borrar el contador se activa y comienza la cuenta de 1mSeg
While timer_1ms < pause  'tiempo en mSeg maximos a contar
Wend
Return                                           
'***********************************Interrupciones*****************************************************
On Interrupt  'Comienzan las rutinas de las interrupciones, desactiva las interrupciones
TMR1H = 0xf8  'recarga el contador del timer1 para que desborde pasado 1mSeg, byte alto
TMR1L = 0x30  'recarga el contador del timer1 para que desborde pasado 1mSeg, byte bajo
Save System  'Guarda los valores del sistema para poder reemprender el curso normal del programa
If PIR1.TMR1IF = 1 Then  'comprueba que la interrupcion del timer1 es activa
'_________________bases de tiempos
timer_base = timer_base + 1  'contador general
If timer_1ms < timer_1ms_tiempo Then timer_1ms = timer_1ms + 1  'contador para control de la rutina Pause
If timer1_ms < timer1_ms_tiempo Then timer1_ms = timer1_ms + 1  'contador
If timer2_ms < timer2_ms_tiempo Then timer2_ms = timer2_ms + 1  'contador
If timer3_ms < timer3_ms_tiempo Then timer3_ms = timer3_ms + 1  'contador
If timer_base >= timer_base_tiempo Then  'limita el timepo de ejecucion, cada timer_base_tiempo
If timer1_100ms < timer1_100ms_tiempo Then timer1_100ms = timer1_100ms + 1  'contador
If timer2_100ms < timer2_100ms_tiempo Then timer2_100ms = timer2_100ms + 1  'condtador
If timer3_100ms < timer3_100ms_tiempo Then timer3_100ms = timer3_100ms + 1  'contador
timer_base = 0  'reset a la base de tiempos
Endif  '________________fin bases de tiempos
PIR1.TMR1IF = 0  'borra el flag de salto del tmr1
Endif
'_________________Detecta tecla pulsada
If s1 = 0 And s1_on = 0 And timer1_ms >= timer1_ms_tiempo Then  'tecla S1
s1_on = 1  'la tecla fue pulsada
s2_on = 0  'la tecla s2 a pff
If s1 = 0 And s2 = 0 Then s2_on = 1  'S2
timer1_ms = 0  'tiempo entre pulsacion y pulsacion
Endif
If s2 = 0 And s2_on = 0 And timer3_ms >= timer3_ms_tiempo Then  'tecla s2
s2_on = 1  'la tecla fue pulsada
s1_on = 0  'la tecla s1 a off
If s1 = 0 And s2 = 0 Then s1_on = 1  'S1
timer3_ms = 0  'tiempo entre pulsacion y pulsacion
Endif
If s1 = 0 Then led_verde = 0  'mestra el estado de S1
If s2 = 0 Then led_amarillo = 0  'muestra el estado de S2
If s1 = 1 Then led_verde = 1  'mestra el estado de S1
If s2 = 1 Then led_amarillo = 1  'muestra el estado de S2
'________Fin detecta tecla pulsada
Resume  'activa las interrupciones y retorna el curso normal del programa, antes del salto
End

PD: 03/06/08
      I2CWrite sda, scl, 0xd0, x, x
      I2CRead sda, scl, 0xd1, x, x
      0xd0 = %11010000 => Seleccion del chip DS1307 y modo escritura
      0xd1 = %11010001 => Seleccion del chip DS1307 y modo lectura
      %1101000x (direccion de seleccion del chip %1101000) siendo "x" el bit indicador de Write/Read. Este bit menos significativo lo controla directamente la funcion I2CWrite y I2CRead, por lo que su valor
      es indiferente, la funcion I2CWrite lo pondra a valor "0" de forma automatica y al ser compilada tambien I2CRead lo colocara a 1.
« Última modificación: 02 de Junio de 2008, 20:14:53 por dogflu66 »
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #192 en: 26 de Mayo de 2007, 07:01:34 »
El uso de funciones para simular los modulos internos del PIC, facilita la tarea de la programacion pero cuando el programa se hace ya demasiado extenso y vemos como la memoria se agota, una solucion clara es utilizar un modulo interno del pic siempre que dispongamos del mismo.... el ahorro de memoria es considerable y tambien observaremos como nuestro codigo se acelera de una forma tambien considerable.  :wink:
Saludos desde Granada, España.

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5490
    • Electrónica Didacta
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #193 en: 26 de Mayo de 2007, 14:48:51 »
Que grandes avances haces amigo dogflu66  :-/ :-/ :-/

veré si puedo hacer arrancar la lcd con este simulador.

una de las bondades, es que puedes ver las instrucciones línea por línea en asm y cambiar la velocidad de simulación.

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #194 en: 27 de Mayo de 2007, 17:38:59 »
Este es otro ejemplo simple de como controlar un servomotor Futaba S3003.
Utilizo la función Waitus y WaitMs del compilador de Basic para conseguir los tiempos.

El problema que plantean estos tipos de programas es que si crecen en complejidad el periodo de la señal del servo tambien se agranda por lo que una vez salidos de la tolerancia permitida del servo tendremos que hacer mas pequeño el periodo para asi compensar el aumento de tamaño del programa.

Código: [Seleccionar]
'***************** PIC Entrenadora BASIC (PicEBasic)**********************
'NOMBRE: 16F88_Pic_EBasic_Ejemplo_14
'MICRO: PIC16F88
'FECHA/AUTOR: 05/07 - By COS, PSI v7.41
'Pprograma para practicar con servos y la declaracion WaitUs
'Periodo para la señal de control del servo 20mSeg. (50Hz)
'Duty Cycle max. 2300uSeg. (extremo derecha) y minimo 450uSeg. (extr. izquierda)
'Control de la posicion del servo mediante RA0 y RA1
'-----------------------------------------------------------------------------------------------
Define CONFIG = 0x2f50  'Configuración bits (Fuses)
Define CONFIG2 = 0x3ffc  'Configuración bits (Fuses)
Define CLOCK_FREQUENCY = 8  'Clock en Mhz
'Define SIMULATION_WAITMS_VALUE = 1  'Activar para simulación
'-------------------------------------------------------------------------------
AllDigital  'Todos los puertos como I/O
CMCON = 0x07  'Comparador a off
OSCCON = 0x7e  'Set intrc To 8mhz, se usara reloj interno a 8Mhz
TRISA = 0xff  'Puerto A como Entradas
TRISB = 0xff  'Puerto B como Entradas
TRISA.4 = 1  'Como entrada (RA4, adc)
TRISA.6 = 1  'Como entrada (RA6, tecla S1)
TRISA.5 = 1  'Como entrada (RA5, tecla S2)
TRISB.3 = 0  'Como salida
TRISB.7 = 0  'Como salida
TRISB.0 = 0  'Como salida
TRISB.4 = 0  'Como salida, control servo
PORTB.3 = 1  'Luz lcd a on (RB3)
PORTA.7 = 1  'Led amarillo a off, negado
PORTB.0 = 1  'Led verde a off, negado
'-------------------------------------------------------------------------------
Dim posicion As Word  'duty cycle, señal de control servo a on
Dim periodo As Word  'frecuencia de trabajo de la señal del servo
Dim resto As Word  'señal de control del servo que tiene que estar a OFF
'-------------------------------------------------------------------------------
periodo = 20000  'Periodo (50Hz) de la señal del servo, en uSeg.
posicion = 1350  'Posicion central, duty cycle, señal de control a ON, uSeg.
'-------------------------------------------------------------------------------
main:
If RA5 = 0 Then  '__________Nueva posicion (izquierda) y sus limites y tecla
If posicion > 450 Then posicion = posicion - 1
Endif  '__________________________________________
If RA6 = 0 Then  '___________Nueva posicion (derecha) y sus limites y tecla
If posicion < 2300 Then posicion = posicion + 1
Endif  '___________________________________________
Gosub pwm_servo  'Salto con retorno a la rutina generadora del PWM
Goto main
End                                               
pwm_servo:  '_____________Genera la señal PWM, para controlar el servo
High RB4  'Control del servo, parte a on
WaitUs posicion  'Duty cycle, señal del servo a ON, pausa absoluta y perdida de tiempo
Low RB4  'Control del servo, parte a off
resto = (periodo - posicion) / 1000  'Tiempo que la señal del servo tiene que estar a OFF
WaitMs resto  'Pausa absoluta y una perdida de tiempo total
Return                                           
« Última modificación: 20 de Junio de 2016, 10:41:13 por dogflu66 »
Saludos desde Granada, España.