Autor Tema: Como haceil para leer interruptores?  (Leído 12829 veces)

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

Desconectado excalibur1491

  • PIC10
  • *
  • Mensajes: 44
Como haceil para leer interruptores?
« en: 23 de Febrero de 2011, 16:34:21 »
No pregunto con respecto a la sintaxis (a lo que ya me respondisteis hace tiempo, gracias, xD), sino a la idea:
yo lo que hago es un bucle for que va testeando todos los pines conectados a interruptores asi:
Código: [Seleccionar]
int j=0;
int i=0;
while(j==0)  //mientras ningun interruptor sea pulsado
{
  for (i=0;i<9;i++)   //chequeo de todos los inerruptores
  {
    if(!(input(Interruptor[i])))   //interruptor contiene todos los interruptores y es de tamaño 9
    {
      qué hacer....;
      j=1;   //salgo del while
    }
  }
}
pero no me parece que sea una solucion optima.. es un poco chapucero

como lo haceis sino??

gracias por la info ;)

Desconectado ppyote

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 929
Re: Como haceil para leer interruptores?
« Respuesta #1 en: 23 de Febrero de 2011, 16:47:58 »
a ver... una interrupcion es lo que la palabra indica... interrupcion...
imagina que esta en una funcion... por ejemplo esta...
___________________________________esto es la funcion de interrupcion por el puerto b4,7____________________________________________________
#int_rb
void cuenta_isr(){
   if(comparacion==0x00)valor_puerto[0]=portb;else valor_puerto[1]=portb;
   for(cuenta=4;cuenta<=7;++cuenta){
      if((bit_test(valor_puerto[0],cuenta))!=(bit_test(valor_puerto[1],cuenta)))++resultado[cuenta-4];
   }
   comparacion=~comparacion;
   if(flag_cambio==0xFF){printf(lcd_putc "\f1 %lu 2 %lu \n3 %lu 4 %lu " resultado[0],resultado[1],resultado[2],resultado[3]);
      flag_cambio=0x00;
      for(borrado=0;borrado<=3;++borrado){
         resultado[borrado]=0;
      }
   }
}
______________________________________funcion interrumpida________________________________________________________
void ejemplo(){
       for(;;){
       delay_ms(10);
       porta= efecto_luces;
       efecto_luces=efecto_luces+1;
       }
}

si hay una interrupcion... deja lo que estaba haciendo el pic en ese momento y atiende la funcion de la interrupcion, osea imagina que hay una interrupcion justo despues de la linea  porta= efecto_luces; entonces dejaria de momento lo que esta haciendo y ejecutaria la funcion void cuenta_isr(), una vez acabada esta retomaria lo que estaba haciendo...


Código: [Seleccionar]
int j=0;
int i=0;
while(j==0)  //mientras ningun interruptor sea pulsado
{
  for (i=0;i<9;i++)   //chequeo de todos los inerruptores
  {
    if(!(input(Interruptor[i])))   //interruptor contiene todos los interruptores y es de tamaño 9
    {
      qué hacer....;
      j=1;   //salgo del while
    }
  }
}

lo que haces en tu codigo es un bucle infinito....
PPyote... siempre estareis en mi corazon.... Te quiero Hermano...

Desconectado excalibur1491

  • PIC10
  • *
  • Mensajes: 44
Re: Como haceil para leer interruptores?
« Respuesta #2 en: 23 de Febrero de 2011, 17:06:11 »
a ver... una interrupcion es lo que la palabra indica... interrupcion...
imagina que esta en una funcion... por ejemplo esta...
___________________________________esto es la funcion de interrupcion por el puerto b4,7____________________________________________________
#int_rb
void cuenta_isr(){
   if(comparacion==0x00)valor_puerto[0]=portb;else valor_puerto[1]=portb;
   for(cuenta=4;cuenta<=7;++cuenta){
      if((bit_test(valor_puerto[0],cuenta))!=(bit_test(valor_puerto[1],cuenta)))++resultado[cuenta-4];
   }
   comparacion=~comparacion;
   if(flag_cambio==0xFF){printf(lcd_putc "\f1 %lu 2 %lu \n3 %lu 4 %lu " resultado[0],resultado[1],resultado[2],resultado[3]);
      flag_cambio=0x00;
      for(borrado=0;borrado<=3;++borrado){
         resultado[borrado]=0;
      }
   }
}
______________________________________funcion interrumpida________________________________________________________
void ejemplo(){
       for(;;){
       delay_ms(10);
       porta= efecto_luces;
       efecto_luces=efecto_luces+1;
       }
}

si hay una interrupcion... deja lo que estaba haciendo el pic en ese momento y atiende la funcion de la interrupcion, osea imagina que hay una interrupcion justo despues de la linea  porta= efecto_luces; entonces dejaria de momento lo que esta haciendo y ejecutaria la funcion void cuenta_isr(), una vez acabada esta retomaria lo que estaba haciendo...

ahi me has roto.
Conzco el principio de las interrupciones un poco "tangencialmente": sé que si sucede algo, se para lo que se estaba haciendo, se ejecuta el codigo d ela interrupcion y luego se sigue (y dura 4 ciclos de reloj creo)
pero .... no tengo el nivel, desde luego.
1- porqué es una interrupcion por el puerto b4,7 como dices? qué la hace especifica a ese puerto?
2- en tu ejemplo, si la interrupcion es justo despues de porta= efecto_luces; qué es lo que activaria la interrupcion? para mi se necesita un if que testee para ver si la interrupcion ha sucedido ...
3- he mirao en CCs la ayuda sobre las interrupciones..
a mi entender yo necesitaria algo tipo: #int_default
 This directive specifies that the following function should be called if an interrupt is triggered but no routine is associated with that interrupt.
y haria:
Código: [Seleccionar]
#int_default
void interruptor0
{la funcion.....}
y una interrupcion para cada interruptor?

siento ser un poco lento, pero esq estoy siendo 100% autodidacta asi que me ayudais mucho XD

graciaaas

Desconectado ppyote

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 929
Re: Como haceil para leer interruptores?
« Respuesta #3 en: 23 de Febrero de 2011, 17:25:20 »

1- porqué es una interrupcion por el puerto b4,7 como dices? qué la hace especifica a ese puerto?
2- en tu ejemplo, si la interrupcion es justo despues de porta= efecto_luces; qué es lo que activaria la interrupcion? para mi se necesita un if que testee para ver si la interrupcion ha sucedido ...
3- he mirao en CCs la ayuda sobre las interrupciones..
a mi entender yo necesitaria algo tipo: #int_default


a ver...
1 el puerto B del 16f628A se puede habilitar la interrupcion por el cambio de flanco en los pines RB4....al RB7 que es justo el ejemplo que yo te he puesto....
2 la interrupcion puede pasar en cualquier instante,antes del delay_ms(), mientras esta en el delay_ms() despues del delay_ms().... imagina que mientras se ejecuta una funcion se detecta un envio por el puerto serie de un dato... el pic debe de ser capaz, de parar lo que esta haciendo, acabar de recibir el valor que se le ha enviado, procesar el dato, actuar ante lo recibido y retomar lo que estaba haciendo...
3 mejor centrate en el tipo de interrupcion que necesitas asi no utilizaras toda la rom del pic..

imagina lo qu puedes hacer con todo esto y mucho mas.... eto son las interrupciones posibles en un 16f886...

 INT_RTCC                 
 INT_RB                   
 INT_EXT_L2H               
 INT_EXT_H2L               
 INT_EXT                   
 INT_AD                   
 INT_TBE                   
 INT_RDA                 
 INT_TIMER1               
 INT_TIMER2             
 INT_CCP1                 
 INT_CCP2             
 INT_SSP                   
 INT_BUSCOL             
 INT_EEPROM               
 INT_TIMER0             
 INT_OSC_FAIL           
 INT_COMP             
 INT_COMP2             
 INT_ULPWU               
 INT_RB0                   
 INT_RB1                 
 INT_RB2               
 INT_RB3                   
 INT_RB4               
 INT_RB5     
 INT_RB6             
 INT_RB7
PPyote... siempre estareis en mi corazon.... Te quiero Hermano...

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Como haceil para leer interruptores?
« Respuesta #4 en: 23 de Febrero de 2011, 17:30:36 »
  Las interrupciones las genera el PIC, no es tu programa el que las genera. Sí es tu programa el que tiene que decidir que hacer cuando ocurre alguna interrupción.
  En los datasheet de los distintos PIC se especifican cuales son las distintas interrupciones y cuando ocurren las mismas.

  Yo también fui aprendiendo solo, como creo que muchos lo han hecho. Yo leí algunos libros bajados de internet que me ayudaron mucho a aprender un poco de C. Asembler lo aprendí leyendo el datasheet del PIC.

  Algunos de los libros que leí son:

"An introduction to programming pic in c"
"Programming 8 bit pic microcontrollers in c "
"Compilador C CCS y simulador Proteus para microcontroladores pic"
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado excalibur1491

  • PIC10
  • *
  • Mensajes: 44
Re: Como haceil para leer interruptores?
« Respuesta #5 en: 23 de Febrero de 2011, 17:41:36 »

1- porqué es una interrupcion por el puerto b4,7 como dices? qué la hace especifica a ese puerto?
2- en tu ejemplo, si la interrupcion es justo despues de porta= efecto_luces; qué es lo que activaria la interrupcion? para mi se necesita un if que testee para ver si la interrupcion ha sucedido ...
3- he mirao en CCs la ayuda sobre las interrupciones..
a mi entender yo necesitaria algo tipo: #int_default


a ver...
1 el puerto B del 16f628A se puede habilitar la interrupcion por el cambio de flanco en los pines RB4....al RB7 que es justo el ejemplo que yo te he puesto....
2 la interrupcion puede pasar en cualquier instante,antes del delay_ms(), mientras esta en el delay_ms() despues del delay_ms().... imagina que mientras se ejecuta una funcion se detecta un envio por el puerto serie de un dato... el pic debe de ser capaz, de parar lo que esta haciendo, acabar de recibir el valor que se le ha enviado, procesar el dato, actuar ante lo recibido y retomar lo que estaba haciendo...
3 mejor centrate en el tipo de interrupcion que necesitas asi no utilizaras toda la rom del pic..

imagina lo qu puedes hacer con todo esto y mucho mas.... eto son las interrupciones posibles en un 16f886...

[...]

gracias por responder tan pronto, xD

entonces, supongamos que yo tnego 8 interruptores (no es el caso, pero bueno, pa entender...) conectados al puerto B (de 0 a 7) en un pic18f4550
(en en .h de CCS he visto que existe #INT_RB supongo pues que las interrupciones funcionan para todo el puerto B)
entonces al principio de mi codigo he de poner:
Código: [Seleccionar]
#INT_RB
void leer_interruptor()
{
for (i=0;i<8;i++)
{
if (bit_test(port_b,i)==1)  //la habia definido port_b como la direcction de puerto b en otro ligar del codigo
{
el interruptor conectado al pin i del puerto b ha sido pulsado (o no, dependiendo de si estoy en pull-up o pull-down);
}
}
}

y esto, cada vez que alguien pulse un interruptor del B, va a ejecutarse?

muchisimas gracias


Gracias angelgris :9 el ultimo que mencionas creo que se ajusta a lo que busco, lo buscaré ;)

Desconectado ppyote

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 929
Re: Como haceil para leer interruptores?
« Respuesta #6 en: 23 de Febrero de 2011, 18:04:09 »
asi es.... pero lo mejor es que guardes el resultado del valor del puerto B en una variable.... es mas fiable ya que puede ser que dentro del for() se demore mucho tiempo y nole de tiempo a leer bien los bits del portB

asi mejor....
#INT_RB
void leer_interruptor(){
   int valor_puerto;
   valor_puerto=portb;
   for (i=0;i<8;i++){
       if (bit_test(valor_puerto,i)==1){  //la habia definido port_b como la direcction de puerto b en otro ligar del codigo
       aqui lo que desees cuando el interruptor conectado al pin i del puerto b ha sido pulsado (o no, dependiendo de si estoy en pull-up o pull-down);
   }
  }
}
PPyote... siempre estareis en mi corazon.... Te quiero Hermano...

Desconectado excalibur1491

  • PIC10
  • *
  • Mensajes: 44
Re: Como haceil para leer interruptores?
« Respuesta #7 en: 23 de Febrero de 2011, 19:05:52 »
muchas gracias :)

pues estoy probando ahora y no funciona.... ¿? lo he simplificado al maximo para ver si era un fallo en bucles etc..
la led de D0 parpadea todo el tiempo, pero por más que pulse el interruptor de B5 no me hace ni caso xD
Código: [Seleccionar]
#include <18F4550.h>
#use delay(clock=2000000)
#byte port_a=0xF80               //esto es correcto, seguro ;)
#byte port_b=0xF81
#byte port_c=0xF82
#byte port_d=0xF83
#byte port_e=0xF84

#INT_RB
void leer_interruptor()
{
   int valor_puerto;
   valor_puerto=port_b;
   if (bit_test(valor_puerto,5)==0)  //he probao poniendo ==1 por si acaso
   { 
          output_high(PIN_A0);  //nunca he conseguido encenderla
   }
}

int main()
{
port_a=0x00;         
port_b=0x00;
port_c=0x00;
port_d=0x00;
port_e=0x00;

set_tris_a(0b0000000);     
set_tris_b(0b11111111);   
set_tris_c(0b00000000);   
set_tris_d(0b00000000);   
set_tris_e(0b1000);
enable_interrupts(INT_RB);   //he probao a poner esto o quitarlo, sin efecto alguno
while(1)
{
 output_high(PIN_D0);  //esto lo hace bien
 delay_ms(1000);
 output_low(PIN_D0);
 delay_ms(1000);
}
}
osea que el codigo funciona bien, y ni caso
os paso tb el dibujo de mi circuito y el header del 18F4550 para que veais las interrupciones disponibles (aparece int_rb)

muchas gracias :)


Corrijo, creo que he hecho una tonteria, leyendo el libreo que me recomendó antes angelgris veo que INT_RB es uan interrupcion para cambio de estado en B4-B7.. asi que he conectado el interruptor en B5... aun asi, no funciona
« Última modificación: 23 de Febrero de 2011, 19:39:51 por excalibur1491 »

Desconectado bmb

  • PIC18
  • ****
  • Mensajes: 423
Re: Como haceil para leer interruptores?
« Respuesta #8 en: 23 de Febrero de 2011, 19:34:09 »
entonces, supongamos que yo tnego 8 interruptores (no es el caso, pero bueno, pa entender...) conectados al puerto B (de 0 a 7) en un pic18f4550
(en en .h de CCS he visto que existe #INT_RB supongo pues que las interrupciones funcionan para todo el puerto B)

Hola excalibur1491, #INT_RB solo es para los pines RB4 a RB7.  Para aprender más sobre el uso de esta interrupción te recomendaría estudiar el ejemplo del CCS: EX_PBUTT.C

Saludos!

Desconectado excalibur1491

  • PIC10
  • *
  • Mensajes: 44
Re: Como haceil para leer interruptores?
« Respuesta #9 en: 23 de Febrero de 2011, 19:40:38 »
entonces, supongamos que yo tnego 8 interruptores (no es el caso, pero bueno, pa entender...) conectados al puerto B (de 0 a 7) en un pic18f4550
(en en .h de CCS he visto que existe #INT_RB supongo pues que las interrupciones funcionan para todo el puerto B)

Hola excalibur1491, #INT_RB solo es para los pines RB4 a RB7.  Para aprender más sobre el uso de esta interrupción te recomendaría estudiar el ejemplo del CCS: EX_PBUTT.C

Saludos!

gracias, ya me di cuenta, y lo cambié y lo intenté poniendo el interruptor en B5, y sigue sin funcioanr (he modificao el codigo en mi post anterior)
gracias, miraré el ejemplo que me comentas ;)

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Como haceil para leer interruptores?
« Respuesta #10 en: 24 de Febrero de 2011, 03:03:38 »
En el código también te falta: enable_interrupts(GLOBAL);

Leete también esto, te puede ayudar: http://www.todopic.com.ar/foros/index.php?topic=21226.0
« Última modificación: 24 de Febrero de 2011, 03:06:46 por pocher »

Desconectado excalibur1491

  • PIC10
  • *
  • Mensajes: 44
Re: Como haceil para leer interruptores?
« Respuesta #11 en: 24 de Febrero de 2011, 06:11:00 »
En el código también te falta: enable_interrupts(GLOBAL);

Leete también esto, te puede ayudar: http://www.todopic.com.ar/foros/index.php?topic=21226.0

Genial, muchas gracias, así si que funciona

pero ahora tengo un problemilla: no tengo solo 4 interruptores conectados al b4,b5,b6 y b7..... tengo 9 interruprotes (los puedo conectar donde convenga, eso no es problema).... entonces como puedo hacer para leer tantos interruptores si el pic18f4550 no tiene int_ra ni int_rd ni int_rc ni int_re ?

mil gracias ;)

modifico:
nno tengo ni idea, pero leyendo cosillas por internet y el header y la ayuda de ccs, hay interrupciones ext, ext1 ext2 y una comp (el pic tiene un pin c1out y otro c2out)  . esas sirven como si fueran las del INT_RB ?

modifico:
He oensado que podria conectar los 9 interruptores, cada uno con una resistencia diferente a un solo PIN del pic que leyera la tension enviada (el verdadero valor) para deducir (segun el valor de la resistencia) que interruptor ha sido pulsado con una interrupcion int_ad
esto se hace con el algo llamado AC, no? he leido en la ayuda de CCs como funciona .. pero no llego a entender muy bien lo de AC..
setup_adc_ports() pone el pin especificado en AC, no?
read_adc() lee la tension del pin especificado en set_adc_channel()
setup_adc() no entiendo que hace...
y set_adc_channel() no entiendo qué es el canal... (creo que he entendido: el el bit del byte llamado ADCON0, no?)
gracias :9
« Última modificación: 24 de Febrero de 2011, 08:46:52 por excalibur1491 »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Como haceil para leer interruptores?
« Respuesta #12 en: 24 de Febrero de 2011, 10:15:02 »
  Te conviene buscar en el foro sobre teclados matriciales, hay mucha información al respecto.
Tené en cuenta que un teclado de 16 teclas matricial lo podés manejar utilizando 8 pines, lo cual es mucho mas conveniente que utilizar un pin por tecla. Con 7 pines del PIC podrías manejar un teclado de hasta 12 teclas
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado excalibur1491

  • PIC10
  • *
  • Mensajes: 44
Re: Como haceil para leer interruptores?
« Respuesta #13 en: 24 de Febrero de 2011, 11:38:40 »
  Te conviene buscar en el foro sobre teclados matriciales, hay mucha información al respecto.
Tené en cuenta que un teclado de 16 teclas matricial lo podés manejar utilizando 8 pines, lo cual es mucho mas conveniente que utilizar un pin por tecla. Con 7 pines del PIC podrías manejar un teclado de hasta 12 teclas

ya he visto el post sobre el tecaldo 4x4... no entiendo na! y ademas no dispongo de teclado, solo de interruptores sueltos
estoy haceindo un 3 en raya , asi que 9 interruptores sueltos conectados al PIC -> 9 pines....

el problema es el siguiente: apra disminuir el consumo, voy a encender un solo led a la vez, muy rapido para que parezca que estan todos encendidos...
pero si hago esto necesito que mi funcion de scaneo de los interruptores para ver donde quiere jugar la persona sea una interrupcion (porque no puedo ejecutar a la vez la funcion que ilumina los leds y la que chequea los botones).
por eso quiero usar una interrupcion.
-> el problema esq creo que mi pic 18f4550 no tiene bastantes interrupciones (rb4 a rb7 son muy pocas) asi que he pensao en usar 3 pines analogicos (AN0 a AN2) cada uno con 3 interruptores coenctados (cada interruptor envia una tension diferente).
Habria una interrupcion para cuando el estado de uno de los pines analogicos cambie y en esta interrupcion (sabiendo la tension medida) determinaria que interruptor ha sido pulsado.

pero no consigo hacerlo.
de momento para aprender estoy haciendo un programa asi:
Código: [Seleccionar]
#include <18F4550.h>
#use delay(clock=2000000)
#include <math.h>

#byte port_a=0xF80                //puertos de 18f4550
#byte port_b=0xF81
#byte port_c=0xF82
#byte port_d=0xF83
#byte port_e=0xF84

void main()
{

port_a=0x00;         //inicializo puertos
port_b=0x00;
port_c=0x00;
port_d=0x00;
port_e=0x00;

set_tris_a(0b0111110);     
set_tris_b(0b00000000);   
set_tris_c(0b0000000);   
set_tris_d(0b00000000);   
set_tris_e(0b1111);

   float p=6;
   double q=6;
   setup_adc_ports(AN0);   //leo la tension por an0 que es A0
   setup_adc(ADC_CLOCK_INTERNAL);  //no sé pa que sirve, pero en un ejemplo lo ponian  asi
   while (1)
   {
   set_adc_channel(0);   //leo por el canal 0, osea An0
   delay_us(20);    //espero
   output_high(PIN_B7);   //enciendo un led que me dice que es el momento de pulsar el interruptor
   delay_ms(1000);    //mientras este segundo, pulso el interruptor
   q=read_adc();    //leo la tension
   //q=floor(q);
   output_low(PIN_B7);   //apago el led
   p=5.0*q /1024.0 ;    //calculo la tension
   if (p==0)     //si la tension era nula, osea que el interruptor no estaba apretao
   {output_high(PIN_B3);}  //enciendo el led B3
   if (ceil(p)==5)                //si aprieto el boton con una resistencia de 10k la tension se pone a 5V y apago el led B3
   {output_low(PIN_B3);}    //PERO NO LO APAGA NUNCA
   if (floor(p)==2)   //resistencia de 0.07Ohm
   {output_high(PIN_B4);}  //NUNCA LO ENCIENDE
   delay_ms(1000);
}
}

osea que no sé hacerlo :'(

alguna idea?? gracias :)


MODIFICO:
en el ejemplo que vi en el libro  Compilador C CCS y simulador Proteus para microcontroladores pic olvidé una linea: #device icd=10 al principio
ahora si que funciona bian. Graciaas :)
por saber... qué hace esa linea?
y la setup_adc() ? gracias :)
« Última modificación: 24 de Febrero de 2011, 12:02:57 por excalibur1491 »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Como haceil para leer interruptores?
« Respuesta #14 en: 24 de Febrero de 2011, 12:08:56 »
  Te conviene buscar en el foro sobre teclados matriciales, hay mucha información al respecto.
Tené en cuenta que un teclado de 16 teclas matricial lo podés manejar utilizando 8 pines, lo cual es mucho mas conveniente que utilizar un pin por tecla. Con 7 pines del PIC podrías manejar un teclado de hasta 12 teclas

ya he visto el post sobre el tecaldo 4x4... no entiendo na! y ademas no dispongo de teclado, solo de interruptores sueltos
estoy haceindo un 3 en raya , asi que 9 interruptores sueltos conectados al PIC -> 9 pines....

el problema es el siguiente: apra disminuir el consumo, voy a encender un solo led a la vez, muy rapido para que parezca que estan todos encendidos...
pero si hago esto necesito que mi funcion de scaneo de los interruptores para ver donde quiere jugar la persona sea una interrupcion (porque no puedo ejecutar a la vez la funcion que ilumina los leds y la que chequea los botones).
por eso quiero usar una interrupcion.


  No importa que no dispongas de un teclado matricial, se puede armar tranquilamente con teclas sueltas.
  Por otro lado se puede usar la interrupción de alguno de los timers para que sea tu base de tiempo para el refresco de los leds.

  Te muestro un ejemplo de como armar un teclado matricial con simples switch. Los pines Col x irían a salidas del pic y los pines Fila x irían a entradas que generen interrupción (RB4..RB7), entonces cuando se presiones alguna tecla se une el puerto de salida con el de entrada y genera interrupción.
  Incluso para tu caso que necesitas 9 pulsadores te alcanza con sólo 6 pines.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas