TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: excalibur1491 en 23 de Febrero de 2011, 16:34:21

Título: Como haceil para leer interruptores?
Publicado por: excalibur1491 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 ;)
Título: Re: Como haceil para leer interruptores?
Publicado por: ppyote 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....
Título: Re: Como haceil para leer interruptores?
Publicado por: excalibur1491 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
Título: Re: Como haceil para leer interruptores?
Publicado por: ppyote 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
Título: Re: Como haceil para leer interruptores?
Publicado por: AngelGris 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"
Título: Re: Como haceil para leer interruptores?
Publicado por: excalibur1491 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é ;)
Título: Re: Como haceil para leer interruptores?
Publicado por: ppyote 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);
   }
  }
}
Título: Re: Como haceil para leer interruptores?
Publicado por: excalibur1491 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
Título: Re: Como haceil para leer interruptores?
Publicado por: bmb 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!
Título: Re: Como haceil para leer interruptores?
Publicado por: excalibur1491 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 ;)
Título: Re: Como haceil para leer interruptores?
Publicado por: pocher 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 (http://www.todopic.com.ar/foros/index.php?topic=21226.0)
Título: Re: Como haceil para leer interruptores?
Publicado por: excalibur1491 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 (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
Título: Re: Como haceil para leer interruptores?
Publicado por: AngelGris 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
Título: Re: Como haceil para leer interruptores?
Publicado por: excalibur1491 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 :)
Título: Re: Como haceil para leer interruptores?
Publicado por: AngelGris 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.
Título: Re: Como haceil para leer interruptores?
Publicado por: excalibur1491 en 24 de Febrero de 2011, 12:18:07
 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.

!! que locura!
vale, entiendo que es, desde luego, una muy buena solucion: 6 pines y 3 de ellso con interrupcion, se puede hacer si problema
pero no entiendo uan cosa:
cualquier boton de la primera linea va a activar una interrupcion del pin conectado a la priemra linea.... pero como voy a saber que boton ha sido?
gracias (me ayudais muchisimo :))

modifico:
es asi como se hace?
"interrupcion de la primera linea activada"
dentor de la interrupcion "una por una quito la tension de las columnas, caundo el pin 'linea 1' deje de recibir corriente es que he quitado la columna del boton apagado" ??
Título: Re: Como haceil para leer interruptores?
Publicado por: jukinch en 24 de Febrero de 2011, 12:51:33
Hola Excalibur1491:
       en la página del amigo RedPic podrás ver un ejemplo de la librería de teclado matricial.

http://picmania.garcia-cuervo.net/picc.php#KBDLIB


y aquí tienes otro ejemplo del amigo Sucky.

http://www.todopic.com.ar/foros/index.php?topic=27167.0
           
          Espero te ayuden a aclarar las cosas.
                               Saludos.
                                    Jukinch
Título: Re: Como haceil para leer interruptores?
Publicado por: excalibur1491 en 24 de Febrero de 2011, 15:19:14
gracias jukinch ;)

ahora estoy asi:
dentro de mi rpograma grande llamo a print que es durante la unica que quiero que pueda haber interrupciones (enciende unos diodos mientras espera a que la persona pulse un interruptor)
Código: [Seleccionar]
void print(char* T)                        
{
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
output_high(PIN_B0);
output_high(PIN_B1);
output_high(PIN_B2);
output_high(PIN_A0);
  while(j==0)
  {
      //Enciendo unas leds segun una secuencia: funciona bien
  }
disable_interrupts(GLOBAL);
disable_interrupts(INT_RB);
output_low(PIN_B0);
output_low(PIN_B1);
output_low(PIN_B2);
output_low(PIN_A0);
j=0;
}

ahora la interrupcion es esta:
Código: [Seleccionar]
#INT_RB //teclado
void teclado(char* T, int* movmntsO, int* M)
{
   int i=4;
   int linea=0;
   int columna=0;
   int mov=0;
   for (i=4;i<7;i++)   //Chequeo que linea ha sido pulsada (rb4, rb5 o rb6)
   {
     if (bit_test(port_b,i)==1)
     {linea=i-3;}  //las lineas se llaman 1 2 o 3... asi que corrijo i
   }
   i=0;
   for(i=0;i<3;i++)
   {
      output_low(31752+i);   // pone a 0 la columna i (el PIN_B0 esta definido en el header como 31752, asi q uso directamente el numero)
      if (bit_test(port_b,linea+3)==0)   //la linea ya no recibe corriente (corrijo.. si linea=1 quiero mirar el rb4, asi que linea+3
      {columna=i;} //
   }
  
   if (linea==1)
   {mov=columna;}                                  //mi cuadro T es asi: {0 ,1 ,2
   if (linae==2)                                                                      3, 4, 5,
   {mov=columna+3;}                                                           6, 7, 8}
   if (linea==2)
   {mov=columna+6;}
   movmntsO[*M]=mov;      //  esto funciona bien ;)              
   T[mov]='O';  
   *M=*M + 1;  
  
   j=1;  //para para la funcion print
   clear_interrupt(INT_RB);
}


y al principio d ela funcion main:
Código: [Seleccionar]
     
port_b=0x00;
  
set_tris_b(0b01110000);  
y lo que sucede este me hace bien la secuencia de leds cuando entra por primera vez en print(T) pero en cuandot pulso un interruptor, se paga todo y buenas noches..... No sé que fallo hay,
os paso el circuito tb:

muchas gracias :)
Título: Re: Como haceil para leer interruptores?
Publicado por: jukinch en 24 de Febrero de 2011, 19:00:22
excalibur1491:
                   Podés subir el código completo y el dsn así chequeo el funcionamiento.
                                                  Saludos.
                                                         Jukinch
Título: Re: Como haceil para leer interruptores?
Publicado por: excalibur1491 en 24 de Febrero de 2011, 20:32:46
excalibur1491:
                   Podés subir el código completo y el dsn así chequeo el funcionamiento.
                                                  Saludos.
                                                         Jukinch

como es para un trabajo, prefiero que no esté el codigo completo por internet, asi que pongo la parte que falla (he borrao todo dejando solo esta aprte, y no funciona como es debido, asi q...)
explico:
en la funcion main tenemos un cuadro T (cuadro del juego tic-tac-toe) , un cuadro momntsO que contiene las casilals de T en las que está puesto 'O' , un contador movimientos que cuenta cuantos movimientos de O ha habido y su puntero M.
aqui, para abrebiar, he puesto el caudro T conteniendo ya 3 X en las casillas 1 4 y 6 de T (asi que se encienden, parpadeando, las leds correpsondientes, eso funciona OK)
ahora, mientras se esta en la funcion print (de la cual no se sale a menos que se declare una interrupcion), al pulsar un boton se detecta a que linea y a q columna pertenece el boton pulsado y se enceinde el diodo correspondiente (porque se ha colocado un 'O' en la casilla de T correspondiente) PERO NO FUNCIONA.

adjunto codigo y circuito

relamente, muchas gracias ;)

P.D.: una curiosidad: si añado output_high(31768+linea+columna); en la funcion telcado justo antes de la tanda de if's al final, depues del 2º for, enciende el diodo correcto pero me enciende, ademas el diodo conectado a D2 (siempre el mismo)...
Título: Re: Como haceil para leer interruptores?
Publicado por: jukinch en 24 de Febrero de 2011, 20:56:30
excalibur1491:
           Subí sólo la parte del header en donde definís los pines.
En los comentarios hacés referencia a que el PIN_B0 esta definido en el header como 31752 y si no me equivoco me parece que luego lo utilizas como si hicieras referencia a  todo el puerto b completo?
Por las dudas te aclaro que las funciones output_high(PIN); o output_low(PIN); sólo controlan un pin del microcontrolador,
Si quieres controlar todo el puertob entero, usá la función output_b(DATO);
             Jukinch       
Título: Re: Como haceil para leer interruptores?
Publicado por: excalibur1491 en 25 de Febrero de 2011, 06:31:42
excalibur1491:
           Subí sólo la parte del header en donde definís los pines.
En los comentarios hacés referencia a que el PIN_B0 esta definido en el header como 31752 y si no me equivoco me parece que luego lo utilizas como si hicieras referencia a  todo el puerto b completo?
Por las dudas te aclaro que las funciones output_high(PIN); o output_low(PIN); sólo controlan un pin del microcontrolador,
Si quieres controlar todo el puertob entero, usá la función output_b(DATO);
             Jukinch       

mmm.. no.. el pin B0 es bien el 31752.. y yo lo que hago en m segundo bucle for es: apago una columna, miro si sigue habiendo tension en la linea (si no la hay, esq he apagao la columna del interruptor pulsado), vuelvo a encenderla y cequeo asi la segunda columna....etc..

los pines estas definidos asi:

#define PIN_A0  31744
#define PIN_A1  31745
#define PIN_A2  31746
#define PIN_A3  31747
#define PIN_A4  31748
#define PIN_A5  31749
#define PIN_A6  31750

#define PIN_B0  31752
#define PIN_B1  31753
#define PIN_B2  31754
#define PIN_B3  31755
#define PIN_B4  31756
#define PIN_B5  31757
#define PIN_B6  31758
#define PIN_B7  31759

#define PIN_C0  31760
#define PIN_C1  31761
#define PIN_C2  31762
#define PIN_C4  31764
#define PIN_C5  31765
#define PIN_C6  31766
#define PIN_C7  31767

#define PIN_D0  31768
#define PIN_D1  31769
#define PIN_D2  31770
#define PIN_D3  31771
#define PIN_D4  31772
#define PIN_D5  31773
#define PIN_D6  31774
#define PIN_D7  31775

#define PIN_E0  31776
#define PIN_E1  31777
#define PIN_E2  31778
#define PIN_E3  31779
#define PIN_E7  31783


gracias ;)
Título: Re: Como haceil para leer interruptores?
Publicado por: excalibur1491 en 25 de Febrero de 2011, 06:43:00
uy, esto se pone siniestro....
si en la interrupcion borro todo y dejo solo T[5]='O' .. T[5] no recibe O... y se apaga todo....
esq acaso el T de la interrupcion no es el mismo que en todos laos??

gracias ;)
Título: Re: Como haceil para leer interruptores?
Publicado por: excalibur1491 en 25 de Febrero de 2011, 10:07:35
BUENO! Ahora sí funciona bien!
he hecho lo siguiente:
crear 2 variables globales columna y linea. la funcion de interrupcion no tiene parametros y solo se ocupa de determinar la linea y la columna, y dentro de print he hehco tod lo que tiene que ver con el cuadro T etc.... asi la de la interrupcion no tiene nada que ahcer mas que cambair el valor de 2 variables globales


sin embrgo: la interrupcion es tan lenta que a vece no llega a leer todo antes de quitar el dedo del pulsador.. asiq ue he quitado todo lo que era outpout_low en el segundo for, apra que vaya mas rapido y ahora parece funcionar bien.
para evitar rebotes he tenido que poner un delay_ms(100) al final de la funcion ....

ahora tnego una duda: yo todo esto lo hacia para poder hacer que mi funcion print, en vez de encender todas las leds a al vez, encienda una por una muy rapido.... pero como esto lo hago con ifs, desde que enciende la de arriba a la izquierda ahsta que enciende la de abajo a la derecha, para un tiempo sin que haya nada encendido....
algun consejo apra optimizar esto? :)
Título: Re: Como haceil para leer interruptores?
Publicado por: jukinch en 25 de Febrero de 2011, 10:59:33
excalibur1491:
               Con relación al tema del array vi el código esta mañana y veo que lo has resuelto solo y era por el ámbito del array T[] el cual estaba declarado dentro de main y no como global como las otras variables que usabas.
         Con respecto a la optimización te sugiero que dentro de la interrupción hagas lo menos posible. Tan sólo cambiar de estado banderas para luego consultarlas en el programa principal para que no se haga un cuello de botella en el código e implementes un antirebote con un algoritmo que no espere un tiempo X. (como es el delay_ms(100))
         Para ello verifica 10 veces seguidas si una variable de tipo bool como ser botonPulsado sea verdadera las 10 veces seguidas en que la consultaste. Con eso detectarás que el botón se haya pulsado de verdad y no que sea ruido.-
         Si no llega a ser verdadera en una de las 10 veces en que consultaste, que descarte la pulsación y vuelva a ingresar al bucle en donde comprobás si se pulsó el botón. Con esto eliminarás el ruido de la pulsación de los botones y serán menores las esperas.
         Y tambíen usaría un cristal que me de el mayor clock para la velocidad de trabajo del micro.
                 Saludos.
                       Jukinch.
Título: Re: Como haceil para leer interruptores?
Publicado por: excalibur1491 en 25 de Febrero de 2011, 11:09:39
excalibur1491:
               Con relación al tema del array vi el código esta mañana y veo que lo has resuelto solo y era por el ámbito del array T[] el cual estaba declarado dentro de main y no como global como las otras variables que usabas.
         Con respecto a la optimización te sugiero que dentro de la interrupción hagas lo menos posible. Tan sólo cambiar de estado banderas para luego consultarlas en el programa principal para que no se haga un cuello de botella en el código e implementes un antirebote con un algoritmo que no espere un tiempo X. (como es el delay_ms(100))
         Para ello verifica 10 veces seguidas si una variable de tipo bool como ser botonPulsado sea verdadera las 10 veces seguidas en que la consultaste. Con eso detectarás que el botón se haya pulsado de verdad y no que sea ruido.-
         Si no llega a ser verdadera en una de las 10 veces en que consultaste, que descarte la pulsación y vuelva a ingresar al bucle en donde comprobás si se pulsó el botón. Con esto eliminarás el ruido de la pulsación de los botones y serán menores las esperas.
         Y tambíen usaría un cristal que me de el mayor clock para la velocidad de trabajo del micro.
                 Saludos.
                       Jukinch.

pregunta esencial: que son las flags, y como se usan? xD graciaas

con respecto al antirrebotes... no enteindo que tiene que hacer botonPulsado.... vale 1 si lo pulso, mientras valga 1 (10 veces en un while que englobe toda la funcion de teclado) hago lo que hay dentro de la funcion del teclado?? no he entendido muy bien....

gracias por toda la ayuda ;)
Título: Re: Como haceil para leer interruptores?
Publicado por: jukinch en 25 de Febrero de 2011, 12:12:55
Excalibur1491:
TEMA INTERRUPCIONES:
                Para que una interrupción cumpla con su cometido el código que pongas dentro de la misma tiene que ser lo más corto que puedas y que dure el menor tiempo posible.
               Para ello se utilizan variables que se las llama normalmente Flags o banderas (para consultar su estado luego dentro del código princial). Si usás un código muy extenso dentro de la interrupción corrés el peligro de que por tardar mucho tiempo ocurra el evento que estás controlando nuevamente y además te quite tiempo para lo que estás haciendo en el código principal. No se si me explico.

Por ejemplo, te paso el pseudocódigo:

INTERRUPCION:
             alarmaEncendida=1;


FIN INTERRUPCIÓN



DENTRO DE MAIN:
while(1)
   { // BUCLE PRINCIPAL
                  if (alarmaEncendida==1)
                                            {
                                              // hago lo que me interesa que se actualice rápido
                                              alarmaEncendida  = 0; // Asigno a la variable alarmaEncendida el valor de cero (0) para que no vuelva
                                                                                  // a este sector del código excepto si se ha producido la interrupción.
                                             }
                 else
                         {
                          // hago otra cosa
                          }                        
} // FINAL DE BUCLE PRINCIPAL



Aquí tienes algunos ejemplos de uso de banderas.
http://todopic.mforos.com/46840/5068985-ejemplos-para-pic16f877-con-ccs/


TEMA ANTIRREBOTE:

            normalmente se usa una espera de x milisegundos para evitar que una pulsación mecánica se interprete digitalmente como varias pulsaciones por los motivos que ya conoces.
            Pero eso no es lo óptimo. ¿Por que esperar X tiempo?
            Se puede comprobar en menos tiempo que X.
Para ello debes crear un algoritmo que verifica si el botón se pulsó, y además se mantuvo pulsado durante x iteraciones.

Un ejemplo a continuación:

do   {

     if (input(PIN_B0) ) // controla si el botón se pulsó
         arranca=arranca+1;
      ELSE
          IF (ARRANCA>1)
            arranca=arranca-1;

 }while(arranca<=100);   // el valor de 100 lo podés variar en más o en menos para afinarlo a tu necesidad.


Es poco probable que tengas un ruido que dure 100 iteraciones seguidas con el estado alto de RB0.
Y así el tiempo de este algoritmo es mucho menor que esperar 1 milisegundo. Se entiende?
Sinó avisá y te amplío el concepto.
               Saludos.
                         Jukinch

Título: Re: Como haceil para leer interruptores?
Publicado por: AngelGris en 25 de Febrero de 2011, 12:27:32
  Es muy interesante la idea de jukinch para evitar los revotes.
Título: Re: Como haceil para leer interruptores?
Publicado por: excalibur1491 en 25 de Febrero de 2011, 12:53:06
jukinch, genial tu explicacion de las bandera, ;) lo entendi perfecto , mil gracias ;)


TEMA ANTIRREBOTE:

            normalmente se usa una espera de x milisegundos para evitar que una pulsación mecánica se interprete digitalmente como varias pulsaciones por los motivos que ya conoces.
            Pero eso no es lo óptimo. ¿Por que esperar X tiempo?
            Se puede comprobar en menos tiempo que X.
Para ello debes crear un algoritmo que verifica si el botón se pulsó, y además se mantuvo pulsado durante x iteraciones.

Un ejemplo a continuación:

do   {

     if (input(PIN_B0) ) // controla si el botón se pulsó
         arranca=arranca+1;
      ELSE
          IF (ARRANCA>1)
            arranca=arranca-1;

 }while(arranca<=100);   // el valor de 100 lo podés variar en más o en menos para afinarlo a tu necesidad.


Es poco probable que tengas un ruido que dure 100 iteraciones seguidas con el estado alto de RB0.
Y así el tiempo de este algoritmo es mucho menor que esperar 1 milisegundo. Se entiende?
mm, no, no se entiende, xD
si arrnca==0, y pulsas B0, arranca==1 y el bucle vuelve a empezar.. si sigues pulsando, arranca==2  y luego arranca==1 y asi hasta el infinito... y arranca no será >100 jamas y estaras en el bucle apra siempre.. no??
y este antirrebotes, donde se pone? en la interrupcion o en la funcion principal??

otra vez: gracias ;)
Título: Re: Como haceil para leer interruptores?
Publicado por: AngelGris en 25 de Febrero de 2011, 13:00:37
  La variable arranca se incrementa mientras el botón esté presionado. Se decrementa si el botón es soltado.

  Hay que tener en cuenta que un reboto sería algo así como presionar y soltar varias veces el botón.

  El loop sirve para leer el puerto varias veces seguidas, hasta que la variable arranca llegue hasta 100.


  Ahora a mí me están entrando algunas dudas..... pero no quiero complicarte excalibur1491, así que luego consultaré
Título: Re: Como haceil para leer interruptores?
Publicado por: jukinch en 25 de Febrero de 2011, 13:17:44
excalibur1491:
                Por ahora olvidate del algoritmo del antirebote y probá sólo con bajar el delay de 100ms a 20 ms para ver que resultado tenés.
                Dependiendo de la calidad del botón podés llegar hasta los 5ms. Pero es cuestión de que pruebes.
                     Saludos.
                         Jukinch
Título: Re: Como haceil para leer interruptores?
Publicado por: excalibur1491 en 25 de Febrero de 2011, 14:53:42
excalibur1491:
                Por ahora olvidate del algoritmo del antirebote y probá sólo con bajar el delay de 100ms a 20 ms para ver que resultado tenés.
                Dependiendo de la calidad del botón podés llegar hasta los 5ms. Pero es cuestión de que pruebes.
                     Saludos.
                         Jukinch

sip, todo perfecto, con 20 ms va de perlas :):)
pues muchisimas gracias por todo y a todos :)

ya entendi tu bucle anti rebotes, como no has puesto los { } pense que era "else if" y no entendia.. pero es else "osea si no se ha apretado"
y junto con la explicacion de angel gris he entendido: arranca aumenta si se esta pulsando el interruptor Bien pulsao... sino lo decrementas

un millon de gracias.

una ultima dudilla: si quiero que pareczca que un monton de diodos estan encendido pero que solo hay uno encendido a la vez.. de cuanto pongo el delay entre que se enciende y que se apaga cada led?

Título: Re: Como haceil para leer interruptores?
Publicado por: jukinch en 25 de Febrero de 2011, 15:11:43
Que bueno que funcione. Gracias a AngelGris también.
 Perdón por el error de los {   }     

Con respecto al tiempo que preguntas para que parezca todo encendido hacé el cálculo para que se prenda la misma columna de leds unas 20 veces por segundo como mínimo. Con eso el ojo humano ya no lo va a ver parpadeando.

Me hiciste acordar a un artículo que publicó un amigo sobre POV persistent of vision.
http://www.neoteo.com/pov-escribe-con-luz-en-el-aire.neo
             Jukinch
Título: Re: Como haceil para leer interruptores?
Publicado por: pocher en 28 de Febrero de 2011, 04:17:44
Una pregunta respecto a:

Código: [Seleccionar]
do   {

     if (input(PIN_B0) ) // controla si el botón se pulsó
         arranca=arranca+1;
      ELSE
          IF (ARRANCA>1)
            arranca=arranca-1;

 }while(arranca<=100);


¿Cuando sale del while?
Título: Re: Como haceil para leer interruptores?
Publicado por: Nocturno en 28 de Febrero de 2011, 04:19:46
Según lo interpreto, si la entrada B0 permanece a nivel alto durante más de 100 iteraciones, saldrá del while, ¿no?
Título: Re: Como haceil para leer interruptores?
Publicado por: pocher en 28 de Febrero de 2011, 05:33:06
Sí, para 101 saldria del while, pero ahora para una nueva lectura que hacemos? arranca=0 ----> se quedaria enganchado en el while.
Título: Re: Como haceil para leer interruptores?
Publicado por: pocher en 28 de Febrero de 2011, 05:44:38
Según lo veo si este trocito de programa fuese para pulsadores RB4..RB7 y este programita se pusiese dentro de la interrupción sí que serviria para los antirebotes haciendo al acabar arranca=0.
Título: Re: Como haceil para leer interruptores?
Publicado por: AngelGris en 28 de Febrero de 2011, 10:01:18
  El código funciona como lo comenta Nocturno, a más de 100 interacciones sale del while. A ese código le encontré, quizá, un defecto y es que si la interrupción se produce por cambio de flanco pero cuando soltamos la tecla, el pulsador nunca va a leer un nivel alto y por lo tanto no saldrá del while.

  Pero imagino que se podría solucionar de la siguiente manera....

Código: C
  1. arranca = 125;
  2. do
  3. {
  4.   if (input(PIN_B0) ) // controla si el botón se pulsó
  5.     arranca = arranca+1;
  6.   ELSE
  7.     arranca = arranca-1;
  8.  }
  9. while (arranca < 250) && (arranca > 0);

  De esa manera si está mucho tiempo suelto el botón también saldría del while.
Título: Re: Como haceil para leer interruptores?
Publicado por: pocher en 01 de Marzo de 2011, 07:42:54
Te refieres a que si la interrupción es por flanco descendente?

Si es así, solo habría que cambiar:

Código: [Seleccionar]
do   {

     if (!input(PIN_B0) ) // controla si el botón se pulsó
         arranca=arranca+1;
      ELSE
          IF (ARRANCA>1)
            arranca=arranca-1;

 }while(arranca<=100);
Título: Re: Como haceil para leer interruptores?
Publicado por: AngelGris en 01 de Marzo de 2011, 09:02:39
  No exactamente.
  Muchas veces los pulsadores también generan rebote cuando los soltamos.
  Suponiendo que el pulsador une el pin del pic con VCC, cuando lo soltamos el pin quedaría a GND por medio de una resistencia. Pero con la rutina, tal cual estaba originalmente, se esperaba a que haya x cantidad de intereacciones y se salía sí y solo sí había muchas con el pin en alto. Por ende si se la utilizaba para tratar de eliminar el rebote cuando se suelta el pulsador, nunca se iba a salir, ya que no iba a haber muchas interacciones con el pin en alto.
Título: Re: Como haceil para leer interruptores?
Publicado por: pocher en 02 de Marzo de 2011, 05:59:23
Los pulsadores siempre generan rebotes cuando los soltamos.

Supongo que cuando te refieres a "por cambio de flanco" te estas refiriendo a por cambio de estado en pines RB4..RB7 ¿es así? , conviene aclararlo porque si no, nos liaremos.

Si la interrupción es por cambio de estado en RB4..RB7, efectivamente al soltar la tecla de nuevo se entraria en la interrupción y como RB4=0, no se saldria del while.

Código: [Seleccionar]
#INT_RB
interrupcion_RB4_RB7()
{
arranca=0;
do   {

     if (input(PIN_B4) ) // controla si el botón se pulsó
         arranca=arranca+1;
     else
          if(arranca>1)
             arranca=arranca-1;
 }while(arranca<=100);
.
.
.
 

La solución es como dices:
Código: [Seleccionar]
#INT_RB
interrupcion_RB4_RB7()
{
      arranca = 0;
      do
      {
       if (input(PIN_B4) ) // controla si el botón se pulsó
         arranca = arranca+1;
       else                              //Se ha quitado el  if(arranca>1)
         arranca = arranca-1;
      }
      while (arranca < 100) && (arranca > 0);      //La variable arranca debe se definida como signed
 

Si la interrupción es por flanco ascendente ó descendente en RB0, no habrían problemas y se mantendría el código original de jukinch:

Por flanco ascendente:

Código: [Seleccionar]
#INT_EXT
interrupcion_RB0()
{
      arranca = 0;
      do   {
     if (input(PIN_B0) ) // controla si el botón se pulsó
         arranca=arranca+1;
      ELSE
          IF (ARRANCA>1)
            arranca=arranca-1;
 }while(arranca<=100);

Por flanco descendente:

Código: [Seleccionar]
#INT_EXT
interrupcion_RB0()
{
      arranca = 0;
      do   {
     if (!input(PIN_B0) )          // esta es la unica modificacion
         arranca=arranca+1;
      ELSE
          IF (ARRANCA>1)
            arranca=arranca-1;
 }while(arranca<=100);

Espero no haberme equivocado.

Un saludo
Título: Re: Como haceil para leer interruptores?
Publicado por: jukinch en 02 de Marzo de 2011, 06:53:46
Gracias Pocher por tus correcciones y tu tiempo. Muy claras tus explicaciones.
Conoces algún otro algoritmo de antirebote que no sea por espera de un tiempo X?
             Saludos.
                         Jukinch
Título: Re: Como haceil para leer interruptores?
Publicado por: AngelGris en 02 de Marzo de 2011, 09:33:06
Los pulsadores siempre generan rebotes cuando los soltamos.

Supongo que cuando te refieres a "por cambio de flanco" te estas refiriendo a por cambio de estado en pines RB4..RB7 ¿es así? , conviene aclararlo porque si no, nos liaremos.

Si la interrupción es por cambio de estado en RB4..RB7, efectivamente al soltar la tecla de nuevo se entraria en la interrupción y como RB4=0, no se saldria del while.


  Sí, me refería a cambio de estado, pido disculpas si generé confusión.


................

La solución es como dices:
Código: [Seleccionar]
#INT_RB
interrupcion_RB4_RB7()
{
      arranca = 0;
      do
      {
       if (input(PIN_B4) ) // controla si el botón se pulsó
         arranca = arranca+1;
       else                              //Se ha quitado el  if(arranca>1)
         arranca = arranca-1;
      }
      while (arranca < 100) && (arranca > 0);      //La variable arranca debe se definida como signed
 



  En ese código, yo le asignaría el valor 125 (para que pueda contar aproximadamente 125 interacciones con el botón pulsado y también 125 interacciones con el botón suelto) a la variable arranca. Y en cuanto a que tenga que ser definida como signed, creo que no es necesario. Ten en cuenta que cuando la variable valga 0, saldrá del while y por lo tanto no se corre riesgo de que se siga decrementando por error.

  Quedaría así...

Código: C
  1. arranca = 125;
  2. do
  3. {
  4.   if (input(PIN_B4) )         // controla si el botón se pulsó
  5.   arranca = arranca+1;
  6.   else                              //Se ha quitado el  if(arranca>1)
  7.     arranca = arranca-1;
  8. }
  9. while (arranca < 250) && (arranca > 0);
Título: Re: Como haceil para leer interruptores?
Publicado por: pocher en 02 de Marzo de 2011, 13:34:47
Tienes razón AngelGris, pido disculpas por el error.

Repito el código de AngelGris para que quede claro.

Esta rutina genera antirebotes tanto al pulsar como al soltar la tecla:

Código: [Seleccionar]
#INT_RB
interrupcion_RB4_RB7()
{
      arranca = 125;
      do
      {
       if (input(PIN_B4) ) // controla si el botón se pulsó
         arranca = arranca+1;
       else                              
         arranca = arranca-1;
      }
      while (arranca < 250) && (arranca > 0);  
.
.
.

 Además también serviría tanto para flanco ascendente como descendente en RB0:

Código: [Seleccionar]
#INT_EXT
interrupcion_RB0()
{
      arranca = 125;
      do
      {
       if (input(PIN_B0) ) // controla si el botón se pulsó
         arranca = arranca+1;
       else                             
         arranca = arranca-1;
      }
      while (arranca < 250) && (arranca > 0);   
.
.
.
Título: Re: Como haceil para leer interruptores?
Publicado por: tannke en 03 de Marzo de 2011, 09:00:08
Muy buenas, sobre el tema este del antirrebote, en el primer ejemplo el del "while(arranca<=100);" yo entiendo que sí se saldría del while (pensando que la variable arranca es de tipo unsigned char) ya que 0-1=255 por lo que o por arriba o por abajo al 100 llegaremos. Es más con el "<=" al 255 ya saldría del bucle.

Un saludo
Título: Re: Como haceil para leer interruptores?
Publicado por: pocher en 03 de Marzo de 2011, 10:29:30
Hola tannke. Tienes razón.

Al soltar la tecla se meteria en la interrupción, decrementaría y la variable arranca sería 255, con lo que saldría del bucle while.

El código sería este:

Código: [Seleccionar]
#INT_RB
interrupcion_RB4_RB7()
{
      arranca = 0;
      do
      {
       if (input(PIN_B4) ) // controla si el botón se pulsó
         arranca = arranca+1;
       else                             
         arranca = arranca-1;
      }
      while (arranca<= 100) ;     
 

El problema que le veo, es que no generaría temporización antirebotes al soltar la tecla.

PD. Hola jukinch, perdona por no contestarte, se me había pasado. A parte de los antirebotes software por tiempo solo conozco los antirebotes hardware, que se pueden implementar de diversas formas.

Un saludo.