como se interpreta este if ?

hola gente del foro estaba comenzando a estudiar los programas en C para micros de 32 bits pero me quedé anclado en un if que no se como es que funciona, le puse los comentarios de que es lo que hace pero no se porque lo hace, a ver si alguien me da una manito para entenderlo :oops:

while(1) // bucle infinito que enciende y apaga un led conectado al pin 17
{
if(IOPIN0 & 0x00020000) //Evaluamos el estado actual del pin P0.17
{
IOCLR0 =0x00020000; // Si está prendido lo apagamos
}
else
{
IOSET0 = 0x00020000; //Si esta en "0" lo ponemos a "1"
}
}

esto es lo que no entiendo como leerlo: if(IOPIN0 & 0x00020000) ?

no tendria que ser algo asi ? f((IOPIN0 & 0x00020000)==0) ?
gracias !
 
Última edición:
Cuando se ejecuta la operación AND (&) se modifica el bit de estado Z. Por lo tanto no hace falta la comprobación ==
 
Última edición:
Lo que estás haciendo es probar el bit con una AND, imaginate que hablamos de 8bits (para que lo veas más fácil) y tenemos esta condición:

- IOPIN0=0x4f
- Queremos saber que pasa con el bit 7 (B0-B7)

Entonces en tú código estarías haciendo algo así:

IOPIN0 & 0x80 => eso equivale a esto => 0x4f & 0x80 => que en binario es esto => 0b0100 1111 & 0b1000 0000 => el resultado es => 0b0000 0000 => en hexa => 0x00

Lo que estás haciendo es lo que se llama máscara (0x80), que te sirve para saber que pasa solamente con el bit 7, para luego ver su estado con el IF:

PHP:
if(IOPIN0 & 0x80) // Solo verifica que el resultado sea 0 o distinto de 0
   {
   //El bit 7 está en 1 => no nuestro caso
   }
else
   {
   //El bit 7 está en 0 => es nuestro caso
   }

Si IOPIN fuera igual a 0xAf (0b1010 1111), ahí si el bit 7 estaría en 1 y entrarías en la 1era condición del if. Ahora todo esto pensalo en 32bits (es lo mismo, pero con Nº más grandes).

Sugerencia:

Para no matarte demasiado con las máscaras (en 8 bits es sencillo, pero en 32 bits se vuelve tedioso), usá desplazamientos y defines (nuevamente pensemos en 8 bits):

- Desplazamiento: variable=(1<<2); => variable tomará este valor => 0b0000 0100 (el bit 2 vale 1), en forma mucho más práctica pude hacer una máscara, pero tiene un costo y es tener que hacer la operación desplazamiento a la hora de ejecutar la linea de código.

- Defines: en vez de trabajar con máscaras o desplazamientos en tú código, tené en cuenta que en un futuro si querés revisar el código que hiciste te volvés loco tratando de entender que significaba tal máscara, usá los defines.

PHP:
#define bit_7 (1<<7)...

Con eso estás definiendo a bit_7 como un desplazamiento que funciona como máscara, para luego usarlo de esta forma en un if (por ej.):

PHP:
if(IOPIN0 & bit_7)...

Fijate que es mucho más sencillo leer eso que 0x80 ó (1<<7) y si trabajamos con 32 bits el asunto se torna mucho más cómodo.
 
Última edición:
hola eduardo no entendi XD!
entonces esto como se lee ?

if(IOPIN0 & 0x00020000) traduccion por mi : Si IOPIN0 and 0x00020000 .... no hace nada! como que no veo donde esta la instruccion para que haga algo XD ! esta haciendo IOPIN0 AND un numero y despues que esta verificando ? ... no se ,, no entiendo
 
la condicional IF busca un resultado TRUE (1) o FALSE (0), cuando realizas IOPIN0 & 0x(valor) el resutado es el que interpreta el IF.... un resultado 0 se interpreta como FALSE y cualquier otro caso como TRUE
 
ah genial ahora lo entendi muchas gracias

igual lo del define que explico cosme estoy a siglos de entenderlo pero gracias igual !

saludos!
 
ah genial ahora lo entendi muchas gracias

igual lo del define que explico cosme estoy a siglos de entenderlo pero gracias igual !

saludos!

No te ahogues con un vaso de agua, pregunta que es lo que no entendiste y vemos como te lo explicamos.

Esto del define no es nada raro y vas a ver que te va a resultar muy útil y más cuando trabajas con 32 bits.

De momento te propongo que pruebes este cambio en tu código:

PHP:
#define puerto_17 0x00020000 // Ó como alternativa  #define puerto_17 (1<<17)

int main()
{
  ....
  while(1) // bucle infinito que enciende y apaga un led conectado al pin 17
    {
    if(IOPIN0 & puerto_17) //Evaluamos el estado actual del pin P0.17
      {
         IOCLR0 =puerto_17; // Si está prendido lo apagamos
      }
    else
      {
         IOSET0 = puerto_17; //Si esta en "0" lo ponemos a "1"
      }
    ....
    }
}
 
ok gracias

esto no lo entiendo : (1<<17)

esto mas o menos: #define puerto_17 0x00020000 no tendria que ser #define puerto_17 = 0x00020000

saludos!
 
ok gracias

esto no lo entiendo : (1<<17)

Esto es desplazamiento a la izquierda (tal vez en assembler lo viste como shifter). La cuestión es que eso se traduce como desplazar un 1 binario 17 veces a la izquierda. Ejemplos (en 8 bits):

(1<<0) = 0b0000 0001
(1<<1) = 0b0000 0010
(1<<2) = 0b0000 0100
....
(1<<6) = 0b0100 0000
(1<<7) = 0b1000 0000

Fijate que esto resulta muy útil para crear máscaras.

Como nota aparte, no solo podés desplazar un 1 binario, sino que podrías desplazar cualquier cosa, ej:

(3<<0) = 0b0000 0011
(3<<1) = 0b0000 0110
(3<<2) = 0b0000 1100
...
(3<<5) = 0b0110 0000
(3<<6) = 0b1100 0000

Incluso podrías hacer combinaciones de varias máscaras usando la OR:

(1<<7)|(1<<0)=0b1000 0001

En forma genérica:

Código:
([COLOR="Blue"]lo_que_desplazo[/COLOR][COLOR="Green"]<<[/COLOR][COLOR="Red"]cuanto_lo_desplazo[/COLOR])

Normalmente cuando haces este tipo de desplazamiento, el uC agrega 0's por la derecha.

Y un desplazamiento a la derecha sería:

Código:
([COLOR="Blue"]lo_que_desplazo[/COLOR][COLOR="Green"]>>[/COLOR][COLOR="Red"]cuanto_lo_desplazo[/COLOR])

Normalmente cuando haces este tipo de desplazamiento, el uC agrega 0's por la izq.

Ves que fácil es trabajar de esta forma en 8 bits, imaginate en 32 bits. Esto último por ej. es útil cuando tenés que poner en 1 o en 0 varios puertos usando el IOCLR0 ó el IOSET0:

PHP:
#define puerto_11 (1<<11)
#define puerto_22 (1<<22)
...

int main()
{
  IOSET0=puerto_22|puerto_11; // Mando a 1 lógico el puerto 22 y 11
  ...
}


esto mas o menos: #define puerto_17 0x00020000 no tendria que ser #define puerto_17 = 0x00020000

No, el define funciona así:

Código:
#define [COLOR="Blue"]Nombre_de_lo_que_defino[/COLOR] [COLOR="Red"]lo_que_defino[/COLOR]

Ejemplo:

Código:
#define [COLOR="Blue"]pepe[/COLOR] [COLOR="Red"]20[/COLOR]

A partir de ahora en el código cada vez que mencione a "pepe", el compilador lo tomará como si fuera 20 decimal.
 
Última edición:
genial la explicacion :aplauso: (y):D:apreton:

al desplazador lo habia visto como Barrel Shifter pero no lo habia entendido bien ... no se si es lo mismo que esto que me explicaste o tiene otras aplicaciones
 
Última edición:
Exacto, es eso, pero en vez de trabajar en forma directa sobre los registros, lo haces en C mediante una variable (habrá que ver como el compilador lo trabaja, pero eso ya es otra cosa).

Una de las ventajas que tienen los ARM, es que dentro de su ALU ya tienen incorporado un Barrel Shifter, con lo cual no necesitan muchos ciclos de maquina para realizar la operación.

Para cerrar el tema sobre el define, te doy un ejemplo donde su uso es muy útil, suponé que para un diseño durante la programación decidiste que el puerto 17 se encargue de manejar un Rele, si no usaras el define tú código sería algo así:

PHP:
int main() 
{ 
  .... 
  while(1) // Bucle principal
    { 
    .... // Bloque de código 1
         .... IOSET0 = 0x00020000; //acciono el Rele por alguna condición
    
    .... // Bloque de código 2
         .... IOSET0 = 0x00020000; //acciono el Rele por alguna condición
    .... 

      .... // Bloque de código 3
         .... IOCLR0 = 0x00020000; //desactivo el Rele por alguna condición

    .....//etc
    
    } 
}

Hasta ahí vas bien, pero suponé que el dia de mañana surge un problema o para facilitar el impreso necesitas cambiar el puerto que controla el Rele por otro, por ej. el puerto 1. Tendrías que modificar el puerto en todos los bloques de código donde manejaste el Rele, lo cual es muy poco práctico.

Entonces si hubieras usado el define desde el principio, ese cambio solo se daría en el propio define y no en todos los bloques de código donde manejaste el Rele. Ejemplo:

PHP:
#define puerto_rele (1<<17) 

int main() 
{ 
  .... 
  while(1) // Bucle principal
    { 
    .... // Bloque de código 1
         .... IOSET0 = puerto_rele; //acciono el Rele por alguna condición
    
    .... // Bloque de código 2
         .... IOSET0 = puerto_rele; //acciono el Rele por alguna condición
    .... 

      .... // Bloque de código 3
         .... IOCLR0 = puerto_rele; //desactivo el Rele por alguna condición

    .....//etc
    
    } 
}

Y el cambio por el puerto 1 solo sería este:

PHP:
#define puerto_rele (1<<1)

Como ves, esta es otra de las grandes ventajas que tiene C sobre assembler, aislarte un poco del hardware, pero mantener el concepto principal.
 
Última edición:
me funciono muy bien el programa conectando el LED al puerto 0 pin 17 (y)

pero ahora queria probar de conectarlo al puerto 1 y me vi como 20 veces el manual del LPC2148 y no veo donde dice como se configura este puerto, queria conectarlo al pin P1.24 porque la placa ya trae un led ahi :)

les adjunto el codigo completo para el led en el pin P0.17 (puerto 0) ( agregando los defines de cosmefulanito (y))

y ademas el manual del LPC2148

A ver si alguien me ayuda con los cambios que tendria que hacerle al codigo para cambiar del pin P0.17 al pin P1.24, gracias :) !! ( en el capilo 6 esta como utilizar los registros pinsel para configurar el puerto 0 como GPIO pero del puerto 1 no hay nada,, que raro ! tiene que estar pero no lo veo :rolleyes: )
 

Adjuntos

  • blinking led.txt
    844 bytes · Visitas: 2
  • manual version 2012_LPC2148_UM10139_Rev4.rar
    1.4 MB · Visitas: 2
Yo en algún momento lo había usado (en un LPC2132), pero no recuerdo bien, creo que tendrías que usar los registros IO1DIR/IO1SET/IO1CLR/IO1PIN (creo que es IO1PIN) y el PINSEL2 para definir si los tipos trabajan como GPIO o debug.

Probá con este código:

PHP:
#include "lpc214x.h"
#define pin_1_24 (1<<24)

int   main (void)
{
   //Definicion de variables
   int      j;
   /*Configuracion del GPIO P1.24*/
   PINSEL2 = 0;   // Todos los Puertos 1 como GPIO
   IO1DIR |= pin_1_24;   // P1.24 como output 
	
   IO1CLR = pin_1_24; //Si esta en "1" lo ponemos a "0"

   // Loop sin fin que prende y apaga los LED's.
      while(1)
      {
         if(IO1PIN & pin_1_24) //Evaluamos el estado actual de P1.24
            {
            IO1CLR = pin_1_24; // Si está prendido lo apagamos
            }
         else
            {
            IO1SET = pin_1_24; //Si esta en "0" lo ponemos a "1"
            }
          
         for (j = 0; j < 100000; j++ ); //Delay por soft
      }
}
 
en el simulador del keil FUNCIONA ! :aplauso: despues lo pruebo grabando el codigo en el lpc2148 a ver si no hace nada raro :D

bueno el tema es que con pinsel 2=0; definimos todos los pines del puerto 2 como GPIO!!!

deberia haber alguna forma de elegir solo la patita 24 como GPIO por si queremos usar el resto para otras funciones es raro que en el manual no este como hacer esto, ( osea no esta claro (para mi) "que trae dentro" el registro pinsel 2,,,el pinsel 0 y 1 estan bien claritos ) voy a averiguar un poco mas a ver si consigo esa info

PD: el compilador Keil acepta que el 1(uno) este asi: IO1DIR/IO1SET/IO1CLR/IO1PIN
o asi: IODIR1/IOSET1/IOCLR1/IOPIN1
Hay otros que no y te matas tratando de encontrar el error,,,ademas el Keil tiene para simular los codigos al estilo CCS o MPLAB , por eso me recomendaron usar keil saludos!
 
Última edición:
Por lo que entiendo del LP2132 (me imagino que en el 48 es lo mismo), es que el Puerto 1 está pensado para realizar debug/trace o funcionar como GPIO y si uno solo de sus puertos funciona como GPIO, deja de tener sentido que resto funcione para el debug/trace (ya que le faltaría 1 puerto), por eso el PINSEL2 funciona de esa forma.



Por ej:

PHP:
#define habilita_debug (1<<2)  
#define habilita_trace (1<<3)  
...
PINSEL2=habilita_debug; // Habilito los puertos 1.26 a 1.32 como Debug y dejo los puertos 1.16 a 1.25 como GPIO 
PINSEL2=habilita_trace; // Habilito los puertos 1.26 a 1.32 como GPIO y dejo los puertos 1.16 a 1.25 como TRACE 
PINSEL2=habilita_trace|habilita_debug; // Habilito los puertos 1.26 a 1.32 como Debug y dejo los puertos 1.16 a 1.25 como TRACE

Sobre el keil, ese es el IDE/compilador que suelo usar y efectivamente está bastante bueno el simulador que tiene incorporado que combinandolo con un proteus te das una idea de que tan bien estás encaminado. Después tenés otro que dicen que es muy bueno llamado IAR, pero todavía no lo llegué a usar.
 
Última edición:
ya que mencionaste el debug XD! .... segun me dijieron es para hacer la "simulacion fisica" digamos ,,,,y para eso se necesita un JTAG .... pero que es el JTAG ? o se puede hacer sin eso ?

y el TRACE que seria ?

saludos!
 
Las familia LPC justamente se destaca frente a otras en poder usar un JTAG "casero" sin necesidad de tener que comprar ningún accesorio especial.

El Jtag te permite debuggear en tiempo real tu uC paso a paso y mediante el keil ir viendo en que linea de código estás parado y ver como evoluciona, en otras palabras es como si fuera la simulación del keil en el que podés ejecutar las lineas de código paso a paso, pero haciendolo con el uC y no simulandolo. Osea podrías ir levantando todos los registros del uC y analizarlos a medida que vas ejecutando el código. Lo cual en un proyecto muy groso, es una herramienta muy importante.

El problema está en que ese Jtag "casero" lo tenés que hacer con el puerto paralelo y si no tenés puerto paralelo, fuiste ... tenés que comprarte uno usb.

Sobre el trace, me imagino que forma parte del JTAG y son los que le indica en que parte del código está parado el uC, igual no estoy del todo seguro ya que nunca usé el JTAG.
 
okas, voy a buscar a ver si encuentro para algun JTAG casero (y)

no sabes en que carpeta del KEIL estan las librerias ? no encuentro ni siquiera el archivo LPC214x.h y seguro que si esta porque los programas compilan bien ,, tampoco encuentro otras librerias ( si es que tiene) como para manejar teclados, LCD etc


y otra cosa que no veo en ningun manual del KEIL es si tiene funciones predefinidas, como ser el CCS para los pics tenia muchas y muy utiles por ejemplo : para hacer un retardo podia usar: Delay_ms(valor); ,y en el keil tengo que usar por ejemplo el ciclo for que hice en el programa que envie antes... el KEIL tampoco tiene funciones predefinidas ?


saludos!
 
Atrás
Arriba