Function SPIIn(FSR0 As uInteger,Data_bit_mask As uByte,FSR1 As uInteger,clock_bit_mask As uByte,num_bits As uByte) ' SPI (Microwire) Input Routine ' ' Receives up to 16 bits to a serial device, using a data line and a clock line. ' ' Parameters: ' FSR0: -> the port to use for the data input, specfied as ADDR(port) ' data_bit_mask: the bit position as a mask (0x01,0x02,0x04,etc) in the port of the data input ' FSR1: -> the port to use for the clock output, specfied as ADDR(port) ' clock_bit: the bit mask in the port of the clock output ' num_bits: the number of bits (1 to 16) of data to be sent. ' ' Returns: a 16 bit word containing the data received ' ' NOTES: ' The clock pulse is at least .2 usec long with a 40 mHz PIC clock. The clock code ' just toggles the clock pin. ' Use #DEFINE SPI_CLOCKUS to make the clock pulse "SPI_CLOCKUS" in length ' Use #DEFINE SPI_READUS to delay the data read for SPI_READUS us after clock trailing edge ' ' The shift loop is 14 instructions Long, thus the clock ' rate is 700 kHz at 40mHz, 350 at 20mHz, etc ' ' The user MUST set the clock pin HIGH or LOW initially, depending on the requirements of ' the device. Dim result As uInteger result = 0 ' Clear out result register While num_bits <> 0 ' Assume for now that we want to clock on the trailing edge, and data is in from the left (MSB 1st) ' Generate a clock pulse of at least .2 usec(2 instr at 40 mHz) movf clock_bit_mask,w ' Get the clock port bit xorwf indf1,f ' Toggle clock bit 'Clock bit length #ifdef SPI_CLOCKUS pauseus( SPI_CLOCKUS ) ' Since pause destroys WREG, need to reload movf clock_bit_mask,w ' Get the clock port bit #else nop #endif xorwf indf1,f ' toggle it again 'Delay to let data settle #ifdef SPI_READUS pauseus( SPI_READUS ) #else nop #endif ' Get a data bit movf indf0,w ' Read the port into W andwf data_bit_mask,w ' mask out the desired bit addlw -1 ' Move the bit to the carry bit rlcf result,f ' Shift the carry bit into the LSB rlcf result+1,f ' Shift into the high byte of the word num_bits = num_bits - 1 End While End Function result Sub SPIOut(FSR0 As uInteger,Data_bit_mask As uByte,FSR1 As uInteger,clock_bit_mask As uByte,dataout As uInteger,num_bits As uByte) ' SPI (Microwire) Output Routine ' ' Sends up to 16 bits to a serial device, using a data line and a clock line. ' ' Parameters: ' FSR0: -> the port to use for the data output, specfied as ADDR(port) ' data_bit_mask: the bit position as a mask (0x01,0x02,0x04,etc) in the port of the data output ' FSR1: -> the port to use for the clock output, specfied as ADDR(port) ' clock_bit: the bit mask in the port of the clock output ' data_out: a 16 bit word containing the data to be sent, right justfified ' num_bits: the number of bits (1 to 16) of data to be sent. ' ' NOTES: ' The data to be sent should be right-justified in the data word no matter how many bits are being sent, ' e.g. To send an 8-bit byte containing "10", the Data word should be set up as 0x00001010. The routine ' will shift the data to the left ' ' The clock pulse is at least .2 usec long with a 40 mHz PIC clock. The clock code ' just toggles the clock pin. ' Use #DEFINE SPI_CLOCKUS to make the clock pulse "SPI_CLOCKUS" usec in length ' Use #DEFINE SPI_WRITEUS to delay the clock by "SPI_WRITEUS" usec after data write ' There are 16 instructions in the shift loop, thus at 40 Mhz the clock rate is ' 625 kHz, 312 kHz at 20 mHz, etc ' The user MUST set the clock pin HIGH or LOW initially, depending on the requirements of ' the device. ' The data is set up before the clock changes, thus the device can clock in the data ' on either the leading or trailing edge. Dim extra_shifts As uByte, carry As Boolean extra_shifts = 16 - num_bits While extra_shifts <> 0 rlcf dataout,f ' Shift the carry bit into the LSB rlcf dataout+1,f ' Shift into the high byte of the word extra_shifts = extra_shifts - 1 End While While num_bits <> 0 ' The data is assumed to be right-justified, thus we need to shift the extra (16-num_bits) ' without sending data to the port ' Rotate the data word into the carry bit. If the carry bit is on, the ' the data bit to send is a 1 rlcf dataout,f ' Shift the carry bit into the LSB rlcf dataout+1,f ' Shift into the high byte of the word ' Send a data bit to the port movf indf0,w ' Read the port iorwf data_bit_mask,w ' Set a 1 btfss STATUS_C ' Skip if carry on (data bit was 1) xorwf data_bit_mask,w ' Data bit was a zero, turn off ' Here is where the port data bit changes movwf indf0 ' Write back to port ' Delay clock to let data settle #ifdef SPI_WRITEUS pauseus( SPI_WRITEUS ) #else nop #endif ' Generate a clock pulse of at least .2 usec(2 instr at 40 mHz) movf clock_bit_mask,w ' Get the clock port bit ' Leading edge of clock pulse xorwf indf1,f ' Toggle clock bit ' Clock bit length #ifdef SPI_CLOCKUS pauseus( SPI_CLOCKUS ) ' Since pause destroys WREG, need to reload movf clock_bit_mask,w ' Get the clock port bit #else nop #endif ' Trailing edge of clock pulse xorwf indf1,f ' toggle it again num_bits = num_bits - 1 End While End Sub Function bitposn(count As uByte) ' Given a number (0-7) in count, return a mask respresenting the position ' of the bit in a byte ' 0: 0x01 ' 1: 0x02 Dim mask As uByte 'Dim count As uByte 'movwf count incf count,f movlw 1 loop: dcfsnz count,f bra finished rlcf wreg,w bra loop finished: movwf mask,w End Function mask