P: ¿Se pueden asignar pines individuales de diferentes puertos de un microcontrolador a un registro y cambiar sus valores al cambiar el valor del registro?
Escenario: he usado algunos pines de cada puerto (8 bits) del microcontrolador. Ahora quiero conectar un dispositivo que necesita un bus de 8 bits (supongamos que D0 a D7 EN SECUENCIA), es decir, necesito 8 pines del controlador para poder conectarlos uno a uno.
portx0 -> D0 // x is the name of port followed by bit location on that port
portx1 -> D1
...
portx7 -> D7
pero no tengo un puerto completo de 8 pines que pueda conectar con este dispositivo, sino que tengo algunos pines de portx, algunos de porty y algunos pines de portz. El nuevo escenario de conexión es como (conexión del microcontrolador al dispositivo respectivamente)
portx0 -> D0
portx1 -> D1
portx2 -> D2
porty4 -> D3
porty5 -> D4
porty6 -> D5
porty7 -> D6
portz1 -> D7
En esta condición si quiero enviar un valor diga
unsigned char dataReg = 0xFA;
a mi dispositivo desde el controlador, tengo que realizar operaciones bit a bit en el valor que se enviará y configurar cada pin de acuerdo con el valor en el registro individualmente. Por ejemplo
portx0 = ((dataReg & 0x01) >> 0 ); // Masking and shifting as bit position
portx1 = ((dataReg & 0x02) >> 1 );
portx2 = ((dataReg & 0x04) >> 2 );
porty4 = ((dataReg & 0x08) >> 3 );
porty5 = ((dataReg & 0x10) >> 4 );
porty6 = ((dataReg & 0x20) >> 5 );
porty7 = ((dataReg & 0x40) >> 6 );
portz1 = ((dataReg & 0x80) >> 7 );
Ahora, volviendo a la pregunta principal, para evitar estos cálculos individuales en cada bit en diferentes puertos, ¿se pueden asignar pines individuales de diferentes puertos de un microcontrolador a un registro y cambiar sus valores al cambiar el valor del registro?
Parece que su pregunta se reduce a tener un valor de 8 bits en el firmware y querer leer y escribir eso desde y hacia una colección arbitraria de pines de puerto.
No hay una forma directa de hardware para hacer esto. Tienes que escribir dos rutinas, una para leer el valor de 8 bits y otra para escribirlo. Otros han mencionado el uso de uniones, pero esa es una mala idea. Con las uniones, tiene que lidiar con cada bit por separado, y el código se vuelve dependiente del orden de bits del micro. Este podría ser el camino a seguir de todos modos si los 8 bits se dispersan de forma completamente independiente. Si es así, es poco lo que puede hacer salvo crear un código especial para cada bit.
La mejor manera de hacer esto, especialmente si puede agrupar los bits en unos pocos fragmentos contiguos en los puertos físicos, es usar enmascaramiento, desplazamiento y ORing. Por ejemplo, si los tres bits inferiores del byte interno están en los bits <6-4> de un puerto, desplace a la derecha ese valor de puerto en 4 y haga AND con 7 para colocar esos bits en su posición final. Desplace y enmascare (o enmascare y desplace) bits de otros puertos a su lugar y ensamble el byte final de 8 bits mediante la operación OR de los resultados en él.
Este tipo de cambio de bits de bajo nivel es más fácil de hacer en ensamblador que en C. Probablemente pondría las rutinas de lectura y escritura de bytes en un solo módulo ensamblador y haría que la interfaz se pueda llamar desde C.
En general esto no es posible. Que yo sepa, no es posible con PIC.
Solo conozco un microcontrolador que puede hacer esto, el Cypress PSoC . Es un sistema altamente configurable en chip. De las muchas cosas que le permite hacer es definir literalmente su propio registro (1-8 bits) y conectarlo a cualquier pin que desee, o incluso a circuitos internos.
Por ejemplo, aquí he creado un registro de control de 6 bits. 5 de los bits van directamente a los pines, mientras que el sexto bit lo estoy usando para XOR con la entrada de un séptimo pin.
En el chip, puedo optar por asignar estos pines a cualquiera de los pines GPIO disponibles. (Son los grises uno de la imagen)
Puede intentar lo siguiente. Escriba una estructura propia que se asigne a los pines respectivos de los 2 puertos (que se utilizarán) Ahora, al actualizar el valor en este registro, se establecerán/reiniciarán los pines de esos 2 puertos. ¡Solo intente y háganos saber si funcionó!
Estoy seguro de que esto debería funcionar.
Si he entendido la pregunta correctamente, es bastante fácil en C:
Declaración de tipo genérico, se puede reutilizar para cualquier registro:
typedef union // Generic 8-bit register Type
{
uint8 reg; // Whole register
struct
{
unsigned bit7 : 1; // Bit 7
unsigned bit6 : 1; // Bit 6
unsigned bit5 : 1; // Bit 5
unsigned bit4 : 1; // Bit 4
unsigned bit3 : 1; // Bit 3
unsigned bit2 : 1; // Bit 2
unsigned bit1 : 1; // Bit 1
unsigned bit0 : 1; // Bit 0
} bit;
} typ_GENERIC_REG8;
Entonces, para definir un puerto que queremos abordar:
#define MCU_GPO_PORTx (*(volatile typ_GENERIC_REG8 *)(0x12345678)) // Number is address
Y para girar directamente un pin en ese puerto:
#define MCU_PORTx_PINn (MCU_GPO_PORTx.bit.bit0)
En codigo:
MCU_PORTx_PINn = 1; // Set pin high
Todo el registro:
MCU_GPO_PORTx.reg = 0xF; // All pins high
Vale la pena leer sobre estructuras, uniones, typedefs y enumeraciones: ¡todo esto hace que la vida sea mucho más agradable en incrustado y en general!
usuario17592