how to optimize this code using c and pic16f84a?

936 views Asked by At

I'm using mikroC to program pic16f84a, and i have the following function

volatile unsigned short d;  // global variable

void put_data(){
    RA3_bit = d & 1;
    d >>= 1;
    RA4_bit = d & 1;
    d >>= 1;
    PORTB.B0 = d & 1;
    d >>= 1;
    PORTB.B1 = d & 1;
    d >>= 1;
    PORTB.B2 = d & 1;
    d >>= 1;
    PORTB.B3 = d & 1;
    d >>= 1;
    PORTB.B4 = d & 1;
    d >>= 1;
    PORTB.B5 = d & 1;
}

this function, take each bit from d (8 bits) and output it to port pin RA3, RA4, RB0, ... , RB5.

how could I optimize this code,, and memory is my first concern.

Update::

from pic16f84a.h:

volatile unsigned char           PORTA               @ 0x005;
// bit and bitfield definitions
volatile bit RA0                 @ ((unsigned)&PORTA*8)+0;
volatile bit RA1                 @ ((unsigned)&PORTA*8)+1;
volatile bit RA2                 @ ((unsigned)&PORTA*8)+2;
volatile bit RA3                 @ ((unsigned)&PORTA*8)+3;
volatile bit RA4                 @ ((unsigned)&PORTA*8)+4;

volatile unsigned char           PORTB               @ 0x006;
// bit and bitfield definitions
volatile bit RB0                 @ ((unsigned)&PORTB*8)+0;
volatile bit RB1                 @ ((unsigned)&PORTB*8)+1;
volatile bit RB2                 @ ((unsigned)&PORTB*8)+2;
volatile bit RB3                 @ ((unsigned)&PORTB*8)+3;
volatile bit RB4                 @ ((unsigned)&PORTB*8)+4;
volatile bit RB5                 @ ((unsigned)&PORTB*8)+5;
volatile bit RB6                 @ ((unsigned)&PORTB*8)+6;
volatile bit RB7                 @ ((unsigned)&PORTB*8)+7;

can i use these values from the header file,, to make the function a few lines of code inside a loop ?

2

There are 2 answers

3
Michael Dorgan On BEST ANSWER

Assuming that PORTB.B0 through PORTB.B5 are bits of the out port, doing this might be faster:


volatile unsigned short d;  // global variable

void put_data(){
    RA3_bit = d & 1;
    d >>= 1;
    RA4_bit = d & 1;
    d >>= 1;

    PORTB &= 0x3F; // Mask out the low 6 bits
    PORTB |= d & 0x3f;  // Or in the low 6 bits of d

    // Clean out the bits if needed in d
    d >>= 6;
}

I would expect the assembler to come out roughly twice as fast as what you are doing now, maybe more. Or'ing the 3rd and 4th bit on the first 2 instructions is probably not worth it do to the location of the bits within the port. To be sure though, always double check the assembler output. The opcodes for your assembler are simple enough that it would be pretty quick to confirm.

0
Brian McFarland On

Read the current value of the PORT or LAT register for A & B. If that PIC has both PORT & LAT, it's important to know the difference, so I suggest you do some research if you're not sure which to use.

Then do the shifting & masking necessary to make sure you only change the appropriate pins, and do just two write operations, one to port A and one to port B.

Alternatively, if all the other pins on port A & B are set to input via the TRIS register associated with each port, skip the reading step.

So for example:

tmp = PORTA;
tmp = (tmp & 0xFC) | (d & 0x3);
PORTA = tmp;

tmp = PORTB;
tmp = (tmp & 0xE0) | ((d >> 2) & 0x1F);
PORTB = tmp;

I think that will actually give you the opposite bit order from what your code does, so you may need to "reverse" the bit manipulation, or alternatively flip the bit order of d before using that code.

Also, I won't guarantee that this actually produces faster PIC code. If you really require that absolute fastest approach, you might need to write a few lines of assembly.