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

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3495
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #195 en: 27 de Mayo de 2007, 17:40: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.



Claro Pedro, con este entorno de trabajo nunca termina uno de abandonar el Assembler... :mrgreen:
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3495
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #196 en: 02 de Junio de 2007, 06:18:22 »
Para mis amigos dejo una version muy mejorada del bufer serie, ahora ocupa menos memoria y va mas rapido
el que quiera saber de los cambios tendra que investigar un poco comparando las versiones anteriores...  :mrgreen:

Código: [Seleccionar]
   '********************************** PIC Entrenadora BASIC *********************************
'NOMBRE: 16F88_Pic_EBasic_LCD_RS232_13
'VERSION: 1.3
'MICRO: PIC16F88
'Fecha/Autor: 1/07, 4/07, 5/7, 6/7 By COS, PSI v7.41
'VERSION 1.3
'Se simplifica la rutina bufer de lectura del puerto serie fisico
'mejora en la precision en las bases de tiempos
'VERSION: 1.2
'modificacion de la rutina Pause_ms
'se baja el bufer del puerto serie a 80 caracteres, porque se aprecia un fallo esporadico de lectura
'se filtran solo los caracteres de control < 31 y "@", se igualan a "_"
'no se aprecia ninguna perdida esporadica de caracteres (ok)
'Version: 1.1
'Simplificacion y mejora de las rutinas
'eliminacion del tiempo de lectura entre byte y byte, ahora solo se lee si hay datos en el bufer
'VERSION: 1.0
'Descripcion: muestra en el display de 16x2, los caracteres recibidos por rs232 y envia otra cadena fija
'tiempo de lectura entre byte y byte del puerto serie 10mseg maximo si no hay datos
'Baudios 4800, 8n1
'************************************************************************************************
Define CONF_WORD = 0x2f50  'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc  'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8  'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1  'Hace que se ignoren los tiempos de los WaitMs
'Puertos del LCD -------------------------------------------------------------------------------------------
Define LCD_BITS = 4  'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA  'Bus de datos sera el puerto A
Define LCD_DBIT = 0  'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB  'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7  'RB7 como RS
Define LCD_EREG = PORTB  'Bit de control E sera del puerto B
Define LCD_EBIT = 6  'RB6 como E
Define LCD_COMMANDUS = 2000  'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50  'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50  'Tiempo de espera despues de inicializar el Display.
'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 TMER1 -------------------------------------------------------------------------------------------------
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
'Bit interrupciones
PIE1.TMR1IE = 1  'Permete las interrupciones del timer1
PIE1.RCIE = 1  'Permte la interrupcion de la uart en modo rx
INTCON.PEIE = 1  'Bit de habilitacion de interrupciones de perifericos
'--------------------------------------------------------------------------------------------------------------------
Lcdinit  'inicializa el LCD sin cursor
Hseropen 4800  'Configura puerto serie
'--------------------------------------Reasignacion de nombres-----------------------------------------
Symbol led_amarillo = PORTA.7  'led amarillo
Symbol led_verde = PORTB.0  'led verde
'--------------------------------------Declaracion DE VARIABLES-------------------------------------
'Variables subrutinas del puerto serie ----------------------------------------------------------------
Dim assi As Byte  'Contiene el valor de lectura del puerto serie
Dim n_uart As Byte  'Numero de datos del uart y del bufer IMAGEN de control
Dim uart As Byte  'Variable indice que apunta al ultimo dato adquirido por la uart
Dim c_serial As Byte  'Como uart pero para la lectura de control del bufer IMAGEN
Dim bufer As Byte  'Indica si hay datos por leer en el bufer uart
'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_1ms_tiempo As Word  'contiene el valor del tiempo del timer_1ms
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 en 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 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--------------------------------------------------
'Variables rutina muestra datos en el LCD
Dim n As Byte  'se utiliza para posicionar caracter en el lcd
Dim flag As Byte  'controla la alternancia para imprimir en el lcd el caracter "(" o el ")"
Dim flag_1 As Byte  'controla la alternacia entre secuencia 1 y 2, tramas tx
'Variables tipo array puerto serie ------------------------------------------------------------------------
Dim uart_imagen(80) As Byte  'Componen el bufer IMAGEN para control del bufer UART
Dim uart_bufer(80) As Byte  'Componen el bufer de la UART de bajo nivel
'Asigna valores a las bases de tiempos del TIMER1-----------------------------------------------
timer_base = 0
aux_pause = 0
pause = 0
timer_1ms = 0
timer1_ms = 0
timer2_ms = 0
timer3_ms = 0
timer1_100ms = 0
timer2_100ms = 0
timer3_100ms = 0
timer_base_tiempo = 100  'cuenta 100mSeg
timer1_ms_tiempo = 5  'cuenta 5mSeg.
timer2_ms_tiempo = 100  'cuenta 0.1Seg
timer3_ms_tiempo = 100  'cuenta 0.1Seg
timer1_100ms_tiempo = 10  'cuenta 1Seg.
timer2_100ms_tiempo = 5  'temporiza 0.5Seg
timer3_100ms_tiempo = 5  'temporiza 0.5seg
'Asigna valores a las variables de la rutina del puerto serie----------------
uart = 0
c_serial = 0
bufer = 0
n_uart = 79
assi = 0
'Asignacion de valores generales ------------------------------------------------
n = 0
flag = 0
flag_1 = 0
'----------------------------------------------------------------------------------------------
Enable  'INTCON.GIE habilita todas las interrupciones globales
Gosub clear_bufer  'Inicializa el Buffer RS232, OBLIGATORIO POR LO MENOS UNA VEZ
pause = 1000  'prepara una pausa de 1Seg
Gosub pause_ms  'espera el tiempo que indica pause
Lcdout "18F88_LCD_RS232"  'imprime en el LCD el literal
Lcdcmdout LcdLine2Home  'selecciona linea y cursor al principio
Lcdout "RS232-4800Baud."  'escribe la cadena de literales en el lcd
Hserout CrLf, CrLf, "VER. 1.0 - TX/RX", CrLf, "TX -> PRUEBAS RS232", CrLf, "By COS", CrLf, CrLf  'envia presentacion al RS232
pause = 3000  'prepara una pausa de 3Seg
Gosub pause_ms  'hace una pausa de tiempo indicado por pause
Lcdcmdout LcdClear  'borra el display
'--------------------------------------Bucle Main ------------------------------------------
main:
If timer2_100ms >= timer2_100ms_tiempo And flag_1 = 0 Then  'determina cuando emitir la secuencia_1
Gosub secuencia_1
timer2_100ms = 0
flag_1 = 1  'activa la alternancia entre secuencia_1 y la 2
Endif
If timer2_100ms >= timer2_100ms_tiempo And flag_1 = 1 Then  'determina cuando emitir la secuencia_2
Gosub secuencia_2
timer2_100ms = 0
flag_1 = 0  'activa la alternancia entre secuencia_1 y la 2
Endif
Gosub lcd_control
Goto main
End                                               
'--------------------------------------Subrutinas Programa-----------------------------------------------
secuencia_1:  'envia la trama por el puerto serie
Hserout "@Hola Amigos de TODOPIC", CrLf
Return                                           
secuencia_2:  'envia la trama por el puerto serie
Hserout "@Ejemplo de Trabajo con RS232", CrLf
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 bufer del puerto serie (assi)
If bufer > 0 Then  'si bufer tiene datos
assi = uart_bufer(c_serial)  'se lee el valor del bufer y se asigna assi
uart_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_uart Then c_serial = 0  'se verifica si se llego al final del bufer
If uart_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_uart  'se ejecuta tantas veces como variables tiene el bufer
uart_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
uart = 0
bufer = 0
assi = 0
'_________________________Borra el error del puerto serie fisico en Rx
RCSTA.OERR = 0
RCSTA.CREN = 0
RCSTA.CREN = 1
Return                                           
'Subrutina gestión interrupciones -----------------------------------------------------------------
On Interrupt  'desactiva las interrupciones
Save System  'Guarda los valores del sistema
'__Bases de tiempos
If PIR1.TMR1IF = 1 Then  'comprueba que la interrupcion la proboco el timer1
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
timer_base = timer_base + 1  'base patron
timer_1ms = timer_1ms + 1  'contador para control del timer_1ms
If timer1_ms < timer1_ms_tiempo Then timer1_ms = timer1_ms + 1  'contador para control del timer1_ms
If timer2_ms < timer2_ms_tiempo Then timer2_ms = timer2_ms + 1  'contador para control del timer2_ms
If timer3_ms < timer3_ms_tiempo Then timer3_ms = timer3_ms + 1  'contador para control del timer3_ms
If timer_base >= timer_base_tiempo Then  'usa la base patron para retrazar la rutina 100mSeg.
If timer1_100ms < timer1_100ms_tiempo Then timer1_100ms = timer1_100ms + 1  'contador para control...
If timer2_100ms < timer2_100ms_tiempo Then timer2_100ms = timer2_100ms + 1  'contador para control...
If timer3_100ms < timer3_100ms_tiempo Then timer3_100ms = timer3_100ms + 1  'contador para control...
timer_base = 0  'reset a la base timer
Endif
PIR1.TMR1IF = 0  'borra el bit de salto del timer1
Endif
'__Bufffer puerto serie
If PIR1.RCIF = 1 Then  'comprueba que es esta la interrupcion activa del modulo USART
If uart_imagen(uart) = 0 Then  'comprueba que la posicion esta vacia
uart_imagen(uart) = 1  'indica que hay dato en el bufer de entrada
bufer = 1  'indica que el bufer tine datos
Hserget uart_bufer(uart)  'carga el dato en el bufer
uart = uart + 1  'indica cual sera la posicion siguiente del bufer
If uart >= n_uart Then uart = 0  'comprueba el final del bufer y lo inicializa
Else
Hserget uart_bufer(n_uart)  'descarga la uart para que no se bloquee porque el bufer de entrada esta lleno
Endif
PIR1.RCIF = 0  'borra el bit de salto del Rx, esto ya lo hace de forma automatica Hserget
Endif
Resume  'activa las interrupciones y retorna al curso normal del programa antes del salto
lcd_control:  'rutina que imprime los valores recibidos por el puerto serie en el display
'parte 1 de la rutina, sincroniza e imprime los caracteres recibidos por el puerto serie
If bufer = 1 Then  'la rutina se ejecuta si hay datos en el bufer
timer1_100ms = 0  'hay datos hace reset al timer1_100ms
Gosub readserial  'salta a la rutina de lectura del bufer serie
If assi = "@" Then  'caracter de sincronismo de la trama
n = 0  'possicion del display
Lcdcmdout LcdClear  'borra el display y posiciona el cursor superior izquierda
Endif
n = n + 1  'incrementa la posicion para escribir el siguiente caracter en el display
If assi < 21 Or assi = "@" Then assi = 95  'filtra los caracteres a imprimir
Lcdout assi  'escribe el caracter del bufer en el display
If n = 16 Then  'detecta fin de la linea primera
Lcdcmdout LcdLine2Home  'situa el cursor al principio de la siguiente linea
Endif
If n >= 32 Then  'detecta fin de la segunda linea
n = 0  'inicializa la posicion del proximo caracter a imprimir en el display
Lcdcmdout LcdLine1Home  'a inicio de linea
Endif
Endif
'parte 2 de la rutina, cuando no se reciben datos imprime en el display "(" y ")" de forma alterna
If timer1_100ms >= timer1_100ms_tiempo Then  'produce un retrazo inicial a la ejecucion de la rutina
If bufer = 0 Then  'si no hay datos en el bufer
If timer1_ms >= timer1_ms_tiempo Then  'produce un retrazo cada vez que se intenta imprimir en el lcd
timer1_ms = 0  'resetea el timer1_ms para que cuente de nuevo
If flag = 0 Then  'produce la alternancia para escribir "("
n = n + 1
Lcdout "("
If n = 16 Then
Lcdcmdout LcdLine2Home
Endif
If n >= 32 Then
n = 0
flag = 1
Lcdcmdout LcdLine1Home
Endif
Endif
If flag = 1 Then  'produce la alternancia para escribir ")"
n = n + 1
Lcdout ")"
If n = 16 Then
Lcdcmdout LcdLine2Home
Endif
If n >= 32 Then
n = 0
flag = 0
Lcdcmdout LcdLine1Home
Endif
Endif
Endif
Endif
Endif
Return                                       
« Última modificación: 19 de Junio de 2016, 11:34:10 por dogflu66 »
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3495
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #197 en: 02 de Junio de 2007, 07:57:00 »
¿Por qué programo de esta manera?... será porque me gusta complicarme la vida....

¿Para qué crear una rutina especial "pause_ms" para las perdidas de tiempo "delay" y no utilizar las que suministra el Basic?
-Pues porque al utilizar las interrupciones en especial las bases de tiempos, "Waitms y Waitus" se ven afectadas, los tiempos asignados se les alargan.

¿Por qué utilizo siempre las interrupciones?
-Pues me permite asegurarme que ciertas rutinas ya sean para control de tiempo, control de periféricos exteriores o módulos internos del pic, estas no se verán afectadas por el crecimiento del programa.

¿Por qué no suelo utilizar la mayoría de las funciones de emulación por software que facilita el lenguaje?
-Pues porque son muy lentas y consumen mucha memoria comparadas con los módulos internos del pic, además se ven afectadas por las interrupciones.
Algunas que usan los módulos por hardware tampoco las utilizo por que son muy lentas ya que son genéricas y no hacen un uso muy optimizado del módulo.

¿Por qué en la mayoría de los casos solo utilizo estructuras simples?
-Porque de esta manera será más fácil migrar el programa a otro lenguaje y también es más fácil de modificar en el futuro.

¿Por qué el uso de las bases de tiempos?
-Permiten controlar las veces que se ejecutara una rutina por segundo. Por ejemplo: para que quiero que se ejecute la función del LCD de continuo con lo lenta que es, si con solo refrescar los datos cada 100mSeg. es suficiente, o con leer un teclado cada 50 o 60mSeg es suficiente.
« Última modificación: 11 de Diciembre de 2011, 17:28:31 por dogflu66 »
Saludos desde Granada, España.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18269
    • MicroPIC
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #198 en: 02 de Junio de 2007, 08:12:16 »
Tú te lo guisas y tú te lo comes. ¡Cualquiera se atreve a preguntarte!  :D

Desconectado aitopes

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5100
    • uControl
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #199 en: 02 de Junio de 2007, 11:16:08 »
Hola Carlos!

Es muy cierto lo que dices del WaitMs yWaitUs. Se "estiran" tanto, que en una ocasion para hacer una demora de 1 milisegundo segundo exacto (bueno....todo lo exacto que lo pude medir) tenia que hacer "WaitUs 945". Los otros 65 us se "perdian" por ahi. el micro era un 16f628a con el oscilador interno, pero seguramente el problema no era el oscilador, que solo debe derivar unos 3 o 4 us por segundo...

Esta excelente este hilo! :-/

Saludos!
Si cualquier habilidad que aprende un niño será obsoleta antes de que la use, entonces, ¿qué es lo que tiene que aprender? La respuesta es obvia:
La única habilidad competitiva a largo plazo es la habilidad para aprender
“. Seymour Papert

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3495
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #200 en: 02 de Junio de 2007, 21:40:46 »
Tú te lo guisas y tú te lo comes. ¡Cualquiera se atreve a preguntarte!  :D

"Killo que panzon de rei me dao", me alegro que tu pequeño accidente no afectara a tu buen humor...  :D :D :D :D

Cierto Ariel, con una buena distribucion del tiempo para controlar las rutinas en nuestros programas podremos conseguir autenticas maravillas con pocos megas de reloj.


PD: Waitms = Waitus = Pause = delay => Perdida de tiempo de CPU = KK
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3495
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #201 en: 09 de Junio de 2007, 15:47:53 »
Este es un antiguo ejemplo para controlar la iluminacion del LCD, empleando las bases de tiempos.
Ahora lo he modificado para que haga la misma funcion pero empleando el modulo CCP.
pasamos de tener 20 puntos de resolucion a tener 1024 puntos, contando el cero, utilizando el modulo interno del pic CCP.
la frecuencia que genera el modulo a 8Mhz de reloj y con la configuracion correspondiente es de 488Hz, que corresponde tambien con la realidad segun me indica mi frecuencimetro.

La puesta en marcha de este modulo desde el Basic es realmente sencilla, tan solo se inicializa el modulo con la declaracion "PWMON 1, 1", el primer parametro es el modulo a controlar, y el segundo nos indica el modo de funcionamiento que lo podemos ver en la tabla del manual. y con la segunda declaracion "PWMDUTY 1, duty" controlamos duty de la salida del modulo.

El programa:
Código: [Seleccionar]
'***************** Placa Entrenadora (PIC EBadic) ***************************************
'NOMBRE: 16F88_Pic_EBasic_LCD_Timer1_ADC_PWM_12
'MICRO: PIC16F88/8Mhz reloj interno
'Fecha/Autor: 1/07, 6/07 By COS, PSI v7.41
'Version: 1.2
'se elimina el control del PWM por bases de tiempos y se controla mediante el modulo CCP1
'Version: 1.1
'Se cambian los Lcdcmdout LcdClear por Lcdcmdout LcdLinexHome en la subrutina del display, print_lcd
'este cambio acelera la escritura en el display
'Se convierte en subrutina el calculo del PWM segun el valor leido del ADC, calculo_pwm
'Se cambian el orden de los saltos en las lineas acotadas por el timer3_100ms, en el main, esto hace que el valor
'leido de la entrada analogica se actualice con los valores del PWM en el mismo ciclo
'Version: 1.0
'Uso del LCD con bus de datos a 4Bit y sin pin de RW
'Activacion del Timer1 por rebose cada 1mSeg.
'implementacion de timer (bases de tiempos) por soft
'lectura de entrada analogica y conversion a voltaje con dos decimales
'Implementacion de PWM con periodo de 20mseg. para el control de la luz del lcd por medio de la entrada adc
'*********************************************************************************************
Define CONF_WORD = 0x2f50  'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc  'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8  'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1  'Hace que se ignoren los tiempos de los WaitMs
'Puertos del LCD-------------------------------------
Define LCD_BITS = 4  'Indicamos que el bus de datos del lcd sera de 4bit
Define LCD_DREG = PORTA  'Bus de datos sera el puerto A
Define LCD_DBIT = 0  'Bus de datos seran los 4 bit menos significativos del puerto A
Define LCD_RSREG = PORTB  'Bit de control RS sera del puerto B
Define LCD_RSBIT = 7  'RB7 como RS
Define LCD_EREG = PORTB  'Bit de control E sera del puerto B
Define LCD_EBIT = 6  'RB6 como E
Define LCD_COMMANDUS = 2000  'Tiempo de espera despues de ejecutar un comando del lcd en uSeg.
Define LCD_DATAUS = 50  'Tiempo de espera despues de enviar un dato al LCD en uSeg.
Define LCD_INITMS = 50  'Tiempo de espera despues de inicializar el Display.
'------------------------------------Definicion de puertos------------------------------------------
ANSEL = 0x00  'los pin I/O digitales
Define ADC_SAMPLEUS = 10  '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 (RA7), negado
PORTB.0 = 1  'led verde a off (RB0), negado
'------------------------------------Inicializacion del TMR1 ---------------------------------
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
PIE1.TMR1IE = 1  'activa las interrupciones del timer1
INTCON.PEIE = 1  'bit de habilitacion de interrupciones de perifericos
'------------------------------------------------------------------------------------------------------
Lcdinit  'inicializa el lcd sin cursor
'Asignación de nombres --------------------------------------------------------------------
Symbol led_amarillo = PORTA.7  'led amarillo
Symbol led_verde = PORTB.0  'led verde
Symbol luz_lcd = PORTB.3  'iluminacion del lcd
'Declaracion de variables-------------------------------------------------------------------
'************************************variables de los timer************************
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 en 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 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 del ADC y Rutina division-------------------
Dim adc_4 As Word  'contiene el valor de la entrada ADC
Dim num_1 As Word  'valor del adc y retorna la parte entera
Dim num_2 As Word  'factor de la escala y retorna el primer decimal
Dim num_3 As Word  'segundo decimal
Dim dvdo As Word  'dividendo operacion
Dim dvsor As Word  'divisor operacion
'-------------------------------Variables generales-----------------------------------------
Dim flag_1 As Byte  'determina si la luz del lcd estara a on o a off
Dim duty As Word  'contiene el tiempo a on de la iluminacion del lcd a 10bit
Dim resto_periodo As Word  'contine el tiempo a off de la iluminacion del lcd
'-------------------------------Asignacion de valores a las variables------------------
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  'cuenta 100mSeg
timer1_ms_tiempo = 1  'cuenta 1mSeg.
timer2_ms_tiempo = 19  'cuenta 19mSeg
timer3_ms_tiempo = 5  'cuenta 5mSeg
timer1_100ms_tiempo = 10  'cuenta 1 Seg.
timer2_100ms_tiempo = 20  'temporiza 2Seg
timer3_100ms_tiempo = 1  'temporiza 0.1seg
flag_1 = 0
adc_4 = 0
resto_periodo = 0
duty = 0
'-------------------------------------------------------------------------------------------------------------
Enable  'INTCON.GIE habilita todas las interrupciones globales
WaitMs 1000  'espera 1Seg, las interrupciones alargan este tiempo
Lcdout "LCD_Tmr1_ADC_PWM"  'escribe en el lcd
Lcdcmdout LcdLine2Home  'seleciona la linea dos como proxima para escritura
Lcdout "Pruebas con CCP"  'escribe en el lcd
WaitMs 3000  'espera 3Seg, las iterrupciones hacen este tiempo mas largo
Lcdcmdout LcdClear  'borra el display
PWMon 1, 1  'activa el modulo CCP1, a 10bit, 488Hz y duty cycle 0
'------------------------------------Rutinas Principal----------------------
main:  'comienza el programa principal
If timer1_100ms >= timer1_100ms_tiempo Then  'cambio de estado el pin RA7 cada timer1_100ms_tiempo
Toggle led_amarillo  'invierte el valor del pin
timer1_100ms = 0  'reinicio el timer1_100ms
Endif
If timer2_100ms >= timer2_100ms_tiempo Then  'cambio de estado el pin RB0 cada timer2_100ms_tiempo
Toggle led_verde  'invierte el valor del pin
timer2_100ms = 0  'reinicio el timer2_100ms
Endif
If timer3_100ms >= timer3_100ms_tiempo Then  'permite que se ejecute las rutinas solo una vez cada timer3_100ms_tiempo
Gosub lee_adc  'salto con retorno, rutina de lectura de la entrada ADC
Gosub division_dos_decimales  'salto con retorno, rutina de conversion de valor adc a voltios
Gosub calculo_pwm  'salto con retorno, rutina de calculo de tiempos del PWM
Gosub print_lcd  'salto con retorno, rutina que imprime los valores en el lcd
timer3_100ms = 0  'reset a la base de tiempos
Endif
PWMduty 1, duty  'mantiene el duty cycle del modulo ccp
Goto main  'impide que termine el programa principal
End  'Fin main                                   
'--------------------------------------Subrutina lectura ADC, division y LCD
lee_adc:  '_______________________lee la entrada analogica
Adcin 4, adc_4  'lee el valor de la entrada analogica y lo carga en adc_4
num_1 = adc_4  'sede el valor del adc para ser procesado
num_2 = 205  'asigna factor de correccion, para 5V
Return                                           
division_dos_decimales:  '________Rutina division con dos decimales y conversion a voltios
dvdo = num_1  'asigna dividendo
dvsor = num_2  'asigna divisor
If dvdo > dvsor Then  'calcula la parte entera
num_1 = dvdo / dvsor
dvdo = dvdo Mod dvsor
Else
num_1 = 0
Endif
dvdo = dvdo * 10
If dvdo > dvsor Then  'extrae el primer decimal
num_2 = dvdo / dvsor
dvdo = dvdo Mod dvsor
Else
num_2 = 0
Endif
dvdo = dvdo * 10
If dvdo > dvsor Then  'extrae el segundo decimal
num_3 = dvdo / dvsor
Else
num_3 = 0
Endif
Return                                           
print_lcd:  '____________________muestra los datos por el display
Lcdcmdout LcdLine1Home  'cursor al principio, de la primera linea
Lcdout "ADC ", #adc_4, " ", #num_1, ".", #num_2, #num_3, "V", "    "  'muestra los datos en el lcd
Lcdcmdout LcdLine2Home  'cursor al principio de la segunda linea
Lcdout "On ", #duty, " Off ", #resto_periodo, "  "  'muestra los datos en el lcd
Return                                           
calculo_pwm:  '__________control de los tiempos del PWM segun el valor de adc_4
duty = adc_4  'controla el tiempo del PWM en estado alto
resto_periodo = 1023 - duty  'nos indica el tiempo del PWM en estado bajo
'___________________________________________________
Return                                           
'--------------------------------Interrupciones---------------------------------------------------
On Interrupt  'Comienzan las rutinas de las interrupciones, desactiva las interrupciones
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
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
'___base de tiempos
timer_base = timer_base + 1  'contador general
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 tiempo 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  'contador
If timer3_100ms < timer3_100ms_tiempo Then timer3_100ms = timer3_100ms + 1  'contador
timer_base = 0  'reset a la base de tiempos
Endif
'__fin base de tiempos
PIR1.TMR1IF = 0  'borra el flag de salto del tmr1
Endif
Resume  'activa las interrupciones y retorna al curso normal del programa antes del salto
« Última modificación: 19 de Junio de 2016, 11:06:49 por dogflu66 »
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3495
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #202 en: 09 de Junio de 2007, 15:50:27 »
El programa esta trucado para funcionar con el PSI
Los modulos a utilizar:
« Última modificación: 03 de Mayo de 2014, 15:52:40 por dogflu66 »
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3495
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #203 en: 09 de Junio de 2007, 16:00:55 »
PD. Proximamente veremos que registros del pic nos modifican estas dos declaraciones
      y de este modo veremos el funcionamiento del modulo CCP.
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3495
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #204 en: 10 de Junio de 2007, 03:17:33 »
Esta es la tabla que nos proporciona el manual del Pic Basic.
Para configurar el modulo interno CCP utilizando PWMON
Para trabajar como generador de PWM
Esta calculada para 4Mhz de reloj asi que con una simple regla de tres
Podemos saber a que frecuencias trabajara nuestro modulo CCP
Segun nuestra propia frecuencia de reloj.

TABLA PARA CONFIGURAR EL MODULO CCP CON PWMON CCPx, Mode
----------------------------------------------------------------------------------
mode 1: 10-bit, 244Hz
mode 2: 10-bit, 977Hz
mode 3: 10-bit, 3906Hz
mode 4: 9-bit, 488Hz
mode 5: 9-bit, 1953Hz
mode 6: 9-bit, 7813Hz
mode 7: 8-bit, 977Hz
mode 8: 8-bit, 3906Hz
mode 9: 8-bit, 15625Hz
mode 10: 7-bit, 1953Hz
mode 11: 7-bit, 7813Hz
mode 12: 7-bit, 31250Hz
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3495
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #205 en: 17 de Junio de 2007, 07:44:32 »
Hola de nuevo

Como habeis podido comprobar mi timer favorito es el Timer1, no solo porque es de 16bit, tambien porque hay funciones que utilizan modulos o los simulan, y se reservan el uso del timer0. El modulo CCP utiliza de forma automatica el Timer2.
Por ejemplo el WatchDog utiliza el timer0. Por todas estas cosas hay que leer con detalle el manual del compilador para ver si alguna de las funciones que vamos a utilizar ocupara un timer durante su ejecucion.

PD. Estoy trabajando en un ejemplo para utilizar el WatchDog.
PD. El modulo CCP trabajando en modo PWM no queda olvidado.


Otro PD. Tambien hay que leer el Data del micro que facilita el fabricante del mismo, porque el verdadero funcionamiento del micro y sus modulos lo tenemos en el (esta en ingles  :().
« Última modificación: 20 de Septiembre de 2008, 20:13:34 por dogflu66 »
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3495
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #206 en: 17 de Junio de 2007, 08:04:21 »
Ayuda a la Programacion:

Cuando estamos programando y el codigo fuente llega ya a una longitud aceptable y al ejecutarlo no hace lo que debiera, a un que siempre hara lo que escribimos  :mrgreen:, una forma de depurar el codigo es tener un elemento donde poder visualizar ciertos datos claves que nos pueden indicar donde cometimos el error, por ejemplo el valor de una variable o simplemente saber si el programa se queda en un bucle infinito al llegar a una rutina en particular. Todo esto lo podemos ver + o - facil con el simulador pero hay que tener en cuenta que como cualquier otro simulador ya sea mejor o peor, los simuladores fallan, puede que un programa funciones bien en el simulador y en la realidad no funcione y viceversa, asi que los simuladores son una buena herramienta pero hay que fiarse de ellos con cierta prudencia.
Bueno volviendo al tema inicial, es bueno tener alguna forma de ver ciertos datos o señalizadores que nosotros colocaremos en la parte sospechosa del programa para que nos indiquen que es lo que esta pasando, esto se hace si disponemos de un Display o mediante el encendido de una señal luminosa, normalmente led, o si no disponemos de esto y disponemos de un puerto RS232 enviando datos al hyperterminal del Windows o visor compatible.
« Última modificación: 17 de Junio de 2007, 08:08:45 por dogflu66 »
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3495
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #207 en: 17 de Junio de 2007, 15:28:48 »
Un ejemplo para el uso del WatchDog, el WatchDog es puesto a cero mediante el opcode clrwdt:

El modulo WatchDog (WDT), si es activado pone en marcha un contador interno programable que
al terminar de contar provoca un reset al microcontrolador, por lo tanto es un modulo supervisor
para controlar que el micro no está bloqueado, o fuera de la rutina principal del programa.
El programador tiene que asegurarse que coloca el reinicio del WDT en varios lugares
(los menos posibles en la rutina principal fundamentalmente) del programa antes que se
desborde su contador y provoque el reset.
Nunca se coloca la línea de código de reinicio del WDT en el vector de interrupciones.

El Pic16F88 tiene un modulo WatchDog (WDT) mejorado.
Este modulo WDT tiene un único reloj que es interno a 31250Hz.
Tiene un Prescaler y se le puede añadir un poscaler, este poscaler
puede ser asignado al WDT o al TMR0, no a los dos a la vez.
Este modulo WDT puede ser activado o apagado en tiempo de ejecución mediante un bit especial.

El programa de ejemplo hace:
Si se pulsa S1 o S2 se anula la línea que hace reset al WatchDog, esto provoca un reset a los 2048uSeg.
Activación del reset generado por el WatchDog sobre los 2mSeg.
Led con secuencia de parpadeo establecida, para observar el reset.
Se crea un tipo de pause (delay) que permite hacer reset al WDT durante la pausa.

Código: [Seleccionar]
''******************** PIC Entrenadora BASIC (PicEBasic)********************
'NOMBRE: 16F88_Pic_EBasic_Ejemplo_16
'MICRO: PIC16F88
'FECHA/AUTOR: 06/07 - By COS, PSI v7.41
'Practicando con el WatchDog (WDT)
'Si se pulsa S1 o S2 se anula la línea que hace reset al WatchDog.
'Activacion del reset generado por el WatchDog sobre los 2mSeg.
'Led con secuencia de parpadeo establecida, para observar el reset.
'Se crea un tipo de pause (delay) que permite hacer reset al WDT.
'Este modulo WDT tiene un único reloj que es interno a 31250Hz.
'Tiene un Prescaler y se le puede añadir un poscaler, este poscaler
'puede ser asignado al WDT o al TMR0, no a los dos a la vez.
'***********************************************************************************
Define CONFIG = 0x2f14  'Configuración de bits (fuses)
Define CONF_WORD_2 = 0x3ffc  'Configuración de bits (fuses)
Define CLOCK_FREQUENCY = 8  'Frecuencia del reloj en Mhz
'Define SIMULATION_WAITMS_VALUE = 1  'Hace que se ignoren los tiempos de los WaitMs
'---------------------------- Configuración del Clock, Puertos I/O -------------------
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, iluminación lcd
TRISA.7 = 0  'como salida, led amarillo
TRISB.0 = 0  'como salida, led verde
TRISB.4 = 0  'como salida, control servo
PORTB.3 = 1  'luz lcd a on (RB3)
PORTA.7 = 1  'led amarillo a off (RA7), negado
PORTB.0 = 1  'led verde a off (RB0), negado
'--------------------------- Configuración del WatchDog ------------------------------
'Prescaler del Wdt 31250Hz/64
WDTCON.WDTPS0 = 1  'Prescaler Rate Select bits 64 (2048uSeg)
WDTCON.WDTPS1 = 0
WDTCON.WDTPS2 = 0
WDTCON.WDTPS3 = 0
OPTION_REG.PSA = 0  'No asigna poscaler al WDT
'Declaración y Asignación de valores -----------------------------------------------
Dim watchdog_on As Bit  'permite que se haga el reset al contador del watchdog
Dim pause As Word  'asigna el valor de espera en mSeg.
watchdog_on = 1  'inicializa la variable, borrado del registro del watchdog a on
'--------------------------------------------------------------------------------------------------
Gosub clear_watchdog  'borra el contador del watchdog antes que rebose
RA7 = 0  'salida led amarillo
RB0 = 0  'salida led verde
pause = 5000  'carga la rutina de espera con 5 Seg.
Gosub wait_ms  'salto con retorno a la rutina de espera
'Bucle main
main:
RA7 = 1  'salida led amarillo
RB0 = 1  'salida led verde
pause = 500  'carga la rutina de espera con 0,5 Seg.
Gosub wait_ms  'salto con retorno a la rutina de espera
RB0 = 0  'salida led verde
pause = 500  'carga la rutina de espera con 0,5 Seg.
Gosub wait_ms  'salto con retorno a la rutina de espera
RA7 = 0  'salida led amarillo
pause = 500  'carga la rutina de espera con 0,5 Seg.
Gosub wait_ms  'salto con retorno a la rutina de espera
Goto main  'impide que termine la rutina main
End                                               
clear_watchdog:  'borra el contador del WatchDog
If watchdog_on = 0 Then Return  'determina si se hace el reset al WatchDog
ASM:        clrwdt  'reinicializa el WDT, assembler
Return                                           
wait_ms:  'rutina de espera, reset al WatchDog y lectura de las teclas
While pause > 0  'bucle que se repite mientras la condición sea cierta
If RA6 = 0 Or RA5 = 0 Then watchdog_on = 0  'lee las teclas
WaitMs 1  'espera 1 mSeg.
pause = pause - 1  'decrementa el tiempo de espera
Gosub clear_watchdog  'salto con retorno a la rutina
Wend  'acota el bucle While
Return     

PD. Este ejemplo no he logrado que funcione en el Simulador del PSI...  :(
« Última modificación: 19 de Junio de 2016, 12:57:00 por dogflu66 »
Saludos desde Granada, España.

Desconectado aitopes

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5100
    • uControl
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #208 en: 17 de Junio de 2007, 17:08:29 »
Hola amigo!

Todo realmente muy impresionante. Esta quedando un hilo estupendo! :-/
Felicitaciones  :mrgreen:
Si cualquier habilidad que aprende un niño será obsoleta antes de que la use, entonces, ¿qué es lo que tiene que aprender? La respuesta es obvia:
La única habilidad competitiva a largo plazo es la habilidad para aprender
“. Seymour Papert

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3495
Re: PIC BASIC del PIC Simulator IDE
« Respuesta #209 en: 17 de Junio de 2007, 19:22:45 »
Gracias Ariel, ya tengo un par de ejemplos mas, pero ahora toca ir a dormir.



Saludos desde Granada, España.