Autor Tema: Programación en C para botones.  (Leído 19250 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Rodya

  • PIC10
  • *
  • Mensajes: 18
Programación en C para botones.
« en: 10 de Abril de 2010, 01:52:45 »
Hola, soy nuevo en el foro. Estoy comenzando con un poco de programación en C++ y ensamblador para un proyecto que tengo.

Estoy programando utilizando una tarjeta entrenadora EasyPic6 y el software de MikroC. Observe que se usa este código para la pulsación de un botón:

do {
    if (Button(&PORTB, 0, 1, 1)) {               // Detect logical one
      oldstate = 1;                              // Update flag
    }
    if (oldstate && Button(&PORTB, 0, 1, 0)) {   // Detect one-to-zero transition
      PORTC = ~PORTC;                            // Invert PORTC
      oldstate = 0;                              // Update flag
    }
  } while(1);   


Y aunque busco, no logro encontrar que es lo que significan los tres números del if, asumo que uno significa el número de bit del Puerto B, otro el voltaje TTL que debe tener para entrar al bucle de if, ¿pero que significa el tercero?

También, estuve revisando algunos ejemplos aquí de personas que usan software para evitar los rebotes, y hacen una lectura de un pin if(portc,0==0) y después solo escriben un delay para evitarlo, pero, ¿qué no debería haber una segunda lectura después de esperar el tiempo para asegurar el voltaje que se busca o escribir primero la instrucción de delay(ms) y luego escribir la instrucción de if?

De antemano una disculpa si la pregunta es muy de principiantes o no es muy clara, pero agradezco cualquier ayuda que me puedan ofrecer con esto.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Programación en C para botones.
« Respuesta #1 en: 10 de Abril de 2010, 03:01:06 »
Bienvenido al foro, Rodya.

Mira, esto es lo que dice la ayuda de MikroC:

Prototype unsigned short Button(unsigned short *port, unsigned short pin, unsigned short time, unsigned short active_state);
 
Returns Returns 0 or 255.
 
Description Function eliminates the influence of contact flickering upon pressing a button (debouncing).

Parameter port specifies the location of the button; parameter pin is the pin number on designated port and goes from 0..7; parameter time is a debounce period in milliseconds; parameter active_state can be either 0 or 1, and it determines if the button is active upon logical zero or logical one.
 
Requires Button pin must be configured as input.
 
Example Example reads RB0, to which the button is connected; on transition from 1 to 0 (release of button), PORTD is inverted:

do {
  if (Button(&PORTB, 0, 1, 1)) oldstate = 1;
  if (oldstate && Button(&PORTB, 0, 1, 0)) {
    PORTD = ~PORTD;
    oldstate = 0;
  }
} while(1);


Según parece los dos últimos parámetros de la función son:
- el tiempo que debe permanecer el botón pulsado para que se considere válido
- el botón se activa con lógica directa o inversa, o sea, con un 1 o con un 0

Desconectado Rodya

  • PIC10
  • *
  • Mensajes: 18
Re: Programación en C para botones.
« Respuesta #2 en: 10 de Abril de 2010, 10:33:52 »
Muchas gracias por tu respuesta Nocturno, estuve como loco buscando esta respuesta analizando el código en ensamblador y en un libro de programación en C (aunque no esta orientado a programar en PICs).

Una vez más, te lo agradezco.

Desconectado bigluis

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 511
    • Tutoriales de Qt C++
Re: Programación en C para botones.
« Respuesta #3 en: 10 de Abril de 2010, 12:19:56 »
Aunque si bien existe esta funcion para utilizar los botones en MikroC, no te recomiendo que la utilices ya que genera mucho codigo ASM lo que te alentara el programa y consumira mucha RAM

Es mejor que hagas una pequeña funcion propia en donde preguntes si esta o no pulsado el boton.

Por ejemplo si conectamos un boton al pin 0 de PORTB (RB0), activo en alto.:
Código: C#
  1. while(!PORTB.F0);//Mientras el boton no este presionado se mantiene en este ciclo.
  2.   delay_10ms();//Retardo necesario para evitar rebotes.
  3.  
  4.  //Aqui puedes escribir lo que deseas hacer luego de haber presionado el boton.
  5.  
  6. while(PORTB.F0);//Mientras mantengas presionado el boton permanecera en este ciclo.

Si quieres que sea activo en bajo lo que debes hacer es intercambiar la primera linea con la ultima linea y listo.

Si lo que deseas es que solo espere hasta que presiones y no espere hasta que suelte, quita la ultima linea y listo.

Compara cuanto porcentaje de memoria utilizan estos dos metodos para que compruebes el ahorro de memoria.
Tutoriales de Qt C++

No es necesario que hagamos Grandes cosas, sino que lo que hagamos sea importante.

SI la NECESIDAD es la MADRE del CONOCIMIENTO, SEGURAMENTE la PEREZA su TÍA.

Cuando el ARTE requiere de PRECISION le llamamos CIENCIA

Desconectado Rodya

  • PIC10
  • *
  • Mensajes: 18
Re: Programación en C para botones.
« Respuesta #4 en: 10 de Abril de 2010, 20:47:44 »
Gracias bigluis. Realmente estoy interesado en hacer el programa lo más eficiente posible (lo que significa que debo seguir leyendo mucho sobre MikroC, programación en C y ensamblador).

Ya estoy familiarizado con los conceptos básicos de C y con ensamblador, pero al momento de realizar implementaciones, como usar sensores, LCDs y botones comencé descargando los ejemplos que venían en la página del EasyPic y analizando lo que hace en código ensamblador, al parecer utilizan mucho funciones ya preestablecidas (por eso lo leo mejor en ensamblador), entonces ¿tu recomendarías que no utilice las librerías que vienen incluidas de LCDs, botones, etc.?

Muchas gracias por la información.

Desconectado bigluis

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 511
    • Tutoriales de Qt C++
Re: Programación en C para botones.
« Respuesta #5 en: 11 de Abril de 2010, 16:47:08 »
Si lo que buscas es eficiencia no te recomiendo usar MikroC, supongo que C18 o CCS son mejoeres.

Las librerias preestablecidas de MikroC como LCD, Teclado, Botones, ADC, etc... son muy buenas si deseas iniciarte en este mundo de los microcontroladores porque son sumamente faciles de usar, ademas el programa contiene un amplio sistema de ayuda, pero como te mencione antes ocupan demasiado espacio en memoria si lo comparas con codigos generados con CCS.

Otra razon por la que te no te recomiendo usar MikroC es que las funciones propias son muy cerradas, por ejemplo la funcion para leer datos del modulo ADC solo puede utilizar el reloj de entrada RC, esto significa que utiliza el modo más lento de adquisición de datos.

A continuacion muestro una libreria que desarrollé para trabajar con el teclado y el LCD con un 16F84.

Código: C
  1. /**************************************
  2. Libreria de Retardos en milisegundos
  3. **************************************/
  4.  
  5. void Ret_ms(short Time_ms){
  6.   for(;Time_ms>=0;Time_ms--)
  7.     Delay_ms(1);}
  8.  
  9.  
  10. /*************************************
  11. LIBRERIA LCD + teclado
  12. Autor: Luis Alberto Vargas Tijerino.
  13. Pais: Leon, Nicaragua
  14. Fecha: 13/11/09
  15.  
  16.     Forma de Conexion de 4bits por Defecto
  17.         para un nucleo PIC
  18.         PORTB= D7..4 y filas teclado
  19.         RB3 = EN
  20.         RB2 = RS
  21.         PORTB 0..3=columnas teclado
  22.  
  23.     Descripcion de Funciones
  24.         Lcd_caracter(caracter);
  25.             Esta funcion imprime un solo caracter en la posicion actual del Lcd
  26.         Lcd_comando(comando);
  27.             Esta funcion envia un comando al Lcd.
  28.         Lcd_Pos(Fila,Columna);
  29.             Esta funcion envia la posicion de:
  30.                 la fila 0 hasta 1
  31.                 la Columna 0 hasta 15.
  32.         Lcd_print(cadena)
  33.             Esta funcion sirve para imprimir cadenas varialbles escritas
  34.         Lcd_printf(Fila,Columna,cadena)
  35.             Estua funcion sirve para imprimir cadenas variables en una posicion determianda
  36.             de la pantalla
  37.         Lcd_printc(cadena)
  38.             Esta funcion sirve para imprimir cadenas constantes escritas
  39.         Lcd_printfc(Fila,Columna,cadena)
  40.             Esta funcion sirve para imprimir cadenas constantes en una posicion determianda
  41.             de la pantalla
  42.  
  43. **************************************/
  44.  
  45. #ifndef data_port
  46.     #define data_port PORTB
  47. #endif
  48.  
  49. #ifndef data_tris
  50.     #define data_tris TRISB
  51. #endif
  52.  
  53. #ifndef EN
  54.     #define EN PORTB.F3
  55. #endif
  56. #ifndef ENt
  57.     #define ENt TRISB.F3
  58. #endif
  59.  
  60. #ifndef RS
  61.     #define RS PORTB.F2
  62. #endif
  63. #ifndef RSt
  64.     #define RSt TRISB.F2
  65. #endif
  66.  
  67. #define Lcd_Pos(F,C) Lcd_comando(0x80+(F)*0x40+(C))
  68. #define Lcd_printf(F,C,Cadena) Lcd_Pos(F,C);Lcd_print(Cadena);
  69. #define Lcd_printfc(F,C,Cadena) Lcd_Pos(F,C);Lcd_printc(Cadena);
  70.  
  71. char guarda_tris;
  72.  
  73. void Lcd_escribe(char dato){
  74.     guarda_tris=data_tris;
  75.     data_tris=data_tris & 0x0f;
  76.     data_port=dato & 0xf0 | data_port & 0x0f;
  77.     EN=1;
  78.     Delay_80us();
  79.     EN=0;
  80.     data_tris=guarda_tris;}
  81.  
  82. void Lcd_envia(char dato){
  83.     Lcd_escribe(dato);
  84.     asm swapf FARG_Lcd_envia,1;
  85.     Lcd_escribe(dato);
  86.     Delay_80us();}
  87.  
  88. void Lcd_comando(char comando){
  89.     RS=0;
  90.     Lcd_envia(comando);
  91.     if(comando==1)Ret_ms(2);}
  92.  
  93. void Lcd_caracter(char caracter){
  94.     RS=1;
  95.     Lcd_envia(caracter);}
  96.  
  97. void Lcd_Inicia(){
  98.     RSt=0;
  99.     ENt=0;
  100.     EN=0;
  101.     RS=0;
  102.     Ret_ms(20);
  103.     Lcd_escribe(0x30);
  104.     Ret_ms(5);
  105.     Lcd_escribe(0x30);
  106.     Delay_500us();
  107.     Lcd_escribe(0x30);
  108.     Delay_500us();
  109.     Lcd_escribe(0x20);
  110.     Lcd_comando(0x28);
  111.     Lcd_comando(LCD_CLEAR);
  112.     Lcd_comando(LCD_FIRST_ROW);}
  113.  
  114. void lcd_print(char *cadena){
  115.     do{
  116.         Lcd_caracter(*cadena++);
  117.         asm{MOVF        FARG_Lcd_caracter,0
  118.             BTFSS       STATUS, Z}
  119.         }while(1);}
  120.  
  121. void lcd_printc(const char *cadena){
  122.     do{
  123.         Lcd_caracter(*cadena++);
  124.         asm{MOVF        FARG_Lcd_caracter,0
  125.             BTFSS       STATUS, Z}
  126.         }while(1);}
  127.  
  128. #ifndef column_port
  129.     #define column_port PORTB
  130. #endif
  131. #ifndef row_port
  132.     #define row_port PORTB
  133. #endif
  134.  
  135. const char Teclas[4][4]={{'7','8','9','/'},
  136.                          {'4','5','6','*'},
  137.                          {'1','2','3','-'},
  138.                          {'c','0','=','+'}};
  139.  
  140. char Keypad_polling(){
  141.     char i,j,lu;
  142.     row_port=0xE;
  143.     for (i=0;i<4;i++){
  144.         Delay_10us();
  145.         lu=PORTA;
  146.     if ((lu & 0xf) != 0xf){
  147.         for(j=0;j<4;j++){
  148.             if(lu.F0==0) return Teclas[j][i];
  149.             lu=lu>>1;}}
  150.     row_port=row_port<<1 | 0x10;}}
  151.    
  152. char column;
  153. char Keypad_liberar(){
  154.     char i=0,j=0;
  155.     column_port=0;
  156.     while(column_port==0XF0);
  157.     Delay_500us();
  158.     column=column_port | 0x0F;
  159.     for(row_port |= 0xE;(column_port&0xf0)==0xf0;row_port=row_port<<1 | 1,i++);
  160.     for(;column.F4!=0;column=column>>1,j++);
  161.     column_port = 0;
  162.     while(column_port!=0xf0);
  163.     return Teclas[j][i];}


Y por supuesto un ejemplo de como utilizarlo.

Código: C
  1. char kp;                 //Variable para guardar la tecla presionada
  2. char msg2[] = "Test";    //Arreglo de variables que se mostrara en la segunda
  3.                          //linea del LCD
  4.  
  5. #define EN PORTA.F0      //Definimos el pin que se encargara de manejar el pin
  6. #define ENt TRISA.F0     //EN del LCD.
  7.  
  8. #include "Lcd_4Bits.h"   //Definimos la libreria que utilizaremos para manejar LCD
  9. void main(){
  10.     TRISB=0XF0;          //Rb7..4 como entradas Rb3..0 como salidas
  11.     OPTION_REG.NOT_RBPU=0;//Habilitamos las resistencias de pull-up del PORTB
  12.     Lcd_inicia();         //Iniciamos el LCD
  13.     Lcd_comando(LCD_CURSOR_OFF);    //Apagamos el cursor del LCD
  14.     Lcd_printfc(0,0,"Hola Amigos"); //En la Fila 0 Columna 0 escribimos "Hola Amigos"
  15.     Lcd_printf(1,0,msg2);           //En la Fila 1 Columna 0 escribimos el msg2
  16.     Lcd_Pos(1,0);                   //Ubicamos el cursor en la Fila 1 Columna 0
  17.     while(1){                       //Inicio del ciclo infinito
  18.         kp=Keypad_liberar();        //Cuando la tecla presionada sea soltada el valor
  19.                                     //se guardara en la variable kp
  20.         Lcd_caracter(kp);}          //Se escribira el caracter proveniente del teclado en el LCD
  21.     }

y el esquema del circuito.



Como observamos en la figura otra ventaje de utilizar mi libreria es que solo necesitas 9 pines para manejar el Teclado y el LCD. A diferencia de otras librerias que por lo general utilizan 11 pines.

A continuacion adjunto el archivo *.rar
« Última modificación: 11 de Abril de 2010, 17:08:51 por bigluis »
Tutoriales de Qt C++

No es necesario que hagamos Grandes cosas, sino que lo que hagamos sea importante.

SI la NECESIDAD es la MADRE del CONOCIMIENTO, SEGURAMENTE la PEREZA su TÍA.

Cuando el ARTE requiere de PRECISION le llamamos CIENCIA

Desconectado Rodya

  • PIC10
  • *
  • Mensajes: 18
Re: Programación en C para botones.
« Respuesta #6 en: 11 de Abril de 2010, 20:29:32 »
Ya vi como utilizaste solo 9 pines para controlar el LCD y el Teclado... no sabía que se podía lograr con tan pocos pines. Yo en éste momento estoy utilizando el PIC que viene por default en el EasyPic6 16F877A, pero estoy conciente que por el número de pins que tiene y todas las otras funciones que no son necesarias para mi proyecto, es demasiado microcontrolador para lo que necesito. Ya terminé la mayoría del código necesario para hacer funcionar mi programa, e hice las pruebas en un Protoboard con el PIC alimentado (aunque he visto que muchas personas aquí usan Proteus, por lo que estoy pensando en adquirirlo también, al parecer es muy útil).

Sin embargo, es un proyecto que me gustaría hacer como un prototipo funcional, por lo que mi prioridad va a ser tratar de utilizar el microcontrolador más barato posible y eficientar todo en código. De ahí tengo unas preguntas que espero me puedas ayudar:

Si utilizo el mikroC para hacer la programación en C, pero no utilizo las librerías, ¿entonces aún me estaría generando mucho código ASM? A lo que me refiero es que quiero programar en C (podría hacerlo en ensamblador, pero para algunas cosas que voy a hacer, el código podría ser muy extenso) pero sin utilizar funciones que me generen el código extenso, como tu ya mencionaste antes.

Y, las definiciones del PORTB, PORTC, para simplificar la escritura al momento de hacer la programación, ¿de que librería se están sustrayendo? Cuando genero un nuevo proyecto en mikroC pregunta que PIC utilizo, y simplemente asumo que es de ahí donde toma esa librería propia del PIC.

Muchas gracias por los comentarios y los ejemplos de programación que pusiste, me han ayudado mucho.

Desconectado AntonioSolorzano

  • PIC10
  • *
  • Mensajes: 1
Re: Programación en C para botones.
« Respuesta #7 en: 22 de Julio de 2010, 18:33:49 »
hola, apenas me estreno en esto de los pics, estoy haciendo un algoritmo para controlar la presencia de personas en una habitacion, por ahora tengo este algoritmo;
void main () {

TRISA = 0XFF;
TRISB = 0;
PORTB = 0x00;
ADCON1 = 0x06;

lectura:
if (PORTA.F0==1)
  { {PORTB = 0x12};
   else {PORTB = 0};
    }
  goto lectura;
   }

pero no es funcional, en la simulacion de proteus activa las salidas al pulsar la entrad, pero luego no se desactivan al desconectar el pushbutton de RA0,

gracias

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Programación en C para botones.
« Respuesta #8 en: 22 de Julio de 2010, 18:51:00 »
hola, apenas me estreno en esto de los pics, estoy haciendo un algoritmo para controlar la presencia de personas en una habitacion, por ahora tengo este algoritmo;
void main () {

TRISA = 0XFF;
TRISB = 0;
PORTB = 0x00;
ADCON1 = 0x06;

lectura:
if (PORTA.F0==1)
  { {PORTB = 0x12};
   else {PORTB = 0};
    }
  goto lectura;
   }

pero no es funcional, en la simulacion de proteus activa las salidas al pulsar la entrad, pero luego no se desactivan al desconectar el pushbutton de RA0,

gracias

Falta un bucle infinito, sino se realiza una sola vez y luego quien sabe que hace el micro. Hay un goto, que en C suele no utilizarse, no se recomienda. Lo mismo seria:


Código: C
  1. void main () {
  2.  
  3. TRISA = 0XFF;
  4. TRISB = 0;
  5. PORTB = 0x00;
  6. ADCON1 = 0x06;
  7.  
  8. while(1){
  9. if (PORTA.F0==1){
  10.     PORTB = 0x12;
  11. }else{
  12.     PORTB = 0;
  13. }
  14. }
  15. }


saludos!
« Última modificación: 22 de Julio de 2010, 18:53:10 por Suky »
No contesto mensajes privados, las consultas en el foro

Desconectado Masterboy1980

  • PIC10
  • *
  • Mensajes: 15
Re: Programación en C para botones.
« Respuesta #9 en: 10 de Enero de 2012, 05:15:46 »
Hola, una pregunta ¿que indicas al compilador cuando escribes las siguientes sentencias?

#ifndef column_port
   #define column_port PORTB
#endif
#ifndef row_port
   #define row_port PORTB
#endif

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Programación en C para botones.
« Respuesta #10 en: 10 de Enero de 2012, 09:29:07 »
Que función cumple PORTB  :mrgreen:
No contesto mensajes privados, las consultas en el foro

Desconectado Masterboy1980

  • PIC10
  • *
  • Mensajes: 15
Re: Programación en C para botones.
« Respuesta #11 en: 10 de Enero de 2012, 13:59:08 »
Amigo quedé en las mismas, se que habla de columnas y renglones, que es lo que al final para eso va a servir el PORTB pero ¿funcionaría para lo mismo si no pone esas "definiciones"?

Desconectado aitorsp

  • PIC18
  • ****
  • Mensajes: 296
Re: Programación en C para botones.
« Respuesta #12 en: 10 de Enero de 2012, 15:08:33 »
Aunque si bien existe esta funcion para utilizar los botones en MikroC, no te recomiendo que la utilices ya que genera mucho codigo ASM lo que te alentara el programa y consumira mucha RAM

Es mejor que hagas una pequeña funcion propia en donde preguntes si esta o no pulsado el boton.

Por ejemplo si conectamos un boton al pin 0 de PORTB (RB0), activo en alto.:
Código: C#
  1. while(!PORTB.F0);//Mientras el boton no este presionado se mantiene en este ciclo.
  2.   delay_10ms();//Retardo necesario para evitar rebotes.
  3.  
  4.  //Aqui puedes escribir lo que deseas hacer luego de haber presionado el boton.
  5.  
  6. while(PORTB.F0);//Mientras mantengas presionado el boton permanecera en este ciclo.



Quizas no sea necesario el delay_10ms() porque debido a la velocidad a la que pulsas cualquier boton ya genera un retardo minimo que seguro que es superior a 10mseg

Desconectado Masterboy1980

  • PIC10
  • *
  • Mensajes: 15
Re: Programación en C para botones.
« Respuesta #13 en: 10 de Enero de 2012, 15:21:51 »
Me parece interesante como bigluis realiza sus librerías denota un gran estudio de programación en C y conocimiento de pics, sin embargo me siguen intrigando esas definiciones pues me parecería redundate usar librerías para hacer otras librerías, pienso que le faltó explicar su metodología y me enredo. me bajé unos videos de programación en C pero todavía no tengo el que refiere a definiciones.

Desconectado jukinch

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 608
Re: Programación en C para botones.
« Respuesta #14 en: 11 de Enero de 2012, 11:04:24 »
Masterboy1980:
     Este fragmento de código:

Código: C
  1. #ifndef column_port
  2.    #define column_port PORTB
  3. #endif
  4. #ifndef row_port
  5.    #define row_port PORTB
  6. #endif

     Son directivas del preprocesador.
#define es una directiva
e #ifndef #endif es otra.

con la directiva #define  El preprocesador reemplazará en el código todas las palabras que encuentre column_port por la palabra PORTB

La directiva #ifndef
#endif
en este caso se usa para prevenir la doble inclusión. Hay casos en el que el código está distribuido en varios archivos. Entonces así se evita que esté definido en varios de ellos.


podés ver más información aquí:

http://es.wikipedia.org/wiki/Preprocesador_de_C

http://www.programatium.com/manuales/c/13.htm#SECTION001310000000000000000

página 36 del tutorial de suky http://www.micros-designs.com.ar/tutorial-mplab-c18/

                 Saludos.
                         Jukinch
« Última modificación: 11 de Enero de 2012, 11:20:47 por jukinch »
"Divide las dificultades que examinas en tantas partes como sea posible para su mejor solución." -René Descartes


 

anything