Pregunta sobre C de HiTech

Estoy haciendo un programa en HTPICC, y me surge una duda. ¿Hay alguna forma de acceder a un bit de una variable sin haber declarado antes una variable de tipo bit apuntando a ese mismo bit? Me refiero a algo equivalente a las instrucciones de ensamblador BSF, BCF, BTFSC, y BTFSS.

Me extraña que no haya una sintaxis que permita hacer referencia a un bit de una variable, pero no encuentro nada al respecto en el manual, y en tutoriales genéricos de ANSI-C, ni siquiera hacen referencia a objetos de tipo bit.

--
Saludos de Jose Manuel Garcia
jose.mgg@terra.es
 Click to see the full signature
Reply to
Pepitof
Loading thread data ...

Depende del tipo con el que trates, si es una char, normalmente tienes una array de char's porque que puedes acceder a ese elemento en concreto, si es una int la unica manera es hacer una operacion logica con ese integer y ver si te da uno o cero. Creo que me explicado... sino lo dices y se propone un ejemplo :D

--
www.escienciaelectronica.org  La pagina de es.ciencia.electronica

Saludos.
 Click to see the full signature
Reply to
RooT

Ojito que no me explique bien realmente, tienes que hacer un desplazamiento > tras eso tienes en la variable un 1 o un 0, sino pues ahi que comprar por

2^(n-1). Es lo maximo que he llegado yo en C ha hacer con binarios, porque es que creo que no hay, absolutamente nada mas para tratar temas binarios.

P.D: El concepto bit existe, pero como sabemos en un pic sacar un bit de la memoria... es igual de trabajoso que sacar 8, es mas, creo que ni si quiera podriamos tener 8 variables de tamaño bit agrupadas en un byte, porque no habria manera de apuntarlas en el direccionamiento (no estoy muy seguro de esto), y ya seria a nivel software.

--
www.escienciaelectronica.org  La pagina de es.ciencia.electronica

Saludos.
 Click to see the full signature
Reply to
RooT

Seguro que te has explicado, pero yo no lo he entendido... ;-))

A ver, yo tengo una variable declarada así:

unsigned char mi_variable;

Y, pongamos por caso, quiero cambiar el valor del bit 3 de esa variable. Entonces podría escribir algo así;

mi_variable &= 0b00001000;

para poner ese bit a 1, o bien:

mi_variable |= 0b11110111;

para poner ese bit a 0. Sin embargo, con esto, el compilador genera en ensamblador una secuencia de dos instrucciones. Por ejemplo para el AND saldría algo como:

MOVLW 0b00001000 ANDWF mi_variable, F

Yo lo que pregunto es si existe una forma de acceder directamente a los bits de una variable. No sé, quizás algo como "mi_variable.3" o algo así (esto ya lo he probado y no va, claro), de forma que el código generado sea algo así:

BSF mi_variable, 3

--
Saludos de Jose Manuel Garcia
jose.mgg@terra.es
 Click to see the full signature
Reply to
Pepitof

Jeje, me he liado con los and y los or, así que lo repito corregido para no liar follón.

Seguro que te has explicado, pero yo no lo he entendido... ;-))

A ver, yo tengo una variable declarada así:

unsigned char mi_variable;

Y, pongamos por caso, quiero cambiar el valor del bit 3 de esa variable. Entonces podría escribir algo así;

mi_variable |= 0b00001000;

para poner ese bit a 1, o bien:

mi_variable &= 0b11110111;

para poner ese bit a 0. Sin embargo, con esto, el compilador genera en ensamblador una secuencia de dos instrucciones. Por ejemplo para el AND saldría algo como:

MOVLW 0b11110111 ANDWF mi_variable, F

Yo lo que pregunto es si existe una forma de acceder directamente a los bits de una variable. No sé, quizás algo como "mi_variable.3" o algo así (esto ya lo he probado y no va, claro), de forma que el código generado sea algo así:

BSF mi_variable, 3

--
Saludos de Jose Manuel Garcia
jose.mgg@terra.es
 Click to see the full signature
Reply to
Pepitof

Hace tiempo que no manejaba el compilador de HiTech, fue el primero que use y aunque trabaja muy bien, las funciones del compilador CCS me hicieron dejar a un lado el HiTech. Acabo de hacer una prueba, y para modificar el valor de algun bit es tan sencillo como simplemente asignando el valor de la patilla correspondiente, por ejemplo si quiero poner el valor del bit 5 del PORTB hago:

RB5=1;

Por medio de la directiva define se puede asignar un nombre mas apropiado, por ejemplo

#define Led1 RB5

Led1=0; //Apagar led

Led1=1; //Activar

el equivalente en asm para las instrucciones anteriores que entrega el compilador es un bcf 0x06,05 y bsf 0x06,05 respectivamente. Tambien valen estos nombres especiales para leer el valor de un bit en particular:

while(RB0) { ..... }

o k=RB4;

por dar algunos ejemplos. En el CCS estan las instrucciones output_low(PIN) y output_high(PIN).

Saludos

Reply to
FlyBoy

Sí, lo que comentas es válido, pero sólo porque en la librería correspondiente a cada modelo de PIC, que es llamada cuando incluyes la librería PIC.H, están declaradas variables de tipo bit coincidiendo con todos esos bits (ports, tris, flags, bits de configuración, etc), uno a uno.

Cuando el bit sobre el que quieres actuar ha sido declarado como variable de tipo bit, efectivamente, el compilador genera instrucciones completamente optimizadas, tipo BSF, BCF, etc.

Yo me refiero a manejar bits sin haber declarado variables que apunten a ellos. Por ejemplo, pongamos por caso que quiero testear el estado del 5º bit de TMR0, para implementar por soft el parpadeo de unos LEDs. Podría hacerlo añadiendo una declaración como esta:

static volatile bit TMR0_5 @ ((unsigned)&TMR0*8)+5;

y ya podría acceder a ese bit, utilizando la variable de tipo bit TMR0_5 que he declarado, y el compilador generaría el código perfectamente optimizado.

Pero supón ahora que lo que quiero es manejar 240 bits correspondientes a 30 bytes (por ejemplo para manejar una matriz de LEDs). Parece una locura declarar 240 variables de tipo bit si pretendo acceder a esos bits uno a uno, pero por otro lado, si accedo a ellos utilizando instrucciones orientadas a bytes, el código generado no estará suficientemente optimizado.

Lo que pregunto es si existe una sintaxis específica que permita acceder a cada bit de un byte, sin haber declarado antes una variable de tipo bit apuntando a cada bit.

--
Saludos de Jose Manuel Garcia
jose.mgg@terra.es
 Click to see the full signature
Reply to
Pepitof

Nada, olvidad la pregunta. Acabo de encontrar la respuesta en las faq de HiTech (juro que las había mirado, pero no la vi).

--
Saludos de Jose Manuel Garcia
jose.mgg@terra.es
 Click to see the full signature
Reply to
Pepitof

C estándar no tiene forma de acceder a bits de variables, la manera es con las operaciones and y or. Sin embargo es tarea del compilador detectar estas instrucciones y generar código óptimo.

Pepitof expuso:

Bueno, es el apaño que le han hecho ante esta necesidad. ¿Has probado a crear una array con esto? static volatile bit TMR0_5[240] @ ((unsigned)&TMR0*8); (o similar)

Reply to
Jeroni Paul

Pues la verdad, no lo he probado, pero juraría haber leído en el manual que no se pueden declarar arrays de tipo bit.

La solución que propone HiTech en sus faq es bastante elegante. Viene a ser algo como definir un nuevo tipo, que es una estructura compuesta por 8 variables de tipo bit (esto sí está permitido), algo como esto:

typedef struct { unsigned b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1; } tipo_bits;

Entonces, al declarar la variable a cuyos bits quieres acceder, lo haces como la unión de una variable char y una variable tipo_bits:

union both { unsigned char byte; //byte es el nombre de la variable char tipo_bits bits; //bits es el nombre de la variable tipo_bits } variable;

A partir de ahí, para acceder a la variable escribirías "variable.byte" y para acceder por ejemplo al bit 2, escribirías "variable.bits.b2".

Lo he probado, y de esta forma el código generado es óptimo. En la faq proponen otras formas, pero basadas todas en usar and y or de bytes completos, con la consiguiente pérdida de optimización.

--
Saludos de Jose Manuel Garcia
jose.mgg@terra.es
 Click to see the full signature
Reply to
Pepitof

Si el compilador fuera lo sufientemente inteligente (al estilo de los que usamos ahora para PC), una instruccion del tipo:

if( varbyte & 0x10 ) loquesea();

testaría ese bit con la instruccion específica del PIC y no realizaría el and.

lo mismo pasaría con instruciones del tipo:

varbyte &= 0xEF; varbyte |= 0x10;

que se traducirían por un SET o RESET bit. Compruebalo no vaya a ser que lo hayan hecho bien. En el CSS yo hice unas comprobacion de ese estilo y el resultado fué bastante decepcionante.

AÑADO: Acabo de leer que lo hace bien así: int foo; foo |= 0x40; will produce the instruction bsf _foo,6

creo que exite la posibilidad de declarar una variable tipo bit, declara entonces un array de variables tipo bit en la direccion "cero" de memoria (o en otra zona si prefieres), y accede usando el operador [], el íncide será el numero de bit en el array.

Otra opcion es usar un puntero apuntando al byte, forzar un cast a un puntero de tipo bit, sumarle el numero de bit y "desreferenciar" el puntero: *puntero = xxxx

Ejemplo: *((bit*) 0xCD2) = 0; *((bit*) 0xCD2) = 1;

En este caso 0xCD2 es la direccion de un bit, es decir que es el bit numero 2 de la direccion 0xCD2/8.

DESCARGA DE RESPONSABILIDADES: Todo lo anterior lo digo "a ojo de buen cubero", porque no lo se seguro ni lo he comprobado.

Saludos :-) -Pedro-

formatting link

Reply to
Pedro Maicas

Flipante, ayer escribi otro mensaje pero aparece ahora, en fin... vaya mierda.

Esta es la otra opcion, que yo pensaba que no era posible (mi P.D del segundo mensaje) pero es que eso ya es optimizacion del propio generador de codigo. Porque si meto eso en el gcc, no me va generar algo de desplazamiento ni de coña... lo detectara y generara instrucciones optimas para eso, sabiendo sobre todo que en los pics es muy necesario trabajar con bites sueltos.

--
www.escienciaelectronica.org  La pagina de es.ciencia.electronica

Saludos.
 Click to see the full signature
Reply to
RooT

"Pedro Maicas" escribió en el mensaje news: snipped-for-privacy@4ax.com...

Pues no, lo acabo de probar y hace el and y luego comprueba si el resultado es cero.

Joder, pues esto sí que funciona. Estaba seguro de haberlo probado ayer, y que no lo hacía bien, y ahora lo he vuelto a probar, y lo hace perfecto, usando un BSF (equivalente a SET) o BCF (equivalente a RESET).

a

No, no se pueden declarar arrays de bits.

Sí, algo así debería funcionar, pero es peor el remedio que la enfermedad. Al usar punteros el compilador utiliza direccionamiento indirecto, y aunque hiciera bien la saignación de 0 o 1 (mediante BCF o BSF), el código generado sería más largo porque en el PIC el direccionamiento indirecto obliga a setar un registro especial y demás, con lo que se hace más largo.

--
Saludos de Jose Manuel Garcia
jose.mgg@terra.es
 Click to see the full signature
Reply to
Pepitof

Escribir un bit es igual de trabajoso que escribir un byte, a nivel interno, ya que en realidad cuando cambias un bit de un byte, lo que hace el PIC es leer el byte, modificar el bit, y volver a escribir el byte. Pero a nivel de la memoria de programa y los ciclos necesarios para hacerlo, escribir un bit directamente ocupa menos espacio y tiempo de ejecución que escribirlo como un byte.

Por ejemplo, para escribir un 1 en el bit 4 de MI_VARIABLE, a nivel de bits, en ensamblador sería algo así:

BSF MI_VARIABLE, 4

en cambio, a nivel de bytes sería algo así:

MOVLW 0b00010000 IORWF MI_VARIABLE, F

Es decir, el doble de espacio y el doble de tiempo de ejecución (y además te obliga a usar W, lo que en algunos casos incrementa más aún el código necesario).

--
Saludos de Jose Manuel Garcia
jose.mgg@terra.es
 Click to see the full signature
Reply to
Pepitof

Compruebalo, porque al ser el puntero una constante no debería usar el registro de direccionamiento indirecto, sino que debería resolverlo el compilador (hasta mi compilador picsc lo hace)

De todas formas si estas acostumbrado al asm, el c en el PIC siempre te va a parecer malo, yo hice hace poco un bootloader en C por probar y ocupé una página entera de 256 bytes, para una cosa ultrasimple, con el css, una verdadra cagada de compilador.

Una alternativa que he usado con suerte de momento, ha sido hacerme un complilador adaptado al PIC, a medio camino entre el C y el asm del PIC, genera codigo asm pero es programacion estructurada.

Curiosamente hace poco (pocos años) hice una prueba de asm contra C con el Visual C (el compilador de microsoft), creyendo que yo era capaz de mejorar el código C escribiendo en asm (despues de años de asm en el 8086 no era tan descabellado) y resultó que el compilador de microsofrt es mejor que yo, y aún dicen que intel tiene un compilador mejor. Así que no es imposible generar código rápido en C.

Saludos :-) -Pedro-

formatting link

Reply to
Pedro Maicas

No tiene nada de ver pero... =BFq mejoras le ves al HiTech para haberte = pasado a =E9l habiendo probado antes el CCS?

--=20 Saludos. Mi web en

formatting link

---------------------------------------- Quitar las XX para responder por mail.

---------------------------------------- =20 "Pepitof" escribi=F3 en el mensaje = news: snipped-for-privacy@individual.net...

Reply to
Robert M. L.

Esencialmente, la integración en MPLAB. Es un entorno que conozco bien, y me resulta cómodo, y su simulador es de los más fiables. Parecerá una tontería, pero si tienes que aprender a la vez a usar un nuevo lenguaje y un nuevo entorno, la cosa es bastante más complicada que si sólo tienes que aprender el lenguaje, en un entorno que dominas.

Por otro lado, el de HiTech tiene fama de ser uno de los compiladores más eficaces para PIC, y por algunas pruebas que he hecho, creo que el CCS optimiza mucho menos.

La única ventaja que le veo al CCS es el tema de la configuración visual de periféricos y esas cosas, pero no termina de gustarme. Quizás es que soy de la vieja escuela del ASM, y prefiero ser yo el que haga esas cosas.

De todas formas estoy muy verde en el tema del C, así que no me hagas mucho caso. Simplemente elegí este. Tampoco creas que he probado muy en serio el CCS.

--
Saludos de Jose Manuel Garcia
jose.mgg@terra.es
 Click to see the full signature
Reply to
Pepitof

Pedro Maicas expuso:

Los compiladores pueden aplicar muchas optimizaciones, si están bien hechos, incluso más de las que se te ocurrirían si programaras en ASM. Este es uno de los puntos que destacan los defensores de lenguajes de alto nivel. El compilador se supone que lo ha hecho un experto en esa arquitectura y por lo tanto siempre generará mejor código que alguien que no conoce al 100% el sistema (es un decir). Pero para que eso se cumpla el compilador tiene que estar muy bien hecho, y puede ser una tarea de años el hacer un compilador así.

Reply to
Jeroni Paul

Bueno el CCS tb se integra a la perfecci=F3n con el MPLab, lo q pasa q = hace falta bajarse un parche de su web ( =

formatting link
). Una vez instalado te lo = reconoce perfectamente al iniciar un proyecto y se puede usar todas las = caracter=EDsticas del MPLab. Yo lo he usado junto al ICD2 de Michochip y = es una gozada.

Sobre la optimizaci=F3n no entro, la verdad q nunca me ha dado por mirar = el c=F3digo asm q me ha generado, con q me coja en la memoria ya me = sobra, y como tiro de samples si en uno no me cabe me voy a un modelo = con m=E1s memoria ;-)

--=20 Saludos. Mi web en

formatting link

---------------------------------------- Quitar las XX para responder por mail.

---------------------------------------- =20 "Pepitof" escribi=F3 en el mensaje = news: snipped-for-privacy@individual.net...

bien, y me

una tonter=EDa,

nuevo

aprender

m=E1s

visual de

que soy de

hagas mucho

serio el

Reply to
Robert M. L.

La optimización afecta a la memoria ocupada, pero también a la velocidad de ejecución. Para muchos diseños, especialmente montajes caseros, esos dos factores pueden no tener mucha importancia, pero si se trata de una pequeña tirada, o simplemente de hacer algo medio en serio, sí que importan.

Si te falta memoria puedes tirar de un micro con más capacidad, pero eso cuesta dinero (de acuerdo, si usas samples te da igual, pero si vas a fabricar, por ejemplo, 1000 unidades, no te da igual). Si te falta velocidad de ejecución, porque el código generado está poco optimizado, puedes subir la frecuencia de reloj, pero eso puede no ser suficiente, y además supone un consumo de energía mayor (un auténtico problema si se trata de un circuito a baterías).

Personalmente, me da alergia hacer las cosas mal, o al menos no hacerlas todo lo bien de lo que soy capaz. Y para mí, elegir un compilador poco optimizado, es hacer las cosas mal.

--
Saludos de Jose Manuel Garcia
jose.mgg@terra.es
 Click to see the full signature
Reply to
Pepitof

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.