2

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 ?

Rami Jarrar
  • 4,523
  • 7
  • 36
  • 52
  • Your defines for PORTB don't show bitfields or structures. Not sure exactly what PORTB.B1 means. If this is a bitfield pointing at the same memory location, then combining your writes would probably be quite a bit faster. Also RA3_bit and RA4_bit are not defined nor is "bit" directly. What are they? I've got the datasheet on your chip and can help, but I need a bit more info :) – Michael Dorgan May 22 '12 at 21:13

2 Answers2

3

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.

Michael Dorgan
  • 12,453
  • 3
  • 31
  • 61
  • PORTB |= d & 0x1f; << this should be PORTB |= d & 0x3f; right,, because its from RA3 - RB5 (8 bits) ? – Rami Jarrar May 22 '12 at 21:35
  • there is also this PORTB &= 0x3F; << should be PORTB &= 0xC0; – Rami Jarrar May 22 '12 at 21:52
  • No, actually, I wanted to mask the lower 6 bits off and leave the top 2 alone, then or in the low 6 bits over the cleared values. That's what your code does. Still, even if the code isn't 100% correct, you get the idea I was trying to convey. – Michael Dorgan May 23 '12 at 17:41
1

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.

Brian McFarland
  • 9,052
  • 6
  • 38
  • 56