Electronic – Can individual pins of different port of a microcontroller be mapped to a register and their values be changed when changing the register value

8051digital-logicembeddedmicrocontrollerpic

Q: Can individual pins of different port of a micro-controller be mapped to a register and their values be changed when changing the register value?

Scenario: I have used up some pins from each port(8-bits) of the micro-controller. Now I want to interface a device which needs an 8-bit bus (suppose D0 to D7 IN SEQUENCE) that is to say I need 8 pins from controller so that I can connect them in one-to-one fashion

portx0  -> D0 // x is the name of port followed by bit location on that port
portx1  -> D1
...
portx7  -> D7

but I don't have a whole port of 8 pins which I can connect with this device, rather I have some pins from portx, some from porty and some pins from portz. The new connection scenario is as (connection from micro-controller to device respectively )

portx0  -> D0
portx1  -> D1
portx2  -> D2
porty4  -> D3
porty5  -> D4
porty6  -> D5
porty7  -> D6
portz1  -> D7

In this condition if I want to send a value say

unsigned char dataReg = 0xFA;

to my device from controller I have to perform bit wise operations on the value to be sent and set each pin according to the value in the register individually. For example

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 );

Now, coming to the main question, to avoid these individual calculations on each bit on different ports, can individual pins of different port of a micro-controller be mapped to a register and their values be changed when changing the register value?

Best Answer

It appears your question comes down to having a 8 bit value in the firmware, and wanting to read and write that from and to a arbitrary collection of port pins.

There is no direct hardware way to do this. You have to write two routines, one to read the 8 bit value and one to write it. Others have mentioned using unions, but that is a bad idea. With unions, you have to deal with every bit separately, and the code becomes dependent on the bit order of the micro. This might be the way to go anyway if all the 8 bits are scattered completely independently. If so, there is little you can do but to make special code for each bit.

The better way to do this, especially if you can group the bits in a few contiguous chunks on the physical ports is to use masking, shifting, and ORing. For example, if the low three bits of the internal byte are on bits <6-4> of a port, right shift that port value by 4 and AND it with 7 to get those bits into their final position. Shift and mask (or mask and shift) bits from other ports into place and assemble the final 8 bit byte by ORing the results into it.

This kind of low level bit twiddling is easier to do in assembler than C. I'd probably put the byte read and write routines in a single assembler module and make the interface callable from C.