Encendido de luz (semáforo) PIC16F88

Ok, gracias por la aclaración, ya mismo lo estoy implementando a ver qué passa con la AND :

if(input(PIN_B0) && input(PIN_B1) && input(PIN_B2)){ // Todas a '1' para cumplir AND
output_high(PIN_B3);
output_high(PIN_B4);
}else{ // De lo contrario, todas las salidas a cero.
output_low(PIN_B3);
output_low(PIN_B4);
}

pero también quiero hacer funciones lógicas que "si tienen en cuenta todos los niveles lógicos y activan salidas según las combinaciones de "0's" y "1's" por ejemplo : que tal si quiero que una salida se active a la combinación de las entradas A,B,Cy D con estas características:

A=0, B=1, C=1 ,D=0;

Mis problemas eran respectivamente: con la AND, fácilmente me enciende después de que pongo a uno sus tres entradas:
///////////////////////////////////////////
void main() {

set_tris_b(0x07);
disable_interrupts(GLOBAL);

do{

if (input (pin_b0)) // entrada 1
if (input (pin_b1)) // entrada 2
if (input(pin_b2)){ //entrada 3
output_high(pin_b3); //salida 1
output_high(pin_b4); //salida 2


}
} while(true);//bucle
}
///////////////////////////////////////

Pero no las baja cuando yo bajo alguna entrada.

Y la otra es, como implementar digamos una función lógica como esta, por ejemplo:

X(salida) = 1 cuando A(entrada)=0;B(entrada)=1;C(entrada)=1;D(entrada)=0; ó cuando
a=0;B=0;C=1;D=0;
Es todo, gracias por su paciencia y ayuda que seguro me dará luces.
 
Última edición:
Pero no las baja cuando yo bajo alguna entrada, se queda activa esa salida, quiero una que siga cambios de la condición AND.
Pero pones esto en alguna parte de tu código??:
Código:
[B]output_low[/B](pin_b3); //salida 1
[B]output_low[/B](pin_b4); //salida 2
de otro modo esas salidas nunca van a bajar cuando bajas una entrada.

Y la otra es, como implementar digamos una función lógica como esta, por ejemplo:

X(salida) = 1 cuando A(entrada)=0;B(entrada)=1;C(entrada)=1;D(entrada)= 0; ó cuando
a=0;B=0;C=1;D=0;
Ahí mismo está la respuesta...
La condición es que todo se cumpla para poner X(salida) = 1...
Código:
if(A==0 && B==0 && C==1 && D==0){ // Si todo se cumple, entonces
   X = 1;  // X = 1.
}
 
Última edición:
Pues, si eso creo tal cual me dijiste depues del

else{
output_low(pin_b3); //salida 1
output_low(pin_b4); //salida 2
} ah, y ya pruebo a ver cómo me va con la "función lógica".

Pero ¿qué tal esto?:

cuando las dejo todas en uno, no hay cambio, ayer si, pero al detener simulación y ponerlas en alto, antes de simular, al oprimir play (con las entradas ya en 1 ó 0) si cambia salida.

ok, ya quedó.Es que le quité el Do{} while(1); de repetir bucle, se lo puse otra vez y quedó oki doki, gracias y ya sigo con la función lógica.

Qué estés bien!
 
Última edición:
Hola aqui en medio de una emergencia por favor al tratar de meter el codigo usando winpic800 me sale este error
de escritura 0x000000 escrito: 0x3000 leido 0x0000
espero alguien me ayude con este problema
 
Bueno ya solucione el problema era el programador que estaba usando que no me servia en todo caso me solicitaron arreglar el problema de que realice de inmediato las instrucciones de cuando se presione mas de un boton asi que aqui me encuentro de nuevo a ver esta vez me dieron tiempo de hasta el martes pero entre más rapido salga de esto mejor... asi que a ver que hago, seguire tu sugerencia ByAxel luego te cuento como me fue
------------------------------------------------------------------------------------------------------------
segun lo comprendo lo que me pides es poner A0, A1, A2 en una misma variable llamada "tecla" segun tu codigo? o cada una de ellas la llamo distinto y repito el codigo
 
Última edición:
Hola. Encontré estas rutinas, pero la verdad no sé si estarán bien.

Código:
#include <p16f88.inc>

__CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC
                   
; Asignacion de variables utilizadas en demora   
CONT equ 0Ch
CONT2 equ 0Dh
CONT3 equ 0Eh
CONT4 equ 0Fh

ORG   0000h
bsf       STATUS,5         ; Cambiamos al banco 1Switch to Bank 1
            movlw     0000h              ; Ponemos los pines del puerto A ...
            movwf     TRISA            ; ...como salidas.
            bcf       STATUS,5         ; Volvemos al Banco 0.

LUZROJA    movlw     b'00000010'   ; Encendemos el LUZROJA poniendo primero el Valor, por 20 segundos.
            
movwf     PORTA
            call RETARDO
            

LUZAMARILLA    movlw     b'00000110'              ; Encendemos LUZROJA Y LUZ AMARILLA.
            movwf     PORTA
            call RETARDO1
            movlw b'00000000'
    

RETARDO ; Retardo de 20s
        movlw d'10'
        movwf CONT4;
CICLO4    movlw d'100'
        movwf CONT3
CICLO3    movlw d'98'
        movwf CONT2
CICLO2    movlw d'67'
        movwf CONT
CICLO    decfsz CONT,1
        goto CICLO
        decfsz CONT2,1
        goto CICLO2
        decfsz CONT3,1
        goto CICLO3
        decfsz CONT4,1
        goto CICLO4
        Return

RETARDO1; Reatardo de 5s
        movlw d'100'
        movwf CONT3
CICLO6    movlw d'100'
        movwf CONT2
CICLO5    movlw d'166'
        movwf CONT
CICL4    decfsz CONT,1
        goto CICLO4
        decfsz CONT2,1
        goto CICLO5
        decfsz CONT3,1
        goto CICLO6
        Return
END



Aquí está un diseño que estoy armando, pero la verdad no sé si estará bien.
 

Adjuntos

  • DISEÑO SEMAFORO DOBLE VIA.jpg
    DISEÑO SEMAFORO DOBLE VIA.jpg
    246.5 KB · Visitas: 13
Última edición por un moderador:
Esa no es la palabra de configuración correcta para ese PIC.
El PIC16F88 tiene dos secciones: 0x2007 y 0x2008
Estas dos direcciones corresponden respectivamente a; _CONFIG1 y _CONFIG2

Si quieres usar un cristal menor o igual a 4 MHz para el oscilador, puedes usar esta configuración:
PHP:
     __config    _CONFIG1, _XT_OSC & _LVP_OFF & _BOREN_OFF & _PWRTE_ON & _WDT_OFF
     __config    _CONFIG2, _IESO_OFF & _FCMEN_OFF
Para usar el oscilador interno:
PHP:
     __config    _CONFIG1, _FOSC_INTOSCIO & _LVP_OFF & _BOREN_OFF & _PWRTE_ON & _WDT_OFF
     __config    _CONFIG2, _IESO_OFF & _FCMEN_OFF
Y en el registro OSCCON estableces la frecuencia de operación.

También necesitas crear un bucle para realizar las rutinas del programa.
De otra forma, se ejecutarán consecutivamente todas las instrucciones hasta llegar a End, y ahí se detendrá el programa completamente.

Por ejemplo:
Código:
[COLOR=Purple]Inicio[/COLOR]
    [COLOR=Green]; Configuraciones[/COLOR]
[COLOR=Purple]Programa[/COLOR]
  [COLOR=Green] ; Rutinas[/COLOR]
   [COLOR=Blue]GoTo[/COLOR] Programa

[COLOR=Purple]Subrutinas[/COLOR]
   [COLOR=Green]; Código[/COLOR]
   [COLOR=Blue]Return[/COLOR]

    [COLOR=Blue]End[/COLOR]
Este PIC tiene conversores ADC y si quieres que funcione en modo digital, debes configurar el todo el registro ANSEL en 0.

Me parece que tienes que estudiar bastante antes de empezar a programar.
Lee la hoja de datos del PIC que vayas a usar y mira programas básicos de ejemplo.
 
¿Qué tal? Estoy haciendo un programa en el cual por cada pulso que va a A0 cambie de estado.
Pero creo que lo estoy haciendo mal porque no sé qué deba agregar para que permanezca B0 (luz verde) prendido esperando el siguiente pulso para pasar al B1(ambar) y luego al B2 (rojo) y regresar a todos apagados.

¿Alguna sugerencia? Aquí dejo mi código. Tengo muy poco en el lenguaje C.

PHP:
#include<16f628a.h>
#fuses INTRC_IO,NOWDT,NOLVP,MCLR,NOPROTECT
#use delay(clock=4000000)
#define puerto_b
#define puerto_a
#use fast_io(a)
#use fast_io(b)
  
void main()
{

set_tris_b(0x00);
set_tris_a(0x07);
output_b(0);




do{
output_low(PIN_B0);
output_low(PIN_B1);
output_low(PIN_B2);


if(input_state(PIN_A0)){
output_high(PIN_B0);
delay_ms(50);
}

if(input_state(PIN_A0)){
    output_low(PIN_B0);
    delay_ms(50);
    output_high(PIN_B1);
    delay_ms(50);
}

if(input_state(PIN_A0)){
    output_low(PIN_B1);
    delay_ms(50);
    output_high(PIN_B2);
    delay_ms(50);
}


}while(true);
}
 
Última edición por un moderador:
Hazlo con una selección "Instrucción Switch" y un contador.

Por ejemplo:
Código:
void semaforo (void)
{
    if(contador > x) contador = 0;
    contador++;
    switch (contador)
    {
        case 1: output_x(0b00000001);
        break;
        case 2: output_x(0b00000011);
        break;
        case 3: output_x(0b00000100);
    }
}
 
¿Qué tal?
Puse esto de código pero creo que está mal porque no inicia nada.
Si se compila pero no funcionó en el protoboard.
PHP:
#include<16f628a.h>
#fuses INTRC_IO,NOWDT,NOLVP,MCLR,NOPROTECT
#use delay(clock=4000000)
#define puerto_b
#define puerto_a

int contador=(PIN_A0);
int x;

void semaforo(void)
{

    if(contador > 3) contador = 0;
        contador++;
    switch (contador)
    {
        case 1: output_high(0b00000001);
        break;
        case 2: output_high(0b00000011);
        break;
        case 3: output_high(0b00000100);
    }
}

void main()
{

set_tris_b(0x00);
set_tris_a(0x03);
output_b(0);
semaforo();


}
 
Última edición por un moderador:
Que tal... tengo un nuevo programa para el proyecto que estoy haciendo... pero tiene unos detalles... Podrian checarlo?

*Cuando quiero pasar al modo 2... solo me permite entrar si presiono el boton 2 antes de terminar la secuencia de automatico (Y eso es solo a veces)
*Cuando estoy en el modo 2 y quiero avanzar de luz en luz... como que me da rebotes.. porque cambia de luz pero se regresa a la anterior... Si necesitan fotos de como lo tengo en proto me dicen y las subo.

Creo que esos son los errores que me esta dando.
Anexo el codigo aqui abajo... Saludos!!



Código:
#include <16f628a.h>          //PIC a utilizar
#fuses INTRC_IO,NOWDT,NOPROTECT,NOPUT       //ordenes para el programador
#use delay (clock=4000000) //Se usaran retardos tomando en cuenta que la frecuencia del
//oscilador es de 4Mhz
#use fast_io(a)         //Rápida entrada y salida
 
  
int Modo=1, Temp=1, i=0;  //Declaración de variables del tipo entero
 
//Prototipo de la funcion que configurara los puertos
void Config_Puertos(void);
//Funciones de interrupciones
#INT_EXT     //Para la interrupción INT (RB0)
void EXT_isr(void)
{
Modo++;
if(Modo==3)
{
Modo=1;
Temp=1;
}
}
 
#INT_RB       //Para la interrupción RB (RB4)
 
void RB_isr(void)
{
if(input(PIN_B4))
{
    Temp++;
delay_ms(150);
}
if(Modo==1 && Temp==2)
{
   delay_ms(150);
Temp=1;
delay_ms(150);
}
if(Modo==2 && Temp==4)
{
    delay_ms(150);
Temp=1;
delay_ms(150);
}
}
///Programa principal
 
void main(void)
{
Config_Puertos();//Llamado a funcion
while(true)
{
if(Modo==1)//Modo automatico
{
output_low(PIN_A2); //led verde off
output_low(PIN_A1); //led amarillo off
output_low(PIN_A0); //led rojo off
if(Temp==1)//Temporizacion 1
{
output_high(PIN_A2); //led verde on
delay_ms(6000);
output_low(PIN_A2); //led rojo off
for(i=0;i<=3;i++)
{
output_high(PIN_A2); //DESTELLO led verde on
delay_ms(500);
output_low(PIN_A2); //led verde off
delay_ms(500);
}
output_high(PIN_A1); //led ambar on
delay_ms(2000);
output_low(PIN_A1); //led ambar off
output_high(PIN_A0);//led rojo on
delay_ms(4000);
output_low(PIN_A0); //led rojo off
}
}

if(Modo==2)//Modo manual
{
while(Temp==1)
{
    
output_high(PIN_A2); //led verde on
output_low(PIN_A1); //led amarillo off
output_low(PIN_A0); //led rojo off
}
while(Temp==2)
{
    
output_low(PIN_A2); //led verde off
output_high(PIN_A1); //led amarillo on
output_low(PIN_A0); //led rojo off
}
while(Temp==3)
{
    
output_low(PIN_A2); //led verde off
output_low(PIN_A1); //led amarillo off
output_high(PIN_A0); //led rojo on
}
}
} //bucle infinito
}
 
 void Config_Puertos(void)
{
set_tris_A(0xF8); //portA como salidas(RA0, RA1 y RA2 ,las demas desactivadas)
set_tris_B(0xFF);
enable_interrupts(GLOBAL); //todas las interrupciones activadas
enable_interrupts(INT_EXT);//Habilitando interrupcion externa (RB0)
enable_interrupts(INT_RB);//Habilitando interrupciones de cambio de nivel (RB4-RB7)
ext_int_edge(H_TO_L);//Seleccionando flanco de interrupcion externa
output_low(PIN_A2); //led verde off
output_low(PIN_A1); //led amarillo off
output_low(PIN_A0); //led rojo off
Modo=1;
Temp=1;
}
 
Última edición por un moderador:
¿De qué forma podría quitar el rebote sin meterle los delays?

Consideraré la opción de empezarlo de 0. :rolleyes:

Pero si tienen consejos que me puedan dar, serían de mucha ayuda.

Gracias.
 
Última edición por un moderador:
Jajajaja el trilo-byte.

Mejor usa interrupciones. Te ahorras el problema de 2 o mas botones presionado. Y lee mi amigo, este foro es ya un ultimo recurso.
 
Pues sí, es que se le ayuda a quien tiene un código funcional o un hardware funcionando.

Pero este código está mal desde el inicio.
 
Última edición por un moderador:
Sí, mi código estaba mal desde el inicio.
Pensé en otro que aún no está al 100%, funciona pero tiene un detalle que tal vez es sencillo, pero no sé cómo corregir.
Cuando llega al case 4 se queda en ese, ya no sale cuando presiono el PIN_A1 (rutina)

El detalle de los rebotes lo adapte con un post que vi de D@arkbytes con una librería que él sugería.
Tengo poco en lenguaje C y entre lo que he leído y visto en esto foro, llegue a este código.

TRILO-BYTE: Éste código si funciona, hasta cierto punto. Jejeje.
PHP:
#include <16f628a.h>
#include <button.c>              //libreria donde esta la funcion rand(); 
#include <STDLIB.H>
#fuses   INTRC_IO,NOWDT,NOPROTECT
#use     delay(internal = 4MHz)
void main (void)
{
    int8 A2,A3,i,rutina,subrutina,avance,avance2=0;

    
   while (true)
   {
      output_b(0xFF);
     
        
      if (button(pin_a1,0,255,10,A2,1))       
          {    
          delay_ms(250);
          if(rutina>3){rutina=0;};
          rutina++;  
          } 
      
      if (button(pin_a0,0,255,10,A3,1))     
         {
          delay_ms(250);
          if(subrutina>2){subrutina=0;};
          subrutina++;
         }
 
                  switch(rutina){
                            case 1:
                                                             switch(subrutina){
                                                                             case 1:
                                                                                   output_low(PIN_B2); //ENCENDIDO VERDE
                                                                                   break;

                                                                             case 2:
                                                                                   output_low(PIN_B1);   //ENCENDIDO AMBAR
                                                                                   break;

                                                                             case 3:
                                                                                   output_low(PIN_B0);   //ENCENDIDO ROJO
                                                                                   break;
                                                                              }                                 
                                   break;

                            case 2:
                                   output_low(PIN_B2); //
                                   output_low(PIN_B0); //
                                 
                                                            
                                   break;

                            case 3:
                                   output_low(PIN_B1);  //
                                   output_low(PIN_B0);   // 
                                   break;
                                
                            case 4:
                                
                           
                                output_low(PIN_B2); //
                                   delay_ms(3000);
                                   output_high(PIN_B2); //
                                   
                                   for (i=0;i<=3;i++)   
                                   {
                                   output_low(PIN_B2); //
                                   delay_ms(500);
                                   output_high(PIN_B2); //
                                   delay_ms(500);
                                   }
       
                                   output_low(PIN_B1); //
                                   delay_ms(1500);
                                   output_high(PIN_B1); //
       
                                   output_low(PIN_B0); //
                                   delay_ms(3000);
                                   output_high(PIN_B0); //
                                   break;
                  
                  
                  
                                 }          
               
    }
}
 
Última edición por un moderador:
Es que ese código está MAL.

Lo que pasa, es que la librería del botón funciona, pero lo que estás haciendo mal es meter DELAY, eso te atora el micro 10 segundos y medio en el caso 4.

Atoras el micro sin hacer nada y obviamente no va a funcionar adecuadamente el código.
 
Última edición por un moderador:
Atrás
Arriba