Autor Tema: Ayuda con configuración de puertos  (Leído 2662 veces)

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

Desconectado Thulsa Doom

  • PIC24F
  • *****
  • Mensajes: 771
    • https://electronicadicto.wordpress.com/
Ayuda con configuración de puertos
« en: 22 de Junio de 2010, 18:08:26 »
Hola a todos, tengo un problemilla en un proyecto que estoy haciendo, antes de nada he de decir que mis conocimientos en C son limitados pero poco a poco pretendo que eso no sea así, y haciendo un proyecto me he topado con un problemilla que me gustaría ver si me pueden echar una mano.

El pic que estoy empleando es el PIC16F876 y el puerto en cuestión donde quiero trabajar es el C,
el problema que tengo es que quiero utilizar el nibble de menor peso para que sea de entrada y lea el estado de unos interruptores y el nibble de mayor peso, sea de salida y me active unos led's dependiendo del estado en que se encuentre el micro y que sea independiente al otro nibble
Hasta ahí el planteamiento general, pues el problema que creo tengo es que no consigo que me lea los nibbles por separado y no me funciona, si elimino los led's, el programa me funciona pero me gustaría saber la forma de solucionar ese caso.

El compilador que utilizo es el CCS C.
Estoy utilizando la directiva #use standard_io
Y a continuación pongo parte del programa a ver si me pueden decir que estoy haciendo mal.



Código: [Seleccionar]
void alarma (){
            lcd_gotoxy(1,1);            //esta es la posición para que el mensaje          
            printf(lcd_putc, "ALARMA"); //funcione en el LCD correctamente            
            
            do{                     //Haz las sigueintes rutinas
             output_high(PIN_C6);
             output_high(PIN_C7);
             delay_ms(10);
             output_low(PIN_C7);
             delay_ms(10);              
             }
            while(PORTC!=0b00001000); // mientras PORTC no sea igual a 0b00001000  

Gracias por la ayuda

« Última modificación: 22 de Junio de 2010, 18:12:40 por Thulsa Doom »
Más códigos y desarrollos en https://electronicadicto.wordpress.com/ date una vuelta y curiosea un rato...

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Ayuda con configuración de puertos
« Respuesta #1 en: 22 de Junio de 2010, 21:20:24 »
No estoy programando en CCS pero trataré de ayudarte de todos modos.

Yo usaria Fast_io. El tris del puerto se lo configuraría con set_tris_c (0x0F) -creo que esa era la función-.
Y en cuanto a la lectura del puerto -en el while- haría una and con 0x0F para asegurarme que el nibble alto siempre lo tome como 0000. Digamos algo así ((PORTC & 0x0F) != 0b00001000);
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado Thulsa Doom

  • PIC24F
  • *****
  • Mensajes: 771
    • https://electronicadicto.wordpress.com/
Re: Ayuda con configuración de puertos
« Respuesta #2 en: 23 de Junio de 2010, 14:44:15 »
Vaya, te doy las gracias por tu ayuda, la verdad es que me ha servido, utilizando
Código: [Seleccionar]
while ((PORTC & 0x0f)!=0x05);Me ha funcionado, pero si utilizo la directiva fast_io no funciona, por lo que he dejado la directiva standard_io.

Si no te importa podrías explicarme como funciona while((PORTC & 0x0f)!=0x05);
Entiendo parte de la sentencia pero no se qué pasa al poner el AND (&).

Voy a colgar el proyecto que he hecho para que le echen un vistazo a ver si se puede mejorar y de qué manera.
de la forma que lo he hecho me funciona, lo que hay un pequeño detalle que no he conseguido arreglar, resulta que cuando está en el bucle de armado, el display parpadea una vez cada 30 o 40 segundos, he estado intentado corregirlo pero no he podido.

Sean comprensivos, es el primer proyecto que hago por mi cuenta



Código: [Seleccionar]

/*
A0 = 1º zona de control
A1 = 2º Zona de control

C0 = Interruptor para código
C1 = Interruptor para código
C2 = Interruptor para código
C3 = Interruptor para código

C5 = led verde
C6 = led rojo
C7 = zumbador, salida PWM
*/

#include <16f876.h>
#fuses XT,NOWDT,NOPROTECT
#use delay(clock = 4000000)
#define use_portb_lcd TRUE
#include <lcd.c>
#use standard_io (A)
#use standard_io (B)
#use standard_io (C)
#BYTE TRISC = 0x87
#BYTE PORTC = 0x07


//----------------------------------Rutina de alarma-----------------------------
void alarma(){
            lcd_gotoxy(1,1);                     //esta es la posición para que el mensaje          
            printf(lcd_putc, "   ALARMA");  //funcione en el LCD correctamente            
            
            do{                             //Haz las siguientes rutinas
             output_high(PIN_C6);           //Apagamos el led rojo
            
             output_high(PIN_C7);           //empieza la rutina de la señal PWM
             delay_ms(10);
             output_low(PIN_C7);
             delay_ms(10);                     //Finaliza la rutina de la señal PWM
             }
            while((PORTC & 0x0f)!=0b00001000); // sigue con el bucle mientras PORTC no sea igual a 0b00001000                
                
}
//-------------------------------Rutina de desactivación-----------------------------------


void desarmado(){
              
            lcd_gotoxy(1,1);                              //Seleccionamos la posición del mensaje  
            printf(lcd_putc, "   DESARMADO");    //Mensaje a desplegar en el LCD  

            do{                                  //Haz la siguiente rutina
            output_high(PIN_C5);                 //Enciende el led verde
            output_low(PIN_C6);                  //Apaga el led Rojo
            output_low(PIN_C7);                  //Desactiva el zumbador
            }
            while((PORTC & 0x0f)!=0b00000110);  //sigue con el bucle Mientras PORTC no sea = a 0x06
}
//-----------------------------Programa principal-------------------------------  
      
void main(){
      
        lcd_init();                                         //Funcion necesaria para que funcione el LCD
        
        
     while(TRUE){                                         //Mientras sea verdad
           lcd_gotoxy(1,1);                                 //Seleccionamos la posición del mensaje
           printf(lcd_putc, "\f    ARMADO");          //Mensaje a desplegar en el LCD
          
           output_low(PIN_C5);                          //apaga el led verde (si estubiera encendido)
           output_low(PIN_C7);                          //apaga el led amarillo (si estuviera encendido)
          
        if (input(PIN_A0)||input(PIN_A1)==1)    // Si A0 o  A1 se pone a 1
             alarma();                                       //Se salta la alarma
                      
                if ((PORTC & 0x0f)==0b00000111)    //si por el nible mas bajo de puerto C, se activa el código 0x07
                   desarmado();                              //Se desactiva el sistema      
                       
                      
         else output_low(PIN_C6);                     //Rutina de parpadeo del led rojo
          delay_ms(600);
          output_high(PIN_C6);
          delay_ms(70);                                    //termina la rutina del led rojo  
        
          
         }
       }
« Última modificación: 23 de Junio de 2010, 14:49:58 por Thulsa Doom »
Más códigos y desarrollos en https://electronicadicto.wordpress.com/ date una vuelta y curiosea un rato...

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Ayuda con configuración de puertos
« Respuesta #3 en: 23 de Junio de 2010, 15:55:24 »
Tal vez la directiva fast_io no permita usar las funciones para LCD...

A ver como me puedo explicar respecto de la AND...

Supongamos que configuro del PORTB el nibble alto como salida y el bajo como entrada (TRISB = 0x0F). Y que todas las salida están en 1. Al leer el PORTB obtengo 0b1111xxxx (siendo x el valor que haya en cada entrada). Es decir que el nibble alto del valor leído está relacionado con como se encuentran las salidas. Al menos así ocurre con HiTech C

En la forma ....while (PORTC != 0b00001000); -que era como lo tenías originalmente- tenías que estar seguro que todas las salidas estaban en 0.

En cambio al hacer PORTC & 0x0F me aseguro de hacer todo el nibble alto 0 y el nibble bajo quedará lo leído. Tené en cuenta que hacer una AND con 0 implica hacer 0 todos los bits donde esté el 0. Hacer una and con 1 no afecta, ya que el que era 1 seguirá siendo 1 y el que era 0 seguirá siendo 0.

Respecto al bucle while (true)... Buscaría la forma de No hacer siempre

Código: C
  1. lcd_gotoxy(1,1);                                 //Seleccionamos la posición del mensaje
  2. printf(lcd_putc, "\f    ARMADO");          //Mensaje a desplegar en el LCD

Tal vez escribiendo el mensaje al salir de la función alarma() y al salir de desrmado()


y me parece que tendrías que cambiar

Código: C
  1. if (input(PIN_A0)||input(PIN_A1)==1)

por

Código: C
  1. if ((input(PIN_A0) == 1) || (input(PIN_A1) == 1))
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado Thulsa Doom

  • PIC24F
  • *****
  • Mensajes: 771
    • https://electronicadicto.wordpress.com/
Re: Ayuda con configuración de puertos
« Respuesta #4 en: 24 de Junio de 2010, 15:23:08 »


Supongamos que configuro del PORTB el nibble alto como salida y el bajo como entrada (TRISB = 0x0F). Y que todas las salida están en 1. Al leer el PORTB obtengo 0b1111xxxx (siendo x el valor que haya en cada entrada). Es decir que el nibble alto del valor leído está relacionado con como se encuentran las salidas. Al menos así ocurre con HiTech C

En la forma ....while (PORTC != 0b00001000); -que era como lo tenías originalmente- tenías que estar seguro que todas las salidas estaban en 0.

En cambio al hacer PORTC & 0x0F me aseguro de hacer todo el nibble alto 0 y el nibble bajo quedará lo leído. Tené en cuenta que hacer una AND con 0 implica hacer 0 todos los bits donde esté el 0. Hacer una and con 1 no afecta, ya que el que era 1 seguirá siendo 1 y el que era 0 seguirá siendo 0.


A ver si me explico con claridad.
¿Lo que me quieres decir, si no te entiendo mal, es que le haces un AND a cada bit del puerto? con lo cual cómo has puesto 0x0f, en binario para verlo mejor:0b00001111 significa que como la AND es:

                                                       A B | S
                                                       0 0  | 0
                                                       0 1  | 0
                                                       1 0  | 0
                                                       1 1  | 1
Por consiguiente los bits que están a 0 siempre estarán a 0 y los que están a 1 con solo poner un 1 en la entrada tenemos         1 | 1 = 1

Lo mismo sucedería en el caso de poner una OR (|) o OR EXCLUSIVA (^) pero con su resultado correspondiente.
¿Me equivoco?

Otra cosa, he hecho lo que me has sugerido y perfecto, ahora no parpadea y es más he cambiado el código y he añadido cosillas, ahora solo me falta la integración de un teclado que lo haré poco a poco, no he llegado a estudiar esto todavía pero me falta poco.


voy a colgar el código para que vean como está ahora.
acepto sugerencias y críticas.

Código: [Seleccionar]

/*
A0 = 1º zona de control
A1 = 2º Zona de control

C0 = Interruptor para código
C1 = Interruptor para código
C2 = Interruptor para código
C3 = Interruptor para código

C5 = led verde
C6 = led rojo
C7 = zumbador, salida PWM
*/

#include <16f876.h>
#fuses XT,NOWDT,NOPROTECT
#use delay(clock = 4000000)
#define use_portb_lcd TRUE
#include <lcd.c>
#use standard_io (A)
#use standard_io (B)
#use standard_io (C)
#BYTE TRISC = 0x87
#BYTE PORTC = 0x07


//----------------------------------Rutina de alarma-----------------------------
void alarma1(){
            lcd_gotoxy(1,1);                                     //esta es la posición para que el mensaje          
            printf(lcd_putc,"\fFALLO SEGURIDAD\nEn la Zona 1");  //funcione en el LCD correctamente            
            
            do{                             //Haz las siguientes rutinas
             output_high(PIN_C6);           //Apagamos el led rojo
            
             output_high(PIN_C7);           //empieza la rutina de la señal PWM
             delay_ms(10);
             output_low(PIN_C7);
             delay_ms(10);                  //Finaliza la rutina de la señal PWM
             }
            while((PORTC & 0x0f)!=0b00001000); // sigue con el bucle mientras PORTC no sea igual a 0b00001000
               lcd_gotoxy(1,1);                    
               printf(lcd_putc, "\fSistema Activado\nZona1 y Zona2");                
}

 //----------------------------------ZONA-2---------------------------------------------------

void alarma2(){
            lcd_gotoxy(1,1);                                     //esta es la posición para que el mensaje          
            printf(lcd_putc,"\fFALLO SEGURIDAD\nEn la Zona 2");  //funcione en el LCD correctamente            
 
            
            do{                             //Haz las siguientes rutinas
             output_high(PIN_C6);           //Apagamos el led rojo
            
             output_high(PIN_C7);           //empieza la rutina de la señal PWM
             delay_ms(10);
             output_low(PIN_C7);
             delay_ms(10);                  //Finaliza la rutina de la señal PWM
             }
            while((PORTC & 0x0f)!=0b00001000); // sigue con el bucle mientras PORTC no sea igual a 0b00001000
               lcd_gotoxy(1,1);                                       //Mensaje al salir del bucle
               printf(lcd_putc, "\fSistema Activado\nZona1 y Zona2"); //para que no parpadee el LCD
                
}


//-------------------------------Rutina de desactivación-----------------------------------


void desarmado(){
              
            lcd_gotoxy(1,1);                                      //Seleccionamos la posición del mensaje  
            printf(lcd_putc, "\f   Sistema \n   Desactivado");    //Mensaje a desplegar en el LCD  

            do{                                  //Haz la siguiente rutina
            output_high(PIN_C5);                 //Enciende el led verde
            output_low(PIN_C6);                  //Apaga el led Rojo
            output_low(PIN_C7);                  //Desactiva el zumbador
            }
            while((PORTC & 0x0f)!=0b00000110);     //sigue con el bucle Mientras PORTC no sea = a 0x06
             lcd_gotoxy(1,1);                                       //Mensaje al salir del bucle
             printf(lcd_putc, "\fSistema Activado\nZona1 y Zona2"); //de esta manera no parpadea el LCD
              
}
//-----------------------------Programa principal-------------------------------  
      
void main(){
      
        lcd_init();                             //Funcion necesaria para que funcione el LCD
        lcd_gotoxy(1,1);                        //Seleccionamos la posición del mensaje
        printf(lcd_putc, "Sistema Activado\n Zona1 y Zona2");         //Mensaje a desplegar en el LCD      
        
     while(TRUE){
          
           output_low(PIN_C5);                  //apaga el led verde (si estubiera encendido)
           output_low(PIN_C7);                   //apaga el led amarillo (si estuviera encendido)
                  
         if (input(PIN_A0)==1)  //Si A0 se pone a 1
             alarma1();         //Salta a alarma1
          if (input(PIN_A1)==1) //Si A1 se pone a 1
              alarma2();        //Salta a alarma2
                      
                if ((PORTC & 0x0f)==0b00000111)//si por el nible mas bajo de puerto C, se activa el código 0x07
                   desarmado();                     //Se desactiva el sistema      
                      
                      
         else output_low(PIN_C6);                  //Rutina de parpadeo del led rojo
          delay_ms(600);
          output_high(PIN_C6);
          delay_ms(70);                        //termina la rutina del led rojo  
        
          
         }
       }




Te doy las gracias por la ayuda que me has prestado, me ha servido de mucho



« Última modificación: 24 de Junio de 2010, 15:26:14 por Thulsa Doom »
Más códigos y desarrollos en https://electronicadicto.wordpress.com/ date una vuelta y curiosea un rato...

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Ayuda con configuración de puertos
« Respuesta #5 en: 24 de Junio de 2010, 15:40:14 »

A ver si me explico con claridad.
¿Lo que me quieres decir, si no te entiendo mal, es que le haces un AND a cada bit del puerto? con lo cual cómo has puesto 0x0f, en binario para verlo mejor:0b00001111 significa que como la AND es:

                                                       A B | S
                                                       0 0  | 0
                                                       0 1  | 0
                                                       1 0  | 0
                                                       1 1  | 1
Por consiguiente los bits que están a 0 siempre estarán a 0 y los que están a 1 con solo poner un 1 en la entrada tenemos         1 | 1 = 1

Lo mismo sucedería en el caso de poner una OR (|) o OR EXCLUSIVA (^) pero con su resultado correspondiente.
¿Me equivoco?


Exacto, esa es la idea.

Un ejemplo de uso de OR sería querer hacer 1 x bit sin alterar el resto. Si queremos hacer 1 el bit 2 sin alterar el resto se puede escribir PORTB |= 0b00000100;

Y un ejemplo de XOR sería cambiar el estado de x bit sin alterar el resto. Sería PORTB ^= 0b00000100;
Al hacer XOR con 1 se cambia el estado. Ya que 1 XOR 1 = 0 y 0 XOR 1 = 1;
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas