PIC16F877A se activa solo sin esperar instrucciones

Saludos.

En este momento estoy aprendiendo a programar PIC en lenguaje C y me surge una novedad:
Cuando hago la programación en PIC C y luego hago la simulación en proteus, todo sale bien pero resulta que cuando hago el montaje en el protoboard, el PIC no espera las instrucciones y parte a ejecutar todas las acciones una por una ignorando las entradas.

Cabe acotar que me pasé por los do-while, if-else, while, modifiqué las configuraciones de entradas y salidas de varias maneras y el resultado fue el mismo.

Espero puedan ayudarme.
Adjunto uno de los programas que estoy montando para aprender este mundo de la automatización.
PHP:
#include <16f877a.h>
#fuses xt, nowdt
#use delay(clock=4000000)

#define p1        Pin_b0
#define p2        pin_b1
#define p3        pin_b2
#define blanco    pin_d7
#define rojo      pin_d6
#define amarillo  pin_d5
#define verde     pin_d4


void main()
{

set_tris_b(0xff);
set_tris_d(0x00);

output_d(0x00);
output_b(0x00);
 
while (true)
   {
      
      if(input(p1)==1)
      {
      output_high(blanco);
      delay_ms(2000);
      output_low(blanco);
      }

           
      if(input(p2)==1)
      {
      output_high(rojo);
      delay_ms(2000);
      output_low(rojo);
      }
      
      
      if(input(p3)==1)
      {
      output_high(blanco);
      delay_ms(700);
      output_low(blanco);
      output_high(rojo);
      delay_ms(700);
      output_low(rojo);
      output_high(amarillo);
      delay_ms(700);
      output_low(amarillo);
      output_high(verde);
      delay_ms(700);
      output_low(verde);
      }
   }
 
}
La idea es activar diferentes secuencias según el pulsador.
En este caso el PIC ejecuta una por una sin esperar alguna instrucción.

Agradecido por la ayuda que puedan suministrarme.
 
Última edición por un moderador:
¿Dónde está tu diagrama físico utilizado?


Gracias por responder.
Básicamente es el circuito mostrado más la alimentación en los respectivos pines vdd y vss, conexión en el Mclr con una resistencia de 10k, y el oscilador de 4M con sus condensadores. Del resto es como se muestra en la imagen.

Agradecido por la ayuda
 

Adjuntos

  • Sin título.jpg
    Sin título.jpg
    114.7 KB · Visitas: 38

D@rkbytes

Moderador
Te hace falta colocar resistencias pull-down en los pulsadores.

Al puerto B se le pueden activar resistencias pull-up internas.
Pero tendrías que cambiar las sentencias para que la orden se realice con 0

Por ejemplo:
Dentro del main...
port_b_pullups (true); // Activar las resistencias pull-up del puerto B.

Y para la comprobación de los pulsadores:
if (!input(PIN_XX)) // Actuar cuando el pin se encuentre en 0
{
// Código
}
 
Como dice Zero, el simulador considera que una entrada sin conectar tiene un potencial eléctrico 0, en la practica una entrada tiene un estado Z (alta impedancia), sin embargo alta no es lo mismo que infinita ni significa que tenga una carga 0, sino que esta es indeterminada y puede variar por la radiación externa o fugas internas que pueden polarizarlas, por eso nunca debes dejarlas desconectadas en la realidad.
 
Efectivamente sus comentarios me sirvieron de mucho. Luego de probar con varios valores de resistencia para colocarlas en Pull Down opte por una de 220Ω la cual me funcionó de maravilla. :aplauso::aplauso:

Luego probare cambiando la programación e incluir las resistencias internas.

""D@rkbytes""
""Nuyel""


Agradecido por su colaboración y disposición en entregar sus conocimiento abiertamente.

S.L.P.S.
 
Es mejor programarlo al revés y activar las resistencias de pullup y que el pulsador de ceros.
Es gratis.

Eso si, depende de más factores. Nada es blanco o negro.

 

D@rkbytes

Moderador
Efectivamente sus comentarios me sirvieron de mucho. Luego de probar con varios valores de resistencia para colocarlas en Pull Down opte por una de 220Ω la cual me funcionó de maravilla. :aplauso::aplauso:
Funcionará de maravilla, pero un valor de 220 Ω es muy bajo y resulta en un mayor consumo de corriente.
(I = V / R) = 5 / 220 = 22.7 mA.
Unos cuantos segundos presionando el botón, bastarán para que una resistencia de 1/4 W. empiece a calentarse.

Los valores para las resistencias pull up/down @ 5 V. son alrededor de 2.2 KΩ a 18 KΩ
Cuando las entradas son CMOS se pueden colocar valores más altos que en las entradas TTL.
 
Depende de si el pulsador está a 1cm o a varios metros del PIC y de lo ruidoso que sea el ambiente.
Cuanta mas impedancia, menos gasta y mas ruido entra, y viceversa.
 
A mi me ocurrio una cosa muy graciosa, matizo que por despiste,pero hasta que lo averigue no sabia el por que, explico: seme activaba la interrupcion RB0 y no veia el motivo, se activaba por que si.

El fallo era que se me olvido poner la resistencia que va a masa de 10k.

Aun asi no termino de entender el porque, la puse y perfecto.

Ya que estoy quiero hacer una pregunta sobre este tema, se puede activar la misma interrupcion desde distintas formas, quiero decir, ver de ahorrar interrupciones, esto lo digo por la falta de pines.
 
Última edición:

D@rkbytes

Moderador
Suena contradictorio que digas que no sabías el por qué, hasta que averiguaste, y luego menciones que aún no terminas de entender el por qué.

¿Cómo es eso de activar la misma interrupción desde distintas formas?
Hablas de la interrupción externa por RB0, pero. ¿A qué te refieres con ahorrar interrupciones por la falta de pines?
La verdad que no comprendí nada.
 
miglo dijo:
A mi me ocurrio una cosa muy graciosa, matizo que por despiste,pero hasta que lo averigue no sabia el por que, explico: seme activaba la interrupcion RB0 y no veia el motivo, se activaba por que si.

El fallo era que se me olvido poner la resistencia que va a masa de 10k.

Aun asi no termino de entender el porque, la puse y perfecto.

Ya que estoy quiero hacer una pregunta sobre este tema, se puede activar la misma interrupcion desde distintas formas, quiero decir, ver de ahorrar interrupciones, esto lo digo por la falta de pines.
Creo que se te mezclaron los cajones de manzanas con naranjas. Las interrupciones ocurren cuando el evento asociado a ella ocurre, de otra forma no puede ser activada, o sea, si activaste la interrupción por RB0, la única forma de hacer que esta se ejecute es que sobre el pin RB0 haya un cambio. Lo que te ocurría con tu interrupción era que, al no tener puesta la resistencia de pull-down, el pin RB0 quedaba en un estado de alta impedancia, o sea sobre el pin no había un valor de tensión digital definido, entonces en ese pin se generaba ruido eléctrico propio del medio ambiente que hacia disparar en forma erronea tu interrupción. Al poner esa resistencia de pull-down, estas estableciendo un valor bien definido de tensión sobre el pin (0V), lo cual hace que la interrupión no se dispare erroneamente.
 
Haber D@rbytes, la explicacion que da juanma2468 es lo que no sabia, ahora ya le veo el por que, nunca habia pensado lo de la alta impedacia.

Sobre lo de mezclar naranjas con manaznas creo que no, en todo caso no expresado bien al hacer la pregunta.

Ya se que la interrupcion RB0 se activa como se activa, y que en el puerto B estan tambien las RB4 a RB7, lo que queria decir es si por necesidad del puertoB, este se usa para el lcd, como se podria tener esa cantidad de interrupciones, hablamos de 5 interrupciones que no se pueden usar o eso creo yo al tener el puertoB ocupado para el lcd.
 
Si empleas un pin de interrupciones para otra cosa... pues ya no la tienes.

Hay formas de tener mas pines y mas interrupciones pero dejan de ser tan directas.
Por ejemplo hay expansores I2C que también controlan interrupciones por cualquiera de sus pines, en ese caso conectas el bus I2C y una línea de interrupción, cuando llegue tienes que ir al dispositivo I2C a averiguar quien la activó ya que esa interrupción se comparte por varios motivos.
 
Scooter creo que eso es lo que yo queria preguntar pero no sabia hacer la pregunta, donde puedo ver algun ejemplo de lo que has dicho?. Gracias
 

D@rkbytes

Moderador
Lo que quería decir, es si por necesidad del puerto B, este se usa para el lcd. ¿Cómo se podría tener esa cantidad de interrupciones?
Hablamos de 5 interrupciones que no se pueden usar, o eso creo yo al tener el puerto B ocupado para el lcd.
Una forma es usar RTOS, no con la misma prioridad de una interrupción, pero está basado en eso.
Otra manera sería usando un circuito dedicado. MCP23017/MCP23S17
 
Pues debería considerar que los expansores I2C y SPI igual ocupan un pin de interrupción asi que termina en el mismo punto si requiere el bus completo del Port B para el LCD, lo recomendable seria buscar una pantalla con interfaz serie en lugar de paralelo y asi dejar los pines para las interrupciones
 
Arriba