Shift register driver in PIC C

Status
Not open for further replies.

lukas.ballo

New Member
I would like to create a function in PIC C (PCWHD plug-in MPLAB) that takes an 8-bit integer as an argument and outputs 8 1-bit variables that can be used to serially setup a shift register.

Something like this:
Code:
int1 b0,b1,b3,b4,b6,b7;

void shift_register (unsigned int8 data)
{
b0 = [least significant bit of "data"];
...
b7 = [most significant bit of "data"];
}
I know that I should use some kind of pointer identifier to each time pick out one particular bit from the 8-bit integer however I don't know how to do it.

Thank you for any ideas!

Papabravo

Well-Known Member
I see no advantage in using a pointer. You just have to waste instructions initializing, incrementing, and testing it. I would unroll the loop and use the right shift operator as follows
Code:
    b0 = data & 1 ;    data >>= 1 ;
b1 = data & 1 ;    data >>= 1 ;
b2 = data & 1 ;    data >>= 1 ;
b3 = data & 1 ;    data >>= 1 ;
b4 = data & 1 ;    data >>= 1 ;
b5 = data & 1 ;    data >>= 1 ;
b6 = data & 1 ;    data >>= 1 ;
b7 = data & 1 ;
It should be pretty easy for even a brain-dead compiler to optimize the nuts out of that one. I'd be willing to bet substantial summs that any other technique will produce inferior code.

Last edited:

felis

New Member
You can connect shift register to SPI output of a PIC, if one that you are using have it. Then just place your variable in SSPBUF and get it out of SDO one bit a time.

Banned
You might want to think about that Papa. The index registers on micro controllers often have instructions for reading them with the increment built in free of charge, it's faster than explicit code.

Papabravo

Well-Known Member
Show me the assembly code from a compiler output. There is still the initiialization and testing. At 8 bits I agree it might be borderline on a 6809 or a 6502. My point is that it can nearly be done in registers without the need for pointers at all

Last edited:

Pommie

Well-Known Member
I tried this for curiosities sake with the BoostC compiler on a 16 series pic chip,
Code:
void ByteToBits(unsigned char Dat){
unsigned char buff[8], i,*p;
p=&buff;
for(i=0;i<8;i++){
*p++=Dat&1;
Dat>>=1;
}
}
Takes 28 instructions.

Code:
void unrolled(unsigned char Dat){
unsigned char buff[8];
buff[0]=Dat&1;
Dat>>=1;
buff[1]=Dat&1;
Dat>>=1;
buff[2]=Dat&1;
Dat>>=1;
buff[3]=Dat&1;
Dat>>=1;
buff[4]=Dat&1;
Dat>>=1;
buff[5]=Dat&1;
Dat>>=1;
buff[6]=Dat&1;
Dat>>=1;
buff[7]=Dat&1;
}
Takes 39 instructions.

So, the looped version uses less rom space but would take about 4 times longer to execute.

Mike.

Papabravo

Well-Known Member
Ah...so. This is not an uncommon result. Does it take less instructions if you don't use a 1-dimensional array, but 8 separate GLOBAL variables. Direct addressing is certainly ugly, but probably faster. In any optimization problem you need to be clear about weather space or execution speed is of greater concern. Forty years ago we were consumed with the importance of reducing memory space because people were cheap (in the sense of wages earned), and memory was expensive. Over time as memory became cheap and people became expensive we migrated to reducing time to a minimum. Now it seems we longer care about either one because people are so expensive and time to market is so critcal that both speed and space are a complete don't care.

Nowadays, my standard is does the task work and execute in acceptable time. I'm looking for the best result possible rather than the best possible result.

Last edited:
Status
Not open for further replies.