Curso de programación de PIC en PICBasic Pro

la idea es que pueda darle diferentes tiempos presionando el mismo pulsador
ejemplo;
* PRIMER TIEMPO mantengo presionado botón por un medio segundo y activa led_1 por 10 segundos si vuelvo a presionar el botón dentro de los 10 segundos le ordenare que se apague led_1 y si no es presionado el botón se apagara después de los 10 segundos automáticamente.

* SEGUNDO TIEMPO mantengo presionado botón por 2 segundos y activa led_1 por 1 minuto si dentro del minuto se vuelve a presionar el botón led_1 se apagara y si no es presionado el botón cumple el tiempo del minuto y el led_1 se apaga automáticamente.

* TERCER TIEMPO mantengo presionado el boton por 5 segundos y se activa led_1 por un tiempo de 2 horas si dentro de este tiempo de 2 horas se vuelve a presionar el boton led_1 se apaga y si no se presiona el boton led_1 se apagara automaticamente cuando se cumpla el tiempo adecuado amigo por favor he avanzado un poco del codigo pero aun no logro dar con el codigo o con la forma adecuada
Mira el programa que adjunto, tal vez te pueda servir como orientación para hacer lo que requieres.
No se utiliza un solo botón para determinar los periodos de retardo, pues eso puede ser muy complicado.
Se utiliza la interrupción por cambio de estado en los pines RB4 a RB7 para determinar que periodo establecer.
El programa cuenta con una rutina para periodos largos de tiempo que puedes utilizar en tu programa.

Como en todas las rutinas de retardo, una vez que el programa entra a la rutina, ya no sale hasta que se cumpla el tiempo establecido.
Por lo tanto el programa principal será retomado hasta que se cumpla la condición y retorne.

Si se puede apagar el LED presionando cualquier botón en RB4 a RB7 y volver a establecer el periodo, pero no se retomará el programa nuevamente hasta que se cumpla el conteo de la rutina.

Espero te sirva de algo este programa, o tal vez hasta lo puedas modificar para lograr tu objetivo.

Nota:
El programa lo escribí con MCS v5.0 y compilado con PBPX 3.0 porque necesitaba el archivo *.cof para realizar un debug al programa.
Sin embargo el código es compatible con versiones anteriores con solo cambiar la palabra de configuración.
La palabra de configuración para PBP 2.60 también está incluida en el programa por si se requiere.

Saludos.
 

Adjuntos

  • 16F628A Timers.rar
    43.6 KB · Visitas: 123
Última edición:
gracias amigo por tu respuesta y ayuda la idea de hacer los tiempos con un solo pulsador es porque hare activar 4 focos independientes cada uno con su pulsador y este pulsador con sus tiempos diferentes en ese caso como podria darle solucion
 
Saludos cesarim, el programa que adjunto D@rkbytes es perfectamente ajustable a lo que tienes pensado hacer.
Se utiliza la interrupción por cambio de estado en los pines RB4 a RB7 para determinar que periodo establecer.
El programa cuenta con una rutina para periodos largos de tiempo que puedes utilizar en tu programa.
Despues de eso lo que debes seleccionar es cual foco deseas encender con cada tiempo establecido.
Suerte!
 
Amigo desde ya muchas gracias por el codigo esta muy muy bueno pero lo que pretendo con esos tiempos es que sean con un mismo pulsador para activar un solo relay
Código:
Define OSC 4				; Definir que se trabajará con 4MHz.

; Declaración de variables.
Contador    Var Word
Flag        Var Bit
T1          Var Word
T2          Var Word

; Nombres para los pines.
Symbol LED_1    = PORTB.1

Inicio:
	CMCON = 7				; Comparadores analógicos OFF
	OPTION_REG.7 = 0		; Resistencias de Pull-Up en Puerto B
	TRISB = %11110000
	PORTB = TRISB
    Clear       ; Inicializar variables a 0
	
On Interrupt GoTo PORTB74_CHANGE
INTCON = $C8    ; %11001000 (Interrupción RB<7:4>)

Programa:
; Programa principal.
	Toggle PORTA.1
	Pause 80
	GoTo	Programa

Disable
PORTB74_CHANGE:
    INTCON.0 = 0    ; Limpiar flag por cambio de estado en RB<7:4>

    While PORTB.4 = 0   ; Mientras RB4 es 0...
        Pause 10
        Contador = Contador +1  ; Incrementar Contador cada 10Ms.
        If Contador = 50 Then   ; Si son 500 Ms...
        T2 = 10                 ; 10 segundos.
        LED_1 = 1               ; Enciende LED_1 por 10 segundos
        GoSub Retardo           ; Ir a Subrutina de retardo.
        EndIf
    Wend                        ; Termina el bucle.

    While PORTB.4 = 0        ; el mismo pulsador con un tiempo de 
        Pause 10
        Contador = Contador +1
        If Contador = 200 Then  ; dos segundos
        T2 = 60                 ; prende led_1 por 1 Minuto
        LED_1 = 1
        GoSub Retardo
        EndIf
    Wend

    While PORTB.4 = 0        ;el mismo pulasador con un tiempo de pulsado
        Pause 10
        Contador = Contador +1
        If Contador = 500 Then  ; de 5 segundos
        T2 = 7200               ; enciende led_1 por 2 Horas
        LED_1 = 1
        GoSub Retardo
        EndIf
    Wend
    
    While PORTB.4 = 0
        Pause 10
        Contador = Contador +1
        If Contador = 100 Then
        T2 = 1
        LED_1 = 1
        GoSub Retardo
        EndIf
    Wend

    Contador = 0
    
    If Flag Then            ; Si Flag es 1 es porque se activo el Retardo.
        Flag = 0            ; Se limpia la bandera.            
        LED_1 = 0           ; Apagar LED_1
    EndIf
    
    Resume                  ; Regresar al programa principal.
    Enable                  ; Habilitar nuevamente las interrupciones.
    
; Procedimiento para retardos largos de tiempo (Por D@rkbytes)
Retardo:
    T1 = 0                  ; Iniciar esta variable con el valor 0
    Flag = 1                ; Activar bandera de LED encendido
Aun_No:                     ; Etiqueta para realizar un bucle               
    T1 = T1 + 1             ; Incrementar T1
    Pause 1000              ; Pausar 1 segundo
    If T1 < T2 Then         ; Si la variable T1 es menor a la variable T2...
    GoTo Aun_No             ; Regresar a Aun_No
    Else                    ; Si es mayor sale del If
    LED_1 = 0               ; Apaga el LED (Fin del período)
    Flag = 0                ; Limpiar bandera de LED encendido
    EndIf                   ; Termina el If
    Return                  ; Regresa dentro de la interrupción
    
	End

y que se apague cuando se vuelva a presionar el pulsador asi no haya cumplido su tiempo programado
 
Hola compañeros estoy aún con lo del PWM, con respecto a sus limitaciones y sus ventajas, estoy realizando un ejemplo con un pic16f877A aun estoy en fases de diseño del programa para dar una idea para compararlo con respecto el PWM del pic y el PWM generado por interrupción cuando lo tenga listo lo comparto.

Por otro lado y para no saturarme con solo el PWM, con respeto a lo de el compañero cesarim estoy revisando el código algo complejo a mi parecer, creo se puede realizar con instrucciones mas simples y algoritmos menos complejos ahora estoy editando un código nuevo en base al código subido hoy mas tarde lo comparto, solo una pregunta. Por que toggle y por que no usas un simple = 1 para estar mas seguro de que sea eso lo que se cumpla. Lo digo por que colocas muchas veces IF variable THEN en ves de IF variable = 1 THEN, y toggle si es que deseas mantenerlo apagado por el mismo tiempo que encendido. Mas conveniente es si utilizas los flag como señalizadores o el mismo pin del led para saber si esta encendido o apagado y así saber como actuar en cada situación. Solo probé cambiando el toggle dentro de la interrupción por led = 0 y los IF variable = 1. Y empezó a dar mejor, de todas formas tienes muchas cosas que hiciste que hacen que sea difícil de entender y de ejecutar. Otra cosa que vi es que usas el PORTA.4 el cual debes de colocar una PULL-UP para que funciones de manera correcta. Los tiempos no se si realizaste los cálculos pero no veo configuración del TMR0 por lo que viendo tu configuración estamos hablando de 16 milisegundos con 384 useg por cada incremento de tu variable MAS_TIEMPO. Osea 16,384 x 61 = 0,999 segundos, Para el primer caso y ultimo se cumple el segundo dice 20 lo que indica que es 20seg. Al cumplirse en cualquier caso debes asegurar de volver a 0 el TMR0 y mas cuando estas desactivando el LED adicional solo activara el contador cuando se este activando alguno de los led y así hacerlo mas preciso. En conclusión voy a seguir por acá con el nuevo código y luego lo coloco saludos.

---------- Actualizado después de 2 horas ----------

Ya realicé el código esta funcionando para un solo led se modifico lo necesario para que funcionara lo mejor posible, parte del código me lo copie de un un código que realice hace unos años atrás para temporizar unas lavadoras por lo que es bien preciso. Ahora funciona de la siguiente manera.

Para iniciar se presiona el primer botón de izquierda a derecha, se mantiene presionado no mas de 200mSeg Ya que sobre pasa el valor de la variable y al pasar de 256 la variable retorna a 0.
Hay dos maneras de saber cuanto tiempo va a quedar encendido el led. Una es sonora con un beep se mantiene 10Seg con dos beep se mantiene 1 min y con 3 beep se mantiene 2 min es modificable en el código. La otra manera en revisando la memoria eeprom del pic la cual utilice como referencia para verificar el valor de la variable lo cual puede borrarse del código si no es necesario. Lo otro es duplicar las misma lineas de código para los demás botones y ya estaría listo...Cual quier cosa me avisas.

Mucho éxito :apreton: saludos.
 

Adjuntos

  • PULSADOR NUEVO COD.rar
    42 KB · Visitas: 91
Última edición por un moderador:
Hola amigo reyvilla te agradesco por el codigo esta muy muy bueno, en esta parte que activamos el boton se podria ponerle un pequeño antirrebote digo por si se le podria meter ruido en algun momento y si seria de esta manera o de que manera posible asegurarlo como para evitar que se active solo o talvez no sea necesario amigo
Código:
     if boton0 = 1  then
     pause 10
     if boton0 = 1 then
     while boton0  = 1
     I = I + 1
veo que guardas el el valor de I en la memoria del pic verdad
if boton0 = 1 then ;activo boton
WHILE boton0 = 1
I = I + 1
FOR AUX = 0 TO 1000 'ESTO ES IGUAL A PAUSE 10 OSEA 10MS
PAUSEUS 10
NEXT
WEND
WRITE 00,I
goto verifica
endif
como podria hacer si le quisiera agregar 1 o 2 pulsadores mas cada uno con su respectivo led y que funcione de la misma manera que el primer pulsador con el primer led. tendria que agregarle 2 variables mas o podria trabajar con la misma en este caso la I.
si para 2 min
Código:
     FLAG0 = 120 'PARA UN TIEMPO DE 2min 
     toggle led_0
     I = 0
     ENDIF
le das 120 segundos verdad podria darle por decir 3600 para una hora en una rutina y en otra rutina
Código:
     FLAG0 = 60 'PARA UN TIEMPO DE 1min
     toggle led_0
     I = 0
     ENDIF
darle 14400 que seria 4 horas o cuanto de maximo de tiempo le podria colocar a cada uno.
 
Última edición:
Hola lo del antirebote en este caso no hace falta en caso de ruido para eso estan las pull-down que son las resistencias que mantienen 0V en cada uno de los pulsadores. Lo de grabar el valor era para poder compara el tiempo de pulsación y el tiempo de encendido del led y esa parte la puedes borrar. Los otros pulsadores necesitarías generar su propia rutina en cada sub-rutina, ejemplo en el inicio cada botón tendría que tener su propia rutina de temporizacion lo que si se mantendria seria la variable de referencia I ya que esa se borra. Y efectivamente como indicas si colocas un valor de 3600seg es una hora. El valor máximo seria de 65535seg que es el valor máximo para una variable tipo word y si colocas otro contador pues puedes extenderlo mucho mas. Cualquier otra cosa me avisas saludos
 
Reyvilla como estas amigo se me complica un poco agregarle un pulsador podrias orientarme y decirme por favor en que parte del codigo me estoy equivocando ya que no trabaja como devberia de ser
Código:
    MAIN:
     IF BOTON0 = 1 THEN GOTO UNO
     IF BOTON1 = 1 THEN GOTO DOS
   GOTO MAIN   

   UNO:  
     if boton0 = 1 then    
      WHILE boton0 = 1
       I = I + 1
        FOR AUX = 0 TO 1000 'ESTO ES IGUAL A PAUSE 10 OSEA 10MS
         PAUSEUS 10
        NEXT
       WEND
      WRITE 00,I
     goto verifica      
    endif 
     
     if led_0 = 0 and led_1 = 0 and led_2 = 0 then
      goto UNO
     else
      goto temporiza
     endif       
    
     verifica:
       
       if i => 256 then
        i = 0
       goto UNO
      endif
     
       IF I <= 50  THEN 
        SOUND Trbuz,[110,5] 
         Trbuz = 0
         FLAG0 = 5 'PARA UN TIEMPO DE 10 SEG
        toggle led_0
       I = 0
      ENDIF
     
       IF I <= 150 and i > 50 THEN 
        for aux = 0 to 1
         SOUND Trbuz,[110,5]
          pause 300
         next
          Trbuz = 0
          FLAG0 = 10 'PARA UN TIEMPO DE 1min
         toggle led_0
        I = 0
       ENDIF
     
       IF I <= 200 and i > 150 THEN  
        for aux = 0 to 2
         SOUND Trbuz,[110,5]
          pause 300
         next 
        Trbuz = 0
        FLAG0 = 15 'PARA UN TIEMPO DE 2min 
       toggle led_0
      I = 0
     ENDIF  
     
     
   DOS:  
     if boton1 = 1 then    
      WHILE boton1 = 1
       I = I + 1
        FOR AUX = 0 TO 1000 'ESTO ES IGUAL A PAUSE 10 OSEA 10MS
         PAUSEUS 10
        NEXT
       WEND
      WRITE 00,I
     goto verifica1      
    endif 
     
     if led_1 = 0 and led_0 = 0 and led_2 = 0 then
      goto DOS
     else
      goto temporiza
     endif       
    
     verifica1:
       
       if i => 256 then
        i = 0
       goto DOS
      endif
     
       IF I <= 50  THEN 
        SOUND Trbuz,[110,5] 
         Trbuz = 0
         FLAG1 = 5 'PARA UN TIEMPO DE 10 SEG
        toggle led_1
       I = 0
      ENDIF
     
       IF I <= 150 and i > 50 THEN 
        for aux = 0 to 1
         SOUND Trbuz,[110,5]
          pause 300
         next
          Trbuz = 0
          FLAG1 = 10 'PARA PRUEBA 10 SEG
         toggle led_1
        I = 0
       ENDIF
     
       IF I <= 200 and i > 150 THEN  
        for aux = 0 to 2
         SOUND Trbuz,[110,5]
          pause 300
         next 
        Trbuz = 0
        FLAG1 = 15 'PARA UN TIEMPO DE 15 SEG PRUEBA
       toggle led_1
      I = 0
     ENDIF       
      
     
     temporiza:
     IF MILISEGUNDO => 78 THEN  '998.4 MILISEGUNDOS + 1.14 = 999.54 ML  = 1 SEG APORX.
     MILISEGUNDO = 0
     
     
     IF led_0 = 1 AND TLed1 < FLAG0 THEN
     TLed1 = TLed1 + 1
     ELSE
     TLed1  = 0
     FLAG0  = 0
     Led_0  = 0
     endif       
     GOTO UNO
     
     IF led_1 = 1 AND TLed2 < FLAG1 THEN
     TLed2 = TLed2 + 1
     ELSE
     TLed2  = 0
     FLAG1  = 0
     Led_1  = 0
     ENDIF 
     endif       
     GOTO DOS     
     
    Disable
    MI_INTERRUPCION:
    PAUSEUS 13   'DIFERENCIA EN TIEMPO 13 * 78 = 1014 US = 1.14 MILISEGUNDOS 
                 'EL VALOR DEL TMR0 ES DE 206 Y  EL DEL PREESCALER DE 256
                 'ESO DA UN VALOR DE 12800uSEG OSEA 12.8SEG
                 'ESO MULTIPLICADO POR 78, 12.8 * 78 = 998.4 PARA APROXIMARLO MAS
                 'SE COMPENSO CON UNA PAUSA DE 13uSEG POR CADA MILISEGUNDO
                 
    MILISEGUNDO = MILISEGUNDO + 1

    TMR0 = 206
    INTCON = %10100000
    Resume 'VUELVE DESDE DONDE FUE INTERRUNPIDA
    Enable 'INTERRUMPE DESPUES DE LA CABECERA SEGUN MANUAL PBP 

    END
como que se complica en algunos moementos o mejor dicho no prende ni apaga como deveria de ser que parte estoy fallando amigo
 
saludos amigo cesarim, viendo tu código puedo notar un error al momento en el que usas la instrucción for- next, y ademas lo usas varias veces e tu codigo; para explicarte mejor tu lo usas así :
Código:
FOR AUX = 0 TO 1000 'ESTO ES IGUAL A PAUSE 10 OSEA 10MS
         PAUSEUS 10
        NEXT
el error tuyo esta en que en la parte de "next" la forma correcta seria "next aux", y así sucesivamente a lo largo del código. Espero haberme echo entender saludos!
 
saludos amigo cesarim, viendo tu código puedo notar un error al momento en el que usas la instrucción for- next, y además lo usas varias veces en tu código; para explicarte mejor, tú lo usas así :
Código:
FOR AUX = 0 TO 1000 'ESTO ES IGUAL A PAUSE 10 OSEA 10MS
         PAUSEUS 10
        NEXT
El error tuyo está en que, en la parte de "next" la forma correcta sería "next aux", y así sucesivamente a lo largo del código. Espero haberme hecho entender, saludos!
Esto no responde la pregunta de cesarim, es una aclaración sobre el uso del bucle For... Next

Veamos un ejemplo:

For Conteo = Inicio To Final {Step {-1} Incremento}
{Instrucciones}
Next {Conteo}

Lo que se encuentra dentro de los corchetes es opcional.
No es necesario escribir la variable Conteo después de Next. PE: "Next Conteo"
El compilador asume por orden los bucles For... Next y genera errores cuando están en desorden las terminaciones Next dentro de bucles anidados.

Por lo tanto al compilar el programa se obtendrá el mismo efecto si se escribe de esta forma...

For Conteo = 1 To 10
High PORTB.1
Pause 100
Low PORTB.1
Pause 100
Next

Que de esta otra forma...

For Conteo = 1 To 10
High PORTB.1
Pause 100
Low PORTB.1
Pause 100
Next Conteo

Ó de esta otra...

For Conteo = 1 To 10 Step 1
High PORTB.1
Pause 100
Low PORTB.1
Pause 100
Next

Porque se asume que la variable Conteo deberá ser incrementada de 1 en 1 hasta que llegue a 10.

Como el código de cesarim carece de comentarios relevantes, es muy difícil entender que es lo que quiere hacer.
Y por lo tanto dar una solución a su problema también lo es.
Aparte únicamente se refiere a una sola persona para la resolución a su problema y con ello se pierde la oportunidad de que otras personas le puedan sugerir como en tu caso, alguna colaboración extra.

Normas del Foro 23) Es de mala educación referir una consulta a un solo miembro de la Comunidad.
Además de que te pierdes la posibilidad de que otros miembros te respondan.

Saludos.
 
Última edición:
saludos amigos del foro espero no interpreten mal mi ayuda a mi codigo, se me es muy dificil entrar por motivos de trabajo al foro ya que no tengo internet en casa. el codigo que generosamente ustedes me estan ayudando a resolver y a terminar para mi ejercicio va quedando como me ayudo nuestro amigo reyvilla, pero al ponerle otro boton con otro relay que trabaje con los mismos tiempos de pulsacion que el primer boton no me funciona y eh ahi donde pido su ayuda ya que me gustaria no solo adecuarle 2 botones cada uno con su respectivo relay sino adecuarlo a 4 botones o pulsadores cada uno con sus respectivos relays. espero me sepan disculpar si me exprese mal o si no supe pedir la ayuda adecuada

el problema que tengo radica aca creo yo y no se de que manera intentarle
Código:
  MAIN:
     IF BOTON0 = 1 THEN GOTO UNO ;aca le indico que lea boton0 si no esta presionado 
     IF BOTON1 = 1 THEN GOTO DOS ;entonces pase a leer boton1 y si detecta que se                                        
   GOTO MAIN   ;presiono cualquiera de estos dos entonces salta a su rutina adecuada
                     ;o si no sigue leyendo hasta que detecte el boton activado

   UNO:  
     if boton0 = 1 then    
      WHILE boton0 = 1
       I = I + 1
        FOR AUX = 0 TO 1000 'ESTO ES IGUAL A PAUSE 10 OSEA 10MS
         PAUSEUS 10
        NEXT
       WEND
      WRITE 00,I
     goto verifica      
    endif 
     
     if led_0 = 0 and led_1 = 0 and led_2 = 0 then
      goto UNO
     else
      goto temporiza
     endif       
    
     verifica:
       
       if i => 256 then
        i = 0
       goto UNO
      endif
     
       IF I <= 50  THEN 
        SOUND Trbuz,[110,5] 
         Trbuz = 0
         FLAG0 = 5 'PARA UN TIEMPO DE 10 SEG
        toggle led_0
       I = 0
      ENDIF
     
       IF I <= 150 and i > 50 THEN 
        for aux = 0 to 1
         SOUND Trbuz,[110,5]
          pause 300
         next
          Trbuz = 0
          FLAG0 = 10 'PARA UN TIEMPO DE 1min
         toggle led_0
        I = 0
       ENDIF
     
       IF I <= 200 and i > 150 THEN  
        for aux = 0 to 2
         SOUND Trbuz,[110,5]
          pause 300
         next 
        Trbuz = 0
        FLAG0 = 15 'PARA UN TIEMPO DE 2min 
       toggle led_0
      I = 0
     ENDIF  
     
   ;el punto es que al pulsar un boton cualquiera de los dos se encienden los dos leds y no 
   ;deveria hacer eso deveria solamente prender un led y al activar el otro boton encender 
   ;el otro led es lo que me marea que manera adecuada podria hacerlo con dos o tres o hasta 
   ; cuatro pulsadores mas  
   DOS:  
     if boton1 = 1 then    
      WHILE boton1 = 1
       I = I + 1
        FOR AUX = 0 TO 1000 'ESTO ES IGUAL A PAUSE 10 OSEA 10MS
         PAUSEUS 10
        NEXT
       WEND
      WRITE 00,I
     goto verifica1      
    endif 
     
     if led_1 = 0 and led_0 = 0 and led_2 = 0 then
      goto DOS
     else
      goto temporiza
     endif       
    
     verifica1:
       
       if i => 256 then
        i = 0
       goto DOS
      endif
     
       IF I <= 50  THEN 
        SOUND Trbuz,[110,5] 
         Trbuz = 0
         FLAG1 = 5 'PARA UN TIEMPO DE 10 SEG
        toggle led_1
       I = 0
      ENDIF
     
       IF I <= 150 and i > 50 THEN 
        for aux = 0 to 1
         SOUND Trbuz,[110,5]
          pause 300
         next
          Trbuz = 0
          FLAG1 = 10 'PARA PRUEBA 10 SEG
         toggle led_1
        I = 0
       ENDIF
     
       IF I <= 200 and i > 150 THEN  
        for aux = 0 to 2
         SOUND Trbuz,[110,5]
          pause 300
         next 
        Trbuz = 0
        FLAG1 = 15 'PARA UN TIEMPO DE 15 SEG PRUEBA
       toggle led_1
      I = 0
     ENDIF       
      
     
     temporiza:
     IF MILISEGUNDO => 78 THEN  '998.4 MILISEGUNDOS + 1.14 = 999.54 ML  = 1 SEG APORX.
     MILISEGUNDO = 0
     
     
     IF led_0 = 1 AND TLed1 < FLAG0 THEN
     TLed1 = TLed1 + 1
     ELSE
     TLed1  = 0
     FLAG0  = 0
     Led_0  = 0
     endif       
     GOTO UNO
     
     IF led_1 = 1 AND TLed2 < FLAG1 THEN
     TLed2 = TLed2 + 1
     ELSE
     TLed2  = 0
     FLAG1  = 0
     Led_1  = 0
     ENDIF 
     endif       
     GOTO DOS     
     
    Disable
    MI_INTERRUPCION:
    PAUSEUS 13   'DIFERENCIA EN TIEMPO 13 * 78 = 1014 US = 1.14 MILISEGUNDOS 
                 'EL VALOR DEL TMR0 ES DE 206 Y  EL DEL PREESCALER DE 256
                 'ESO DA UN VALOR DE 12800uSEG OSEA 12.8SEG
                 'ESO MULTIPLICADO POR 78, 12.8 * 78 = 998.4 PARA APROXIMARLO MAS
                 'SE COMPENSO CON UNA PAUSA DE 13uSEG POR CADA MILISEGUNDO
                 
    MILISEGUNDO = MILISEGUNDO + 1

    TMR0 = 206
    INTCON = %10100000
    Resume 'VUELVE DESDE DONDE FUE INTERRUNPIDA
    Enable 'INTERRUMPE DESPUES DE LA CABECERA SEGUN MANUAL PBP 

    END
por favor espero su ayuda
 
Última edición:
buenas noches compañeros de foros de electrónica me podrían colaborar explicándome una parte de este código que publicaron en post del foro, hay parte del código que no la entiendo.

Código:
ADCON1 = %10000010  
TrisB  = %00000001
TrisC  = %00000000
TrisD  = %00000001
PortB  = %00000000
PortC  = %00000000


LPV     con 70    'Porcentaje minimo de bateria
LB      var word
adVal   var word					
aVal    var word		
aACC    var byte
L       var byte

Lcdout $fe, 1   				
Lcdout "Lubeck "			
Pause 50       		
aval=0

Inicio: 
 'Inserta tu codigo Aqui...
 gosub ACC	
 gosub adc
Goto inicio      				
End

ACC:
 if aacc<>portb.0 then                        ; en esta parte dicen que aacc no es igual a portb.0
   LCDOUT $FE,64                               ; cargan en en la memoria CG RAM
   LCDOUT $1F,$11,$1B,$E,$4,$4,$4,$4  ; mostrar el carácter personalizado de un enchufe 
   LCDOUT $A,$1F,$11,$1B,$E,$4,$4,$4
   LCDOUT $0,$A,$1F,$11,$1B,$E,$4,$4
   LCDOUT $0,$0,$A,$1F,$11,$1B,$E,$4
   LCDOUT $0,$0,$0,$A,$1F,$11,$1B,$E
   LCDOUT $0,$0,$0,$0,$A,$1F,$11,$1B
   LCDOUT $0,$0,$0,$0,$0,$A,$1F,$11
   LCDOUT $0,$0,$0,$0,$0,$0,$A,$1F
   if not PortB.0 then                         ; esta parte no la se expresar bien y no se lo que hace
    for L=7 to 0 step-1                        ; hace que se muestre el carácter como si estuviera 
     lcdout $FE,$8F,l                           ; desconectando de la luz.
     pause 50
    next L
   else                                             ; 
    for L=0 to 7
     lcdout $FE,$8F,l
     pause 50
    next L
   endif
   LCDOUT $FE,$8F,"E"
   pause 2000
  aacc=  portb.0   
 endif
return
 
ADC:
 ADCIN 0, adval			
 lb=(1024/100)*LPV;LB = 717
 L=(adval-lb)/((1024-lb)/7) 
 if aacc=0 or l+1<7 then			
  if aval<>adval then
   LCDOUT $FE,64 
   lcdout $0E,$11,$1B,$15,$1B,$11,$1F,$1F
   lcdout $0E,$11,$11,$11,$11,$11,$11,$1F
   lcdout $0E,$11,$11,$11,$11,$11,$1F,$1F
   lcdout $0E,$11,$11,$11,$11,$1F,$1F,$1F
   lcdout $0E,$11,$11,$11,$1F,$1F,$1F,$1F
   lcdout $0E,$11,$11,$1F,$1F,$1F,$1F,$1F
   lcdout $0E,$11,$1F,$1F,$1F,$1F,$1F,$1F
   lcdout $0E,$1F,$1F,$1F,$1F,$1F,$1F,$1F
   LCDOUT $FE,$8F,l+1
   pause 2000
  endif
 else  
  LCDOUT $FE,$8F,"C"
 endif 
 aval=adval		
Return
end

el archivo de proteus y el codigo estan en el post de Solo Ejemplos PICBASICPRO-PROTEUS UPS para microcontroladores. Estaría muy agradecido si me pudieran explicar bien el funcionamiento de este código ya que me serviría de mucho para el proyecto que quiero realizar.
Cordial saludo
 
hola buenas tardes. de antemano muchas gracias por la atención prestada.
pude instalar proteus 8, pbp v4, tengo un pic 16f84a y un lcd 16*2 ; mirando varios de todos los ejemplos aquí mostrados he hecho varias practicas pequeñas ya que no se nada de programación. pero tengo muchas ganas de aprender de todos ustedes.

En este primer programa mantengo presionado un pulsador y durante el tiempo que lo mantengo presionado el pulsador sale en pantalla un mensaje.

En el 2do programa, la idea es que al presionar 1 vez el pulsador, aparezca el mensaje, luego al presionar el pulsador por segunda vez, el mensaje desaparezca. No lo he podido lograr, una vez presionado el pulsador, sale un mensaje intermitente y el pulsador no responde mas. sin embargo lo coloco para que me ayuden, me corrijan y me expliquen

Programa 1
Código:
DEFINE LCD_DREG PORTA 'UTILIZAR 4 BITS DEL PUERTO A PARA TX DE DATOS
DEFINE LCD_DBIT 0     'DESDE EL BIT A.0 AL BIT A.3
DEFINE LCD_RSREG PORTA 'UTILIZAR EL REGISTRO  DE CONTROL/DATOS EN EL PUERTO A
DEFINE LCD_RSBIT 4    'EN EL BIT A.4
DEFINE LCD_EREG PORTB 'UTILIZAR EL ENABLE EN EL PUERTO B
DEFINE LCD_EBIT 3     'EN EL BIT B.3

TRISA=0  'ESTABLECER EL PUERTO A COMO SALIDA
TRISB=1 ; RB0,RB1 SON ENTRADAS
PAUSE 500 ' PAUSE DE MEDIO SEGUNDO

;CONFIGURACION DE ENTRADAS AL PIC 16F84a
Symbol PULSADOR = PORTB.0   ; BOTON DE AJUSTE PARA HORA


IF PULSADOR = 1 THEN
LCDOUT $FE, 1 ' LIMPIAR VISOR
LCDOUT $FE, 1, "HOLA" 'ESCRIBIR EN LA PRIMER LÍNEA
LCDOUT $FE, $C0, "ELECTRONICA" 'ESCRIBIR EN LA SEGUNDA LÍNEA
LCDOUT $FE, $0C                                        'APAGAR EL CURSOR
ENDIF

IF PULSADOR = 0 THEN
LCDOUT $FE, 1 ' LIMPIAR VISOR
ENDIF
Programa 2
Código:
DEFINE LCD_DREG PORTA 'UTILIZAR 4 BITS DEL PUERTO A PARA TX DE DATOS
DEFINE LCD_DBIT 0     'DESDE EL BIT A.0 AL BIT A.3
DEFINE LCD_RSREG PORTA 'UTILIZAR EL REGISTRO  DE CONTROL/DATOS EN EL PUERTO A
DEFINE LCD_RSBIT 4    'EN EL BIT A.4
DEFINE LCD_EREG PORTB  'UTILIZAR EL ENABLE EN EL PUERTO B
DEFINE LCD_EBIT 3     'EN EL BIT B.3

TRISA=0 'ESTABLECER EL PUERTO A COMO SALIDA
TRISB=1 ; RB0,RB1 SON ENTRADAS
PAUSE 500  ' PAUSE DE MEDIO SEGUNDO

;CONFIGURACION DE ENTRADAS AL PIC 16F84a
Symbol PULSADOR = PORTB.0   ; BOTON DE AJUSTE PARA HORA

CONTADOR VAR BYTE

INICIO: 

   IF PULSADOR  THEN
   CONTADOR = CONTADOR + 1 
   GOSUB AUMENTAR
   ENDIF
GOTO INICIO

AUMENTAR:

   IF CONTADOR = 1 THEN
   GOSUB PRENDER
   ENDIF
   IF CONTADOR = 2 THEN
   GOSUB APAGAR
   ENDIF
GOTO AUMENTAR

PRENDER:
   LCDOUT $FE, 1 ' LIMPIAR VISOR
   LCDOUT $FE, 1, "HOLA" 'ESCRIBIR EN LA PRIMER LÍNEA
   LCDOUT $FE, $C0, "ELECTRONICA" 'ESCRIBIR EN LA SEGUNDA LÍNEA
   LCDOUT $FE, $0C                                        'APAGAR EL CURSOR
GOTO AUMENTAR

APAGAR:
   LCDOUT $FE, 1 ' LIMPIAR VISOR
GOTO AUMENTAR
                                  
END
Muchas gracias por la atención prestada, disculpen la ignorancia pero por algo se empieza. ...
 
Última edición por un moderador:
hola jesusmolo porque no ensayas en la etiqueta apagar colocar la bandera contador otra vez en cero y en inicio en la parte de if pulsador colocale si pulsador=1 ó pulsador=0 segun como tengas el pulsador configurado si con resistencia pull-up ó pull-down.
 
En este primer programa mantengo presionado un pulsador y durante el tiempo que lo mantengo presionado el pulsador sale en pantalla un mensaje.

En el 2do programa, la idea es que al presionar 1 vez el pulsador, aparezca el mensaje, luego al presionar el pulsador por segunda vez, el mensaje desaparezca. No lo he podido lograr, una vez presionado el pulsador, sale un mensaje intermitente y el pulsador no responde mas. sin embargo lo coloco para que me ayuden, me corrijan y me expliquen
Para el programa 1 puedes hacerlo de esta forma:
Código:
Symbol Pulsador = PORTB.0

Inicio:
    LCDOut $FE,1        ; Inicializar la pantalla.
    
Programa:
    If Pulsador Then                ; Si Pulsador = 1
    While Pulsador                  ; Mientras Pulsador = 1
    LCDOut $FE,$80,"HOLA"           ; Escribir en línea 1
    LCDOut $FE,$C0,"ELECTRONICA"    ; Escribir en línea 2
    Pause 100
    Wend                            ; Pulsador ahora está en 0
    LCDOut $FE,1                    ; Limpiar la pantalla
    EndIf
    GoTo Programa
Para el segundo programa de esta otra forma:
Código:
Symbol Pulsador = PORTB.0

; Declaración de variables.
B0          Var Byte
Contador    Var Byte

Inicio:
    LCDOut $FE,1        ; Inicializar la pantalla.
    Clear               ; Limpiar variables.
    
Programa:
    Button Pulsador,1,255,255,B0,0,Programa
    Contador = Contador + 1         ; Incrementar Contador
    If Contador = 1 Then            ; Si Contador llegó a 1...
    LCDOut $FE,$80,"HOLA"           ; Escribir en línea 1
    LCDOut $FE,$C0,"ELECTRONICA"    ; Escribir en línea 2
    Pause 100
    Else                            ; Si es superior a 1...
    LCDOut $FE,1                    ; Borrar la pantalla.
    Contador = 0                    ; Regresar Contador a 0
    EndIf
    GoTo Programa
    
    End
Nota que estás usando el pin RA4 para el pin RS de la pantalla y el pin RA4 es con drenador abierto.
Para utilizar ese pin y obtener los dos estados lógicos que se requieren, debes colocar una resistencia Pull-Up.

Adjunto los códigos y la simulación por si requieres saber la conexión.

Saludos.
 

Adjuntos

  • Programas 1 y 2.rar
    21.4 KB · Visitas: 68
hola jesusmolo porque no ensayas en la etiqueta apagar colocar la bandera contador otra vez en cero y en inicio en la parte de if pulsador colocale si pulsador=1 ó pulsador=0 según como tengas el pulsador configurado si con resistencia pull-up ó pull-down.

hola juancaca, de antemano gracias por tu pronta respuesta, te comento que siguiendo tus indicaciones o corrígeme si me equivoque en algo, hice lo siguiente:

Código:
DEFINE LCD_DREG PORTA 'UTILIZAR 4 BITS DEL PUERTO A PARA TX DE DATOS
DEFINE LCD_DBIT 0     'DESDE EL BIT A.0 AL BIT A.3
DEFINE LCD_RSREG PORTA 'UTILIZAR EL REGISTRO  DE CONTROL/DATOS EN EL PUERTO A
DEFINE LCD_RSBIT 4    'EN EL BIT A.4
DEFINE LCD_EREG PORTB  'UTILIZAR EL ENABLE EN EL PUERTO B
DEFINE LCD_EBIT 3     'EN EL BIT B.3

TRISA=0 'ESTABLECER EL PUERTO A COMO SALIDA
TRISB=1 ; RB0,RB1 SON ENTRADAS
PAUSE 500  ' PAUSE DE MEDIO SEGUNDO

;CONFIGURACION DE ENTRADAS AL PIC 16F84a
Symbol PULSADOR = PORTB.0   ; BOTON DE AJUSTE PARA HORA

CONTADOR VAR BYTE

INICIO: 

   IF PULSADOR = 1  THEN
   CONTADOR = CONTADOR + 1 
   GOSUB AUMENTAR
   ENDIF
GOTO INICIO

AUMENTAR:

   IF CONTADOR = 1 THEN
   GOSUB PRENDER
   ENDIF
   IF CONTADOR = 2 THEN
   GOSUB APAGAR
   ENDIF
GOTO AUMENTAR

PRENDER:
   LCDOUT $FE, 1 ' LIMPIAR VISOR
   LCDOUT $FE, 1, "HOLA" 'ESCRIBIR EN LA PRIMER LÍNEA
   LCDOUT $FE, $C0, "ELECTRONICA" 'ESCRIBIR EN LA SEGUNDA LÍNEA
   LCDOUT $FE, $0C                                        'APAGAR EL CURSOR
GOTO AUMENTAR

APAGAR:
   CONTADOR = 0
   LCDOUT $FE, 1 ' LIMPIAR VISOR
GOTO AUMENTAR
                                  
END

La resistencia es PULL DOWN en PORTB.0, me sigue apareciendo el mensaje intermitente.
Probare ahora como me indica D@rkbytes y les comentaré.
De todas maneras muchas gracias juancaca por tu tiempo. (y)

Adjunto el diagrama en proteus.
 

Adjuntos

  • PULSADOR MENSAJE.png
    PULSADOR MENSAJE.png
    20.7 KB · Visitas: 47
Última edición por un moderador:
Para el programa 1 puedes hacerlo de esta forma:
Código:
Symbol Pulsador = PORTB.0

Inicio:
    LCDOut $FE,1        ; Inicializar la pantalla.
    
Programa:
    If Pulsador Then                ; Si Pulsador = 1
    While Pulsador                  ; Mientras Pulsador = 1
    LCDOut $FE,$80,"HOLA"           ; Escribir en línea 1
    LCDOut $FE,$C0,"ELECTRONICA"    ; Escribir en línea 2
    Pause 100
    Wend                            ; Pulsador ahora está en 0
    LCDOut $FE,1                    ; Limpiar la pantalla
    EndIf
    GoTo Programa
Para el segundo programa de esta otra forma:
Código:
Symbol Pulsador = PORTB.0

; Declaración de variables.
B0          Var Byte
Contador    Var Byte

Inicio:
    LCDOut $FE,1        ; Inicializar la pantalla.
    Clear               ; Limpiar variables.
    
Programa:
    Button Pulsador,1,255,255,B0,0,Programa
    Contador = Contador + 1         ; Incrementar Contador
    If Contador = 1 Then            ; Si Contador llegó a 1...
    LCDOut $FE,$80,"HOLA"           ; Escribir en línea 1
    LCDOut $FE,$C0,"ELECTRONICA"    ; Escribir en línea 2
    Pause 100
    Else                            ; Si es superior a 1...
    LCDOut $FE,1                    ; Borrar la pantalla.
    Contador = 0                    ; Regresar Contador a 0
    EndIf
    GoTo Programa
    
    End
Nota que estás usando el pin RA4 para el pin RS de la pantalla y el pin RA4 es con drenador abierto.
Para utilizar ese pin y obtener los dos estados lógicos que se requieren, debes colocar una resistencia Pull-Up.

Adjunto los códigos y la simulación por si requieres saber la conexión.

Saludos.

hola D@rkbytes buenas tardes, muchas gracias por tan pronta, corta y acertada respuesta, hermanazo :aplauso:, con respuestas como estas, haces que los que apenas empezamos y veiamos la programacion de pic como algo muy complejo; le tomemos empeño y ganas de seguir explorando. :apreton: :aplauso: (y)

si no es molestia me gustaria que me expliacaras 2 dudas que tengo:

1.- esta instruccion del 2do programa.

Button Pulsador,1,255,255,B0,0,Programa


2.- La funcion del pulsador de reset en el pin MCRL, del pic es borrar todo rastro de programa grabado, para poder grabar otros programas? o tiene otra funsión? es necesario colocarlo en todos los ejercicios que quiera hacer? o al momento que yo quiera montar el ejercicio fisicamente no lo coloco para no borrar por accidende el programa?

Nuevamente muchas gracias compañero. :apreton: :aplauso: (y)
 
hola juancaca, de antemano gracias por tu pronta respuesta, te comento que siguiendo tus indicaciones o corrígeme si me equivoque en algo, hice lo siguiente:

Código:
DEFINE LCD_DREG PORTA 'UTILIZAR 4 BITS DEL PUERTO A PARA TX DE DATOS
DEFINE LCD_DBIT 0     'DESDE EL BIT A.0 AL BIT A.3
DEFINE LCD_RSREG PORTA 'UTILIZAR EL REGISTRO  DE CONTROL/DATOS EN EL PUERTO A
DEFINE LCD_RSBIT 4    'EN EL BIT A.4
DEFINE LCD_EREG PORTB  'UTILIZAR EL ENABLE EN EL PUERTO B
DEFINE LCD_EBIT 3     'EN EL BIT B.3

TRISA=0 'ESTABLECER EL PUERTO A COMO SALIDA
TRISB=1 ; RB0,RB1 SON ENTRADAS
PAUSE 500  ' PAUSE DE MEDIO SEGUNDO

;CONFIGURACION DE ENTRADAS AL PIC 16F84a
Symbol PULSADOR = PORTB.0   ; BOTON DE AJUSTE PARA HORA

CONTADOR VAR BYTE

INICIO: 

   IF PULSADOR = 1  THEN
   CONTADOR = CONTADOR + 1 
   GOSUB AUMENTAR
   ENDIF
GOTO INICIO

AUMENTAR:

   IF CONTADOR = 1 THEN
   GOSUB PRENDER
   ENDIF
   IF CONTADOR = 2 THEN
   GOSUB APAGAR
   ENDIF
GOTO AUMENTAR

PRENDER:
   LCDOUT $FE, 1 ' LIMPIAR VISOR
   LCDOUT $FE, 1, "HOLA" 'ESCRIBIR EN LA PRIMER LÍNEA
   LCDOUT $FE, $C0, "ELECTRONICA" 'ESCRIBIR EN LA SEGUNDA LÍNEA
   LCDOUT $FE, $0C                                        'APAGAR EL CURSOR
GOTO AUMENTAR

APAGAR:
   CONTADOR = 0
   LCDOUT $FE, 1 ' LIMPIAR VISOR
GOTO AUMENTAR
                                  
END

La resistencia es PULL DOWN en PORTB.0, me sigue apareciendo el mensaje intermitente.
Probare ahora como me indica D@rkbytes y les comentaré.
De todas maneras muchas gracias juancaca por tu tiempo. (y)

Adjunto el diagrama en proteus.

hola jesusmolo mirando tu codigo le hice unas modificaciones y ya me funciona e hice otro muy parecido al de D@rkbytes y tambien funciona

codigo 1

Código:
INICIO: 

    IF PULSADOR = 1 THEN
        while pulsador=1
        wend
        pause 200
        CONTADOR = CONTADOR + 1 
        GOSUB AUMENTAR
    ENDIF
GOTO INICIO

AUMENTAR:

    IF CONTADOR = 1 THEN
        GOSUB PRENDER
    ENDIF
    IF CONTADOR = 2 THEN
        GOSUB APAGAR
    ENDIF
GOTO inicio

PRENDER:
    LCDOUT $FE, 1 ' LIMPIAR VISOR
    LCDOUT $FE, 1, "HOLA" 'ESCRIBIR EN LA PRIMER LÍNEA
    LCDOUT $FE, $C0, "ELECTRONICA" 'ESCRIBIR EN LA SEGUNDA LÍNEA
    'LCDOUT $FE, $0C 'APAGAR EL CURSOR
return 

APAGAR:
    
    CONTADOR = 0
    LCDOUT $FE, 1 ' LIMPIAR VISOR
return

END

codigo 2

Código:
INICIO: 

    IF PULSADOR = 1 THEN
        while pulsador=1
        wend
        pause 200
        CONTADOR = CONTADOR + 1 
        if contador=1 then
            LCDOUT $FE, 1 ' LIMPIAR VISOR
            LCDOUT $FE, 1, "HOLA" 'ESCRIBIR EN LA PRIMER LÍNEA
            LCDOUT $FE, $C0, "ELECTRONICA" 'ESCRIBIR EN LA SEGUNDA LÍNEA 
        else
            contador=2
            LCDOUT $FE, 1 ' LIMPIAR VISOR
            CONTADOR = 0
        endif    
    ENDIF
GOTO INICIO
end
espero te sirva
cordial saludo
 
Atrás
Arriba