If you need total control of data & clock timing, it should be relatively easy to roll your own
synchronous serial routines.

See if something like this works. To adjust data & clock timing just change the constant
delays or even switch to PAUSEUS VS PAUSE.
Code:
DEFINE OSC 4            ' 16F877A @ 4MHz sending
DEFINE LOADER_USED 1

SYMBOL DOUT = PORTB.0   ' data output pin
SYMBOL CLOCK = PORTB.1  ' clock output pin

DAT_DLY CON 1           ' data bit rate = DAT_DLY*2 + CLK_DLY + loop overhead
CLK_DLY CON 1           ' clock time

PACKET VAR WORD         ' 16-bit data packet
INDEX VAR BYTE          ' data packet bit index pointer/loop counter

PORTB = 0               ' pins idle low
TRISB = %11111100       ' RB0, RB1 outputs
PAUSE 3000

MAIN:
    PACKET = %1010101010101101  ' load 16-bit data packet (receiving PIC displays $AAAD)
    
    ' delay values give around 3.1mS wide data bits with a 1mS clock pulse
    ' in the center of each data bit. 
SEND:
    FOR INDEX = 15 TO 0 STEP-1  ' send msb first  (lsb first would be 0 to 15)
        DOUT = PACKET.0[INDEX]  ' place data bit on RB0
        PAUSE DAT_DLY           ' pause bit time
        HIGH CLOCK              ' set clock in middle of data bit
        PAUSE CLK_DLY           ' pause for clock time
        LOW CLOCK               ' low clock
        PAUSE DAT_DLY           ' pause for last of data bit
    NEXT INDEX                  ' get next data bit
    LOW DOUT                    ' data out & clock pins idle low
    PAUSE 50
    GOTO MAIN
    END
You may want to work out some type of synchronization between the two. I flipped on
power to the receiving end just before the transmitter to synch-up.
Code:
DEFINE OSC 20           ' 18F2431 @ 20MHz receiving
DEFINE LOADER_USED 1

SYMBOL DIN = PORTB.0    ' data input pin
SYMBOL CLOCK = PORTB.1  ' clock output pin

IDLE CON 0              ' idle logic state
ACTIVE CON 1            ' active clock logic state

PACKET VAR WORD         ' 16-bit data packet
INDEX VAR BYTE          ' data packet bit index pointer/loop counter

TRISB = %11111111       ' data and clock both inputs
PAUSE 3000

MAIN:
    PACKET = 0          ' clear data packet
    
RCV:
    FOR INDEX = 15 TO 0 STEP-1  ' receive msb first
        WHILE CLOCK = IDLE      ' wait for active clock
        WEND
        PACKET.0[INDEX]=DIN     ' place data bit on RB0 in packet
        WHILE CLOCK = ACTIVE    ' wait for clock to return to idle state
        WEND
    NEXT INDEX                  ' get next data bit
    HSEROUT [HEX4 PACKET,13,10] ' show value received
    GOTO MAIN
    END
You could probably use SHIFTOUT and SHIFTIN too, but if you need full control of data and
clock rates, something like this should give you the extra flexibility.