CanBus

SwordfishUser.CanBus History

Hide minor edits - Show changes to markup

Added line 77:
Deleted line 5:
Changed lines 76-79 from:

For initialization you can choice between Sensirion_Init or Sensirion_Init_

You can download source code from : http://www.microelemente.ro/Swordfish/Sensirion.zip

to:

You can download source code from : http://www.microelemente.ro/Swordfish/CAN.zip In ZIP file, you have 4 examples and additional SYS_lib module.

Changed lines 81-94 from:

Device = 18F8520

to:

{

  • Name : CAN_Echo.BAS *
  • Author : Florin Andrei Medrea *
  • Notice : Copyright (c) 2007 - YO2LIO - *
  • : All Rights Reserved *
  • Date : 10/26/2007 *
  • Version : 1.0 *
  • Notes : Receive CAN message for XTD id "S01", *
  • : send message back to sender with XTD id "S01" *
  • : and send message to Usart *

} Device = 18F458

Changed lines 98-159 from:

// some LCD options...

  1. option LCD_DATA = PORTH.4
  2. option LCD_RS = PORTH.2
  3. option LCD_EN = PORTH.3

// import LCD library... Include "LCD.bas" Include "Sensirion" Include "convert.bas"

Dim NoError As Boolean Dim temperature, humidity, dew_point As Float Dim TempA, TempB As Byte Dim buf As Integer

ADCON0 = 0 CMCON = $07 // turn off comparators ADCON1 = $0F // turn off analog inputs MEMCON.7 = 1 // disable external memory bus

Cls //Sensirion.Sensirion_Init(PORTC.1, PORTC.2)

                                          // Sensirion.Sensirion_Init(Port.(Data Pin), Port.(Clock pin))
                                          // Data an Clock Pin must be at the same Port
                                          // This is a wrong configuration : 
                                          // Sensirion.Sensirion_Init(PORTB.1, PORTD.2) 

Sensirion.Sensirion_Init_(PORTC, 0, 1) // Sensirion.Sensirion_Init(Port, Data Pin, Clock Pin) While true

    NoError = Sensirion.Sensirion_Get_Temp_Hum(temperature, humidity)
    If NoError Then
        buf = temperature * 100
        TempA = buf / 100
        TempB = buf Mod 100
        LCD.WriteAt(1,1, " TS = ",DecToStr(TempA,2),".",DecToStr(TempB,2)," ", 223, "C  ")
        buf = humidity * 100
        TempA = buf / 100
        TempB = buf Mod 100
        LCD.WriteAt(2,1, " Rh = ",DecToStr(TempA,2),".",DecToStr(TempB,2)," "," %  ")
        dew_point = Sensirion.Sensirion_Get_Dew_Point(temperature, humidity)       
    Else 
        LCD.WriteAt(1,1, " Error detected ")
        LCD.WriteAt(2,1, " Error detected ")        
    End If
    DelayMS(2000)

Wend =]

Module Code

=code [= {

  • Name : CAN_lib.BAS *
  • Author : Florin Andrei Medrea *
  • Notice : Copyright (c) 2007 - YO2LIO - *
  • : All Rights Reserved *
  • Date : 10/26/2007 *
  • Version : 1.0 *
  • Notes : This module is based on Microchip sample *
  • : CAN Application Note AN738 *

} Module CAN_lib

to:

Include "CAN_lib" Include "usart"

Changed lines 102-115 from:

Public Const

  CAN_TX_PRIORITY_BITS= %00000011,
  CAN_TX_PRIORITY_0   = %11111100,            // XXXXXX00
  CAN_TX_PRIORITY_1   = %11111101,            // XXXXXX01
  CAN_TX_PRIORITY_2   = %11111110,            // XXXXXX10
  CAN_TX_PRIORITY_3   = %11111111,            // XXXXXX11

  CAN_TX_FRAME_BIT    = %00001000,
  CAN_TX_STD_FRAME    = %11111111,            // XXXXX1XX
  CAN_TX_XTD_FRAME    = %11110111,            // XXXXX0XX

  CAN_TX_RTR_BIT      = %01000000,
  CAN_TX_NO_RTR_FRAME = %11111111,            // X1XXXXXX
  CAN_TX_RTR_FRAME    = %10111111,            // X0XXXXXX
to:

Dim Can_Init_Flags, Can_Send_Flags, Can_Rcv_Flags, Rx_Data_Len, i As Byte,

    RxTx_Data(8) As Byte,
    Tx_ID, Rx_ID As LongWord,
    Msg_Rcvd, Msg_Sent As Boolean
Changed lines 108-127 from:
  CAN_RX_FILTER_BITS  = %00000111,
  CAN_RX_FILTER_1     = %00000000,
  CAN_RX_FILTER_2     = %00000001,
  CAN_RX_FILTER_3     = %00000010,
  CAN_RX_FILTER_4     = %00000011,
  CAN_RX_FILTER_5     = %00000100,
  CAN_RX_FILTER_6     = %00000101,

  CAN_RX_OVERFLOW     = %00001000,            // Set if Overflowed else cleared 
  CAN_RX_INVALID_MSG  = %00010000,            // Set if invalid else cleared
  CAN_RX_XTD_FRAME    = %00100000,            // Set if XTD message else cleared
  CAN_RX_RTR_FRAME    = %01000000,            // Set if RTR message else cleared
  CAN_RX_DBL_BUFFERED = %10000000,            // Set if this message was hardware double-buffered

  CAN_OP_MODE_BITS    = %11100000,
  CAN_OP_MODE_NORMAL  = %00000000,
  CAN_OP_MODE_SLEEP   = %00100000,
  CAN_OP_MODE_LOOP    = %01000000,
  CAN_OP_MODE_LISTEN  = %01100000,
  CAN_OP_MODE_CONFIG  = %10000000,
to:
  ADCON1 = %11000110      // AD off
  CMCON = $07             // Comparator off
  WDTCON = 1
Changed lines 112-188 from:
  CAN_CONFIG_DEFAULT          = %11111111,    // 11111111
  CAN_CONFIG_PHSEG2_PRG_BIT   = %00000001,
  CAN_CONFIG_PHSEG2_PRG_ON    = %11111111,    // XXXXXXX1
  CAN_CONFIG_PHSEG2_PRG_OFF   = %11111110,    // XXXXXXX0

  CAN_CONFIG_LINE_FILTER_BIT  = %00000010,
  CAN_CONFIG_LINE_FILTER_ON   = %11111111,    // XXXXXX1X
  CAN_CONFIG_LINE_FILTER_OFF  = %11111101,    // XXXXXX0X

  CAN_CONFIG_SAMPLE_BIT       = %00000100,
  CAN_CONFIG_SAMPLE_ONCE      = %11111111,    // XXXXX1XX
  CAN_CONFIG_SAMPLE_THRICE    = %11111011,    // XXXXX0XX

  CAN_CONFIG_MSG_TYPE_BIT     = %00001000,
  CAN_CONFIG_STD_MSG          = %11111111,    // XXXX1XXX
  CAN_CONFIG_XTD_MSG          = %11110111,    // XXXX0XXX

  CAN_CONFIG_DBL_BUFFER_BIT   = %00010000,
  CAN_CONFIG_DBL_BUFFER_ON    = %11111111,    // XXX1XXXX
  CAN_CONFIG_DBL_BUFFER_OFF   = %11101111,    // XXX0XXXX

  CAN_CONFIG_MSG_BITS         = %01100000,
  CAN_CONFIG_ALL_MSG          = %11111111,    // X11XXXXX
  CAN_CONFIG_VALID_XTD_MSG    = %11011111,    // X10XXXXX
  CAN_CONFIG_VALID_STD_MSG    = %10111111,    // X01XXXXX
  CAN_CONFIG_ALL_VALID_MSG    = %10011111,    // X00XXXXX

  CAN_MASK_B1           = 1,
  CAN_MASK_B2           = 2,

  CAN_FILTER_B1_F1      = 1,
  CAN_FILTER_B1_F2      = 2,
  CAN_FILTER_B2_F1      = 3,
  CAN_FILTER_B2_F2      = 4,
  CAN_FILTER_B2_F3      = 5,
  CAN_FILTER_B2_F4      = 6

Const

                                              // BRGCON3
  WAKFIL = 6,
                                              // BRGCON2
  SEG2PHTS = 7,
  SAM = 6,
                                              // COMSTAT
  RX1OVFL = 7,
  RXB0OVFL = 7,
  TXBO = 5,
  TXBP = 4,
  RXBP = 3,
                                              // PIR3
  IRXIF = 7,
  RXB1IF = 1,
  RXB0IF = 0,
                                              // CANCON
  ABAT = 4,
                                              // RXBnCON
  RXFUL = 7,
  RXB0DBEN = 2,
                                              // RXBnDLC
  RXRTR = 6,
                                              // RXBnSIDL
  EXID = 3,
                                              // TXBnCON
  TXREQ = 3

Dim

  RXB0CON_RX0DBEN  As RXB0CON.Bits(RXB0DBEN),
  BRGCON2_SAM      As BRGCON2.Bits(SAM),
  BRGCON2_SEG2PHTS As BRGCON2.Bits(SEG2PHTS),
  BRGCON3_WAKFIL   As BRGCON3.Bits(WAKFIL),
  PIR3_RXB0IF      As PIR3.Bits(RXB0IF),
  COMSTAT_RX0OVFL  As COMSTAT.Bits(RXB0OVFL),
  PIR3_RXB1IF      As PIR3.Bits(RXB1IF),
  COMSTAT_RX1OVFL  As COMSTAT.Bits(RX1OVFL),
  RXB0DLC_RTR      As RXB0DLC.Bits(RXRTR),
  RXB0SIDL_EXID    As RXB0SIDL.Bits(EXID),
  PIR3_IRXIF       As PIR3.Bits(IRXIF),
to:
  ClrWDT
  SetBaudrate(br115200)
Changed lines 115-134 from:
  COMSTAT_TXB0     As COMSTAT.Bits(TXBO),
  COMSTAT_TXBP     As COMSTAT.Bits(TXBP),
  COMSTAT_RXBP     As COMSTAT.Bits(RXBP),
  CANCON_ABAT      As CANCON.Bits(ABAT),
  RXB0CON_RXFUL    As RXB0CON.Bits(RXFUL)

// RXB1CON_RXFUL As RXB1CON.Bits(RXFUL), // TXB0CON_TXREQ As TXB0CON.Bits(TXREQ), // TXB1CON_TXREQ As TXB1CON.Bits(TXREQ), // TXB2CON_TXREQ As TXB2CON.Bits(TXREQ)

{

  • Name : CANSetOperationMode *
  • Purpose : Given mode byte is copied to CANCON *
  • and made sure that requested mode is set. *

} Public Sub CANSetOperationMode(mode As Byte)

  CANCON = mode   // Request desired mode.  
  While((CANSTAT And CAN_OP_MODE_BITS) <> mode)
to:
  Can_Init_Flags = 0
  Can_Send_Flags = 0
  Can_Rcv_Flags  = 0

  Can_Send_Flags = CAN_TX_PRIORITY_0 And                    // Form value to be used
                   CAN_TX_XTD_FRAME  And                    //  with CANSendMessage
                   CAN_TX_NO_RTR_FRAME

  Can_Init_Flags = CAN_CONFIG_SAMPLE_THRICE And             // Form value to be used
                   CAN_CONFIG_PHSEG2_PRG_ON And             //  with CANInitialize
                   CAN_CONFIG_XTD_MSG       And            
                   CAN_CONFIG_DBL_BUFFER_ON And
                   CAN_CONFIG_ALL_VALID_MSG

  CANInitialize(1, 10, 7, 6, 2, Can_Init_Flags)             // initialize CAN at 250 Kbps

  CANSetOperationMode(CAN_OP_MODE_CONFIG)                   // set CONFIGURATION mode
  Rx_ID = $FFFFFFFF
  CANSetMask(CAN_MASK_B1, Rx_ID, CAN_CONFIG_XTD_MSG)        // set all mask1 bits to ones
  CANSetMask(CAN_MASK_B2, Rx_ID, CAN_CONFIG_XTD_MSG)        // set all mask2 bits to ones  
  Rx_ID = String2ID("S01")
  Tx_ID = String2ID("S01")
  CANSetFilter(CAN_FILTER_B1_F1, Rx_ID, CAN_CONFIG_XTD_MSG) // set id of filter B1_F1 to "S01"
  CANSetOperationMode(CAN_OP_MODE_NORMAL)                   // set NORMAL mode

  While true
Changed lines 142-143 from:
  Wend            // Wait till desired mode is set.

End Sub

to:
    Msg_Rcvd = CANReceiveMessage(Rx_ID , RxTx_Data , Rx_Data_Len, Can_Rcv_Flags)
    If Msg_Rcvd Then
      WriteByte(Rx_ID.Byte2)
      WriteByte(Rx_ID.Byte1)
      WriteByte(Rx_ID.Byte0)
      WriteByte(" ")
      i = 0
      While i < Rx_Data_Len
        WriteByte(RxTx_Data(i))
        Inc(i)
      Wend
      Write($0D, $0A)
      Msg_Sent = CANSendMessage(Tx_ID, RxTx_Data, Rx_Data_Len, Can_Send_Flags) // send data back
      If Msg_Sent Then
        Write("CANSendMessage Success", $0D, $0A)
      Else
        Write("CANSendMessage Error", $0D, $0A)
      End If
    End If
  Wend 

=]

Module Code

=code [=

Changed lines 166-181 from:
  • Name : CANSetBaudRate *
  • Purpose : Given values are bit adjusted to fit in 18CXX8 *
  • BRGCONx registers and copied. *
  • Input : SJW - SJW value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 4) *
  • BRP - BRP value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 64) *
  • PHSEG1 - PHSEG1 value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • PHSEG2 - PHSEG2 value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • PROPSEG - PROPSEG value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • flags - Value of CAN_CONFIG_FLAGS *
to:
  • Name : CAN_lib.BAS *
  • Author : Florin Andrei Medrea *
  • Notice : Copyright (c) 2007 - YO2LIO - *
  • : All Rights Reserved *
  • Date : 10/26/2007 *
  • Version : 1.0 *
  • Notes : This module is based on Microchip sample *
  • : CAN Application Note AN738 *
Changed lines 177-197 from:

Sub CANSetBaudRate(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, flags As Byte)

  Dec(SJW)
  Dec(BRP)
  Dec(PHSEG1)
  Dec(PHSEG2)
  Dec(PROPSEG)
  BRGCON1 = SJW << 6
  BRGCON1 = BRGCON1 Or BRP
  BRGCON2 = PHSEG1 << 3
  BRGCON2 = BRGCON2 Or PROPSEG
  If (flags And CAN_CONFIG_SAMPLE_BIT) = 0 Then
    BRGCON2_SAM = 1
  End If
  If (flags And CAN_CONFIG_PHSEG2_PRG_BIT) <> 0 Then
    BRGCON2_SEG2PHTS = 1
  End If
  BRGCON3 = PHSEG2
  If (flags And CAN_CONFIG_LINE_FILTER_BIT) <> 0 Then 
    BRGCON3_WAKFIL = 1
  End If   

End Sub

to:

Module CAN_lib

Include "SYS_lib"

Public Const

  CAN_TX_PRIORITY_BITS= %00000011,
  CAN_TX_PRIORITY_0   = %11111100,            // XXXXXX00
  CAN_TX_PRIORITY_1   = %11111101,            // XXXXXX01
  CAN_TX_PRIORITY_2   = %11111110,            // XXXXXX10
  CAN_TX_PRIORITY_3   = %11111111,            // XXXXXX11

  CAN_TX_FRAME_BIT    = %00001000,
  CAN_TX_STD_FRAME    = %11111111,            // XXXXX1XX
  CAN_TX_XTD_FRAME    = %11110111,            // XXXXX0XX

  CAN_TX_RTR_BIT      = %01000000,
  CAN_TX_NO_RTR_FRAME = %11111111,            // X1XXXXXX
  CAN_TX_RTR_FRAME    = %10111111,            // X0XXXXXX

  CAN_RX_FILTER_BITS  = %00000111,
  CAN_RX_FILTER_1     = %00000000,
  CAN_RX_FILTER_2     = %00000001,
  CAN_RX_FILTER_3     = %00000010,
  CAN_RX_FILTER_4     = %00000011,
  CAN_RX_FILTER_5     = %00000100,
  CAN_RX_FILTER_6     = %00000101,

  CAN_RX_OVERFLOW     = %00001000,            // Set if Overflowed else cleared 
  CAN_RX_INVALID_MSG  = %00010000,            // Set if invalid else cleared
  CAN_RX_XTD_FRAME    = %00100000,            // Set if XTD message else cleared
  CAN_RX_RTR_FRAME    = %01000000,            // Set if RTR message else cleared
  CAN_RX_DBL_BUFFERED = %10000000,            // Set if this message was hardware double-buffered

  CAN_OP_MODE_BITS    = %11100000,
  CAN_OP_MODE_NORMAL  = %00000000,
  CAN_OP_MODE_SLEEP   = %00100000,
  CAN_OP_MODE_LOOP    = %01000000,
  CAN_OP_MODE_LISTEN  = %01100000,
  CAN_OP_MODE_CONFIG  = %10000000,

  CAN_CONFIG_DEFAULT          = %11111111,    // 11111111
  CAN_CONFIG_PHSEG2_PRG_BIT   = %00000001,
  CAN_CONFIG_PHSEG2_PRG_ON    = %11111111,    // XXXXXXX1
  CAN_CONFIG_PHSEG2_PRG_OFF   = %11111110,    // XXXXXXX0

  CAN_CONFIG_LINE_FILTER_BIT  = %00000010,
  CAN_CONFIG_LINE_FILTER_ON   = %11111111,    // XXXXXX1X
  CAN_CONFIG_LINE_FILTER_OFF  = %11111101,    // XXXXXX0X

  CAN_CONFIG_SAMPLE_BIT       = %00000100,
  CAN_CONFIG_SAMPLE_ONCE      = %11111111,    // XXXXX1XX
  CAN_CONFIG_SAMPLE_THRICE    = %11111011,    // XXXXX0XX

  CAN_CONFIG_MSG_TYPE_BIT     = %00001000,
  CAN_CONFIG_STD_MSG          = %11111111,    // XXXX1XXX
  CAN_CONFIG_XTD_MSG          = %11110111,    // XXXX0XXX

  CAN_CONFIG_DBL_BUFFER_BIT   = %00010000,
  CAN_CONFIG_DBL_BUFFER_ON    = %11111111,    // XXX1XXXX
  CAN_CONFIG_DBL_BUFFER_OFF   = %11101111,    // XXX0XXXX

  CAN_CONFIG_MSG_BITS         = %01100000,
  CAN_CONFIG_ALL_MSG          = %11111111,    // X11XXXXX
  CAN_CONFIG_VALID_XTD_MSG    = %11011111,    // X10XXXXX
  CAN_CONFIG_VALID_STD_MSG    = %10111111,    // X01XXXXX
  CAN_CONFIG_ALL_VALID_MSG    = %10011111,    // X00XXXXX

  CAN_MASK_B1           = 1,
  CAN_MASK_B2           = 2,

  CAN_FILTER_B1_F1      = 1,
  CAN_FILTER_B1_F2      = 2,
  CAN_FILTER_B2_F1      = 3,
  CAN_FILTER_B2_F2      = 4,
  CAN_FILTER_B2_F3      = 5,
  CAN_FILTER_B2_F4      = 6

Const

                                              // BRGCON3
  WAKFIL = 6,
                                              // BRGCON2
  SEG2PHTS = 7,
  SAM = 6,
                                              // COMSTAT
  RX1OVFL = 7,
  RXB0OVFL = 7,
  TXBO = 5,
  TXBP = 4,
  RXBP = 3,
                                              // PIR3
  IRXIF = 7,
  RXB1IF = 1,
  RXB0IF = 0,
                                              // CANCON
  ABAT = 4,
                                              // RXBnCON
  RXFUL = 7,
  RXB0DBEN = 2,
                                              // RXBnDLC
  RXRTR = 6,
                                              // RXBnSIDL
  EXID = 3,
                                              // TXBnCON
  TXREQ = 3

Dim

  RXB0CON_RX0DBEN  As RXB0CON.Bits(RXB0DBEN),
  BRGCON2_SAM      As BRGCON2.Bits(SAM),
  BRGCON2_SEG2PHTS As BRGCON2.Bits(SEG2PHTS),
  BRGCON3_WAKFIL   As BRGCON3.Bits(WAKFIL),
  PIR3_RXB0IF      As PIR3.Bits(RXB0IF),
  COMSTAT_RX0OVFL  As COMSTAT.Bits(RXB0OVFL),
  PIR3_RXB1IF      As PIR3.Bits(RXB1IF),
  COMSTAT_RX1OVFL  As COMSTAT.Bits(RX1OVFL),
  RXB0DLC_RTR      As RXB0DLC.Bits(RXRTR),
  RXB0SIDL_EXID    As RXB0SIDL.Bits(EXID),
  PIR3_IRXIF       As PIR3.Bits(IRXIF),

  COMSTAT_TXB0     As COMSTAT.Bits(TXBO),
  COMSTAT_TXBP     As COMSTAT.Bits(TXBP),
  COMSTAT_RXBP     As COMSTAT.Bits(RXBP),
  CANCON_ABAT      As CANCON.Bits(ABAT),
  RXB0CON_RXFUL    As RXB0CON.Bits(RXFUL)

// RXB1CON_RXFUL As RXB1CON.Bits(RXFUL), // TXB0CON_TXREQ As TXB0CON.Bits(TXREQ), // TXB1CON_TXREQ As TXB1CON.Bits(TXREQ), // TXB2CON_TXREQ As TXB2CON.Bits(TXREQ)

Changed lines 307-312 from:
  • Name : CANIDToRegs *
  • Purpose : If given id is standard identifier, *
  • only SIDH and SIDL are updated *
  • If given id is extended identifier, *
  • bits value<17:0> is copied to EIDH, EIDL and SIDH<1:0> *
  • bits value<28:18> is copied to SIDH and SIDL *
to:
  • Name : CANSetOperationMode *
  • Purpose : Given mode byte is copied to CANCON *
  • and made sure that requested mode is set. *
Changed lines 312-326 from:

Sub CANIDToRegs(CANreg As Word, value As LongWord, flags As Byte)

  FSR2 = CANreg
  If (flags And CAN_CONFIG_MSG_TYPE_BIT) <> 0 Then  // Standard Identifier  
    INDF2 = value.Byte0 >> 3                  // Copy SID<7:3> to SIDH<4:0>
    POSTINC2 = INDF2 Or (value.Byte1 << 5)    // Copy SID<10:8> to SIDH<7:5>
    INDF2 = value.Byte0 << 5                  // Copy SID<2:0> to SIDL<7:5>
  Else                                              // Extended Identifier
    INDF2 = value.Byte2 >> 5                  // Copy EID<23:21> to SIDH<2:0>
    POSTINC2 = INDF2 Or (value.Byte3 << 3)    // Copy EID<28:24> to SIDH<7:3>
    INDF2 = (value.Byte2 << 3) And $E0        // Copy EID<20:18> to SIDL<7:5>
    INDF2 = INDF2 Or %00001000                // Set EXIDEN bit  to SIDL<3>
    POSTINC2 = INDF2 Or (value.Byte2 And $03) // Copy EID<17:16> to SIDL<1:0>
    POSTINC2 = value.Byte1                    // Copy EID<15:8> to EIDH<7:0>
    INDF2 = value.Byte0                       // Copy EID<7:0> to EIDL<7:0>
  End If
to:

Public Sub CANSetOperationMode(mode As Byte)

  CANCON = mode   // Request desired mode.  
  While((CANSTAT And CAN_OP_MODE_BITS) <> mode)
    ClrWDT
  Wend            // Wait till desired mode is set.
Changed lines 320-325 from:
  • Name : RegsToCANID *
  • Purpose : If given id is standard identifier, *
  • only SIDH and SIDL are used *
  • If given id is extended identifier, *
  • EIDH, EIDL And SIDH<1:0> is copied To bits value<17:0> *
  • SIDH And SIDL is copied To bits value<28:18> *
to:
  • Name : CANSetBaudRate *
  • Purpose : Given values are bit adjusted to fit in 18CXX8 *
  • BRGCONx registers and copied. *
  • Input : SJW - SJW value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 4) *
  • BRP - BRP value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 64) *
  • PHSEG1 - PHSEG1 value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • PHSEG2 - PHSEG2 value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • PROPSEG - PROPSEG value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • flags - Value of CAN_CONFIG_FLAGS *
Changed lines 336-352 from:

Function RegsToCANID(CANreg As Word, flags As Byte) As LongWord

  FSR2 = CANreg 
  If (flags And CAN_CONFIG_MSG_TYPE_BIT) <> 0 Then  // Standard Identifier
    result.Byte0 = INDF2 << 3                   // Copy SIDH<4:0> to SID<7:3>
    result.Byte1 = POSTINC2 >> 5                // Copy SIDH<7:5> to SID<10:8>
    result.Byte0 = result.Byte0 Or (INDF2 >> 5) // Copy SIDL<7:6> to SID<2:0>
    result.Byte2 = $00
    result.Byte3 = $00                               
  Else                                              // Extended Identifier
    result.Byte2 = INDF2 << 5                   // Copy SIDH<2:0> to EID<23:21>
    result.Byte3 = POSTINC2 >> 3                // Copy SIDH<7:3> to EID<29:25>
    result.Byte2 = result.Byte2 Or (INDF2 And $03) // Copy SIDH<1:0> to EID<17:16>
    result.Byte2 = result.Byte2 Or ((POSTINC2 And $E0) >> 3) // Copy SIDL<7:6> to EID<20:18>
    result.Byte1 = POSTINC2                     // Copy EIDH<15:8> to EID<15:8>
    result.Byte0 = INDF2                        // Copy EIDH<7:0> to EID<7:0>
  End If  

End Function

to:

Sub CANSetBaudRate(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, flags As Byte)

  Dec(SJW)
  Dec(BRP)
  Dec(PHSEG1)
  Dec(PHSEG2)
  Dec(PROPSEG)
  BRGCON1 = SJW << 6
  BRGCON1 = BRGCON1 Or BRP
  BRGCON2 = PHSEG1 << 3
  BRGCON2 = BRGCON2 Or PROPSEG
  If (flags And CAN_CONFIG_SAMPLE_BIT) = 0 Then
    BRGCON2_SAM = 1
  End If
  If (flags And CAN_CONFIG_PHSEG2_PRG_BIT) <> 0 Then
    BRGCON2_SEG2PHTS = 1
  End If
  BRGCON3 = PHSEG2
  If (flags And CAN_CONFIG_LINE_FILTER_BIT) <> 0 Then 
    BRGCON3_WAKFIL = 1
  End If   

End Sub

Changed lines 359-361 from:
  • Name : CANSetMask *
  • Purpose : Given value is bit adjusted to appropriate buffer *
  • mask registers. *
to:
  • Name : CANIDToRegs *
  • Purpose : If given id is standard identifier, *
  • only SIDH and SIDL are updated *
  • If given id is extended identifier, *
  • bits value<17:0> is copied to EIDH, EIDL and SIDH<1:0> *
  • bits value<28:18> is copied to SIDH and SIDL *
Deleted lines 365-382:

} Public Sub CANSetMask(mask As Byte, value As LongWord, flags As Byte) Dim buf As Word

  Save(FSR1, FSR2)
  If mask = CAN_MASK_B1 Then // Select appropriate starting address based on given CAN_MASK value.
    buf = AddressOf(RXM0SIDH)
  Else
    buf = AddressOf(RXM1SIDH)
  End If
  CANIDToRegs(buf, value, flags)
  Restore

End Sub {

  • Name : CANSetFilter *
  • Purpose : Given value is bit adjusted to appropriate buffer *
  • filter registers. *
Changed lines 367-386 from:

Public Sub CANSetFilter(filter As Byte, value As LongWord, flags As Byte) Dim buf As Word

  Save(FSR1, FSR2)
  Select filter
    Case CAN_FILTER_B1_F1
      buf = AddressOf(RXF0SIDH)
    Case CAN_FILTER_B1_F2
      buf = AddressOf(RXF1SIDH)
    Case CAN_FILTER_B2_F1
      buf = AddressOf(RXF2SIDH)
    Case CAN_FILTER_B2_F2
      buf = AddressOf(RXF3SIDH)
    Case CAN_FILTER_B2_F3
      buf = AddressOf(RXF4SIDH)
    Else
      buf = AddressOf(RXF5SIDH)
  End Select
  CANIDToRegs(buf, value, flags)
  Restore

End Sub

to:

Sub CANIDToRegs(CANreg As Word, value As LongWord, flags As Byte)

  FSR2 = CANreg
  If (flags And CAN_CONFIG_MSG_TYPE_BIT) <> 0 Then  // Standard Identifier  
    INDF2 = value.Byte0 >> 3                  // Copy SID<7:3> to SIDH<4:0>
    POSTINC2 = INDF2 Or (value.Byte1 << 5)    // Copy SID<10:8> to SIDH<7:5>
    INDF2 = value.Byte0 << 5                  // Copy SID<2:0> to SIDL<7:5>
  Else                                              // Extended Identifier
    INDF2 = value.Byte2 >> 5                  // Copy EID<23:21> to SIDH<2:0>
    POSTINC2 = INDF2 Or (value.Byte3 << 3)    // Copy EID<28:24> to SIDH<7:3>
    INDF2 = (value.Byte2 << 3) And $E0        // Copy EID<20:18> to SIDL<7:5>
    INDF2 = INDF2 Or %00001000                // Set EXIDEN bit  to SIDL<3>
    POSTINC2 = INDF2 Or (value.Byte2 And $03) // Copy EID<17:16> to SIDL<1:0>
    POSTINC2 = value.Byte1                    // Copy EID<15:8> to EIDH<7:0>
    INDF2 = value.Byte0                       // Copy EID<7:0> to EIDL<7:0>
  End If

End Sub

Changed lines 385-397 from:
  • Name : CANInitialize *
  • Purpose : Initialize CAN module, Filters, Mask *
  • Input : SJW - SJW value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 4) *
  • BRP - BRP value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 64) *
  • PHSEG1 - PHSEG1 value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • PHSEG2 - PHSEG2 value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • PROPSEG - PROPSEG value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • flags - Value of CAN_CONFIG_FLAGS *
to:
  • Name : RegsToCANID *
  • Purpose : If given id is standard identifier, *
  • only SIDH and SIDL are used *
  • If given id is extended identifier, *
  • EIDH, EIDL And SIDH<1:0> is copied To bits value<17:0> *
  • SIDH And SIDL is copied To bits value<28:18> *
Changed lines 393-395 from:

Public Sub CANInitialize(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, flags As Byte) Dim FilterConfig1 As Byte,

    FilterConfig2 As Byte
to:

Function RegsToCANID(CANreg As Word, flags As Byte) As LongWord

  FSR2 = CANreg 
  If (flags And CAN_CONFIG_MSG_TYPE_BIT) <> 0 Then  // Standard Identifier
    result.Byte0 = INDF2 << 3                   // Copy SIDH<4:0> to SID<7:3>
    result.Byte1 = POSTINC2 >> 5                // Copy SIDH<7:5> to SID<10:8>
    result.Byte0 = result.Byte0 Or (INDF2 >> 5) // Copy SIDL<7:6> to SID<2:0>
    result.Byte2 = $00
    result.Byte3 = $00                               
  Else                                              // Extended Identifier
    result.Byte2 = INDF2 << 5                   // Copy SIDH<2:0> to EID<23:21>
    result.Byte3 = POSTINC2 >> 3                // Copy SIDH<7:3> to EID<29:25>
    result.Byte2 = result.Byte2 Or (INDF2 And $03) // Copy SIDH<1:0> to EID<17:16>
    result.Byte2 = result.Byte2 Or ((POSTINC2 And $E0) >> 3) // Copy SIDL<7:6> to EID<20:18>
    result.Byte1 = POSTINC2                     // Copy EIDH<15:8> to EID<15:8>
    result.Byte0 = INDF2                        // Copy EIDH<7:0> to EID<7:0>
  End If  

End Function {

  • Name : CANSetMask *
  • Purpose : Given value is bit adjusted to appropriate buffer *
  • mask registers. *

} Public Sub CANSetMask(mask As Byte, value As LongWord, flags As Byte) Dim buf As Word

Changed lines 420-437 from:
  #if _device in (18F248, 18F258, 18F448, 18F458, 18F2480, 18F2580, 18F4480, 18F4580, 18F2682, 18F2685, 18F4682, 18F4685)
  TRISB.2 = 0 'TX CAN
  TRISB.3 = 1 'RX CAN
  #else
  TRISG.0 = 0 'TX CAN
  TRISG.2 = 1 'RX CAN
  #endif
  CIOCON = 0
  CANSetOperationMode(CAN_OP_MODE_CONFIG) // In order to setup necessary config parameters of CAN module, it must be in Config mode. 
  #if _device in (18F248, 18F258, 18F448, 18F458)
  Nop
  #else
  ECANCON = ECANCON And %00111111
  #endif    
  CANSetBaudRate(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, flags) // Now set the baud rate.
  RXB0CON = flags And CAN_CONFIG_MSG_BITS
  If (flags And CAN_CONFIG_DBL_BUFFER_BIT) = CAN_CONFIG_DBL_BUFFER_ON Then
    RXB0CON_RX0DBEN = 1
to:
  If mask = CAN_MASK_B1 Then // Select appropriate starting address based on given CAN_MASK value.
    buf = AddressOf(RXM0SIDH)
  Else
    buf = AddressOf(RXM1SIDH)
Changed lines 425-445 from:
  RXB1CON = RXB0CON  
  CANSetMask(CAN_MASK_B1, 0, CAN_CONFIG_XTD_MSG)  // Set default filter and mask registers for all receive buffers.
  CANSetMask(CAN_MASK_B2, 0, CAN_CONFIG_XTD_MSG)
  Select ((flags And CAN_CONFIG_MSG_BITS) Or (Not(CAN_CONFIG_MSG_BITS)))
    Case CAN_CONFIG_VALID_XTD_MSG
      FilterConfig1 = CAN_CONFIG_XTD_MSG
      FilterConfig2 = CAN_CONFIG_XTD_MSG
    Case CAN_CONFIG_VALID_STD_MSG
      FilterConfig1 = CAN_CONFIG_STD_MSG
      FilterConfig2 = CAN_CONFIG_STD_MSG
    Else
      FilterConfig1 = CAN_CONFIG_STD_MSG
      FilterConfig2 = CAN_CONFIG_XTD_MSG
  End Select 
  CANSetFilter(CAN_FILTER_B1_F1, 0, FilterConfig1) // By default, there will be no mask on any receive filters, hence filter value of '0' will be ignored.
  CANSetFilter(CAN_FILTER_B1_F2, 0, FilterConfig1)
  CANSetFilter(CAN_FILTER_B2_F1, 0, FilterConfig2)
  CANSetFilter(CAN_FILTER_B2_F2, 0, FilterConfig2)
  CANSetFilter(CAN_FILTER_B2_F3, 0, FilterConfig2)
  CANSetFilter(CAN_FILTER_B2_F4, 0, FilterConfig2)  
  CANSetOperationMode(CAN_OP_MODE_NORMAL)         // Restore to Normal mode.
to:
  CANIDToRegs(buf, value, flags)
Changed lines 430-433 from:
  • Name : CANSendMessage *
  • Purpose : If at least one empty transmit buffer is found, *
  • given message is queued to be transmitted. *
  • If none found FALSE value is returned. *
to:
  • Name : CANSetFilter *
  • Purpose : Given value is bit adjusted to appropriate buffer *
  • filter registers. *
Changed lines 434-436 from:

} Public Function CANSendMessage(id As LongWord, ByRef Data() As Byte, DataLen, flags As Byte) As Boolean Dim i As Byte

to:

} Public Sub CANSetFilter(filter As Byte, value As LongWord, flags As Byte) Dim buf As Word

Changed lines 438-448 from:
  FSR2 = AddressOf(TXB0CON)           // For compatibility with SwordfishSE
  If INDF2.bits(TXREQ) = 0 Then       // Find the first empty transmitter.

// If TXB0CON_TXREQ = 0 Then

    CANCON = CANCON And %11110001     // TxBuffer0 is empty.  Set WIN bits to point to TXB0
    CANCON = CANCON Or %00001000
  Else
    FSR2 = AddressOf(TXB1CON)         // For compatibility with SwordfishSE
    If INDF2.bits(TXREQ) = 0 Then  

// If TXB1CON_TXREQ = 0 Then

      CANCON = CANCON And %11110001   // TxBuffer1 is empty. Set WIN bits to point to TXB1
      CANCON = CANCON Or %00000110
to:
  Select filter
    Case CAN_FILTER_B1_F1
      buf = AddressOf(RXF0SIDH)
    Case CAN_FILTER_B1_F2
      buf = AddressOf(RXF1SIDH)
    Case CAN_FILTER_B2_F1
      buf = AddressOf(RXF2SIDH)
    Case CAN_FILTER_B2_F2
      buf = AddressOf(RXF3SIDH)
    Case CAN_FILTER_B2_F3
      buf = AddressOf(RXF4SIDH)
Changed lines 450-482 from:
      FSR2 = AddressOf(TXB2CON)       // For compatibility with SwordfishSE
      If INDF2.bits(TXREQ) = 0 Then

// If TXB2CON_TXREQ = 0 Then

        CANCON = CANCON And %11110001 // TxBuffer2 is empty. Set WIN bits to point to TXB2
        CANCON = CANCON Or %00000100
      Else
        result = false                // None of the transmit buffers were empty.
        Exit
      End If
    End If
  End If      
  RXB0CON = flags And CAN_TX_PRIORITY_BITS  // Set transmit priority.
  If (flags And CAN_TX_FRAME_BIT) = 0 Then  // Populate Extended identifier information only if it is desired.
    CANIDToRegs(AddressOf(RXB0SIDH), id, CAN_CONFIG_XTD_MSG)
  Else
    CANIDToRegs(AddressOf(RXB0SIDH), id, CAN_CONFIG_STD_MSG)
  End If
  RXB0DLC = DataLen
  If (flags And CAN_TX_RTR_BIT) = 0 Then
    RXB0DLC = RXB0DLC Or %01000000
  End If
  i = 0
  FSR2 = AddressOf(RXB0D0)            // Populate data values.
  FSR1 = AddressOf(Data)
  While i < DataLen 
    POSTINC2 = POSTINC1
    Inc(i)
  Wend
  ASM
    bsf RXB0CON, 3
  End ASM
  CANCON = CANCON And %11110001
  result = true
to:
      buf = AddressOf(RXF5SIDH)
  End Select
  CANIDToRegs(buf, value, flags)
Changed line 454 from:

End Function

to:

End Sub

Changed lines 457-460 from:
  • Name : CANReceiveMessage *
  • Purpose : If at least one full receive buffer is found, *
  • it is extrated and returned. *
  • If none found FALSE value is returned. *
to:
  • Name : CANInitialize *
  • Purpose : Initialize CAN module, Filters, Mask *
  • Input : SJW - SJW value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 4) *
  • BRP - BRP value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 64) *
  • PHSEG1 - PHSEG1 value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • PHSEG2 - PHSEG2 value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • PROPSEG - PROPSEG value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • flags - Value of CAN_CONFIG_FLAGS *
Changed lines 471-474 from:

} Public Function CANReceiveMessage(ByRef id As LongWord, ByRef Data(), DataLen, flags As Byte) As Boolean Dim i, buf As Byte,

    lbIsItBuffer0 As Boolean  
to:

} Public Sub CANInitialize(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, flags As Byte) Dim FilterConfig1 As Byte,

    FilterConfig2 As Byte
Changed lines 476-506 from:
  flags = 0                         // Start with no error or flags set.
  If RXB0CON_RXFUL = 1 Then         // Find which buffer is ready.    
    CANCON = CANCON And %11110001   // RXBuffer0 is full.
    lbIsItBuffer0 = true
    PIR3_RXB0IF = 0                 // Clear the received flag.    
    If COMSTAT_RX0OVFL = 1 Then     // Record and forget any previous overflow
      flags = flags Or CAN_RX_OVERFLOW
      COMSTAT_RX0OVFL = 0
    End If
    If RXB0CON_RX0DBEN = 1 Then
      flags = (flags Or RXB0CON) And CAN_RX_FILTER_BITS
      flags = flags And $01
    End If
  Else
    FSR2 = AddressOf(RXB1CON)       // For compatibility with SwordfishSE
    If INDF2.bits(RXFUL) = 1 Then

// If RXB1CON_RXFUL = 1 Then

      CANCON = CANCON And %11110001 // RXBuffer1 is full
      CANCON = CANCON Or %00001010
      lbIsItBuffer0 = false      
      PIR3_RXB1IF = 0               // Clear the received flag.
      If COMSTAT_RX1OVFL = 1 Then   // Record and forget any previous overflow
        flags = flags Or CAN_RX_OVERFLOW
        COMSTAT_RX1OVFL = 0
      End If
      FSR2 = AddressOf(RXB1CON)      // For compatibility with SwordfishSE
      flags = (flags Or INDF2) And CAN_RX_FILTER_BITS

// flags = (flags Or RXB1CON) And CAN_RX_FILTER_BITS

      If flags < $02 Then
        flags = flags Or CAN_RX_DBL_BUFFERED
      End If
to:
  #if _device in (18F248, 18F258, 18F448, 18F458, 18F2480, 18F2580, 18F4480, 18F4580, 18F2682, 18F2685, 18F4682, 18F4685)
  TRISB.2 = 0 'TX CAN
  TRISB.3 = 1 'RX CAN
  #else
  TRISG.0 = 0 'TX CAN
  TRISG.2 = 1 'RX CAN
  #endif
  CIOCON = 0
  CANSetOperationMode(CAN_OP_MODE_CONFIG) // In order to setup necessary config parameters of CAN module, it must be in Config mode. 
  #if _device in (18F248, 18F258, 18F448, 18F458)
  Nop
  #else
  ECANCON = ECANCON And %00111111
  #endif    
  CANSetBaudRate(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, flags) // Now set the baud rate.
  RXB0CON = flags And CAN_CONFIG_MSG_BITS
  If (flags And CAN_CONFIG_DBL_BUFFER_BIT) = CAN_CONFIG_DBL_BUFFER_ON Then
    RXB0CON_RX0DBEN = 1
  End If
  RXB1CON = RXB0CON  
  CANSetMask(CAN_MASK_B1, 0, CAN_CONFIG_XTD_MSG)  // Set default filter and mask registers for all receive buffers.
  CANSetMask(CAN_MASK_B2, 0, CAN_CONFIG_XTD_MSG)
  Select ((flags And CAN_CONFIG_MSG_BITS) Or (Not(CAN_CONFIG_MSG_BITS)))
    Case CAN_CONFIG_VALID_XTD_MSG
      FilterConfig1 = CAN_CONFIG_XTD_MSG
      FilterConfig2 = CAN_CONFIG_XTD_MSG
    Case CAN_CONFIG_VALID_STD_MSG
      FilterConfig1 = CAN_CONFIG_STD_MSG
      FilterConfig2 = CAN_CONFIG_STD_MSG
Changed lines 506-516 from:
      result = false
      Exit
    End If
  End If 
  DataLen = RXB0DLC And %00001111   // Retrieve message length.  
  If RXB0DLC_RTR = 1 Then           // Determine whether this was RTR or not.
    flags = flags Or CAN_RX_RTR_FRAME
  End If 
  If RXB0SIDL_EXID = 1 Then         // Retrieve EIDX bytes only if this is extended message
    flags = flags Or CAN_RX_XTD_FRAME
    id = RegsToCANID(AddressOf(RXB0SIDH), CAN_CONFIG_XTD_MSG)
to:
      FilterConfig1 = CAN_CONFIG_STD_MSG
      FilterConfig2 = CAN_CONFIG_XTD_MSG
  End Select 
  CANSetFilter(CAN_FILTER_B1_F1, 0, FilterConfig1) // By default, there will be no mask on any receive filters, hence filter value of '0' will be ignored.
  CANSetFilter(CAN_FILTER_B1_F2, 0, FilterConfig1)
  CANSetFilter(CAN_FILTER_B2_F1, 0, FilterConfig2)
  CANSetFilter(CAN_FILTER_B2_F2, 0, FilterConfig2)
  CANSetFilter(CAN_FILTER_B2_F3, 0, FilterConfig2)
  CANSetFilter(CAN_FILTER_B2_F4, 0, FilterConfig2)  
  CANSetOperationMode(CAN_OP_MODE_NORMAL)         // Restore to Normal mode.
  Restore

End Sub {

  • Name : CANSendMessage *
  • Purpose : If at least one empty transmit buffer is found, *
  • given message is queued to be transmitted. *
  • If none found FALSE value is returned. *

} Public Function CANSendMessage(id As LongWord, ByRef Data() As Byte, DataLen, flags As Byte) As Boolean Dim i As Byte

  Save(FSR1, FSR2)
  FSR2 = AddressOf(TXB0CON)           // For compatibility with SwordfishSE
  If INDF2.bits(TXREQ) = 0 Then       // Find the first empty transmitter.

// If TXB0CON_TXREQ = 0 Then

    CANCON = CANCON And %11110001     // TxBuffer0 is empty.  Set WIN bits to point to TXB0
    CANCON = CANCON Or %00001000
Changed lines 535-536 from:
    id = RegsToCANID(AddressOf(RXB0SIDH), CAN_CONFIG_STD_MSG)
  End If  
to:
    FSR2 = AddressOf(TXB1CON)         // For compatibility with SwordfishSE
    If INDF2.bits(TXREQ) = 0 Then  

// If TXB1CON_TXREQ = 0 Then

      CANCON = CANCON And %11110001   // TxBuffer1 is empty. Set WIN bits to point to TXB1
      CANCON = CANCON Or %00000110
    Else
      FSR2 = AddressOf(TXB2CON)       // For compatibility with SwordfishSE
      If INDF2.bits(TXREQ) = 0 Then

// If TXB2CON_TXREQ = 0 Then

        CANCON = CANCON And %11110001 // TxBuffer2 is empty. Set WIN bits to point to TXB2
        CANCON = CANCON Or %00000100
      Else
        result = false                // None of the transmit buffers were empty.
        Exit
      End If
    End If
  End If      
  RXB0CON = flags And CAN_TX_PRIORITY_BITS  // Set transmit priority.
  If (flags And CAN_TX_FRAME_BIT) = 0 Then  // Populate Extended identifier information only if it is desired.
    CANIDToRegs(AddressOf(RXB0SIDH), id, CAN_CONFIG_XTD_MSG)
  Else
    CANIDToRegs(AddressOf(RXB0SIDH), id, CAN_CONFIG_STD_MSG)
  End If
  RXB0DLC = DataLen
  If (flags And CAN_TX_RTR_BIT) = 0 Then
    RXB0DLC = RXB0DLC Or %01000000
  End If
Changed lines 563-566 from:
  buf = DataLen                     // Get message data itself
  FSR1 = AddressOf(RXB0D0)
  FSR2 = AddressOf(Data)
  While i < buf 
to:
  FSR2 = AddressOf(RXB0D0)            // Populate data values.
  FSR1 = AddressOf(Data)
  While i < DataLen 
Changed lines 568-580 from:
  Wend  
  CANCON = CANCON And %11110001     // Restore default RXB0 mapping.  
  If PIR3_IRXIF = 1 Then            // Record and Clear any previous invalid message bit flag.
    flags = flags Or CAN_RX_INVALID_MSG
    PIR3_IRXIF = 0
  End If
  If lbIsItBuffer0 = true Then 
    RXB0CON_RXFUL = 0
  Else
    FSR2 = AddressOf(RXB1CON)       // For compatibility with SwordfishSE
    INDF2.bits(RXFUL) = 0

// RXB1CON_RXFUL = 0

  End If
to:
  Wend
  ASM
    bsf RXB0CON, 3
  End ASM
  CANCON = CANCON And %11110001
Changed lines 578-579 from:
  • Name : String2ID *
  • Purpose : Transform 3 Char String into LongWord id *
to:
  • Name : CANReceiveMessage *
  • Purpose : If at least one full receive buffer is found, *
  • it is extrated and returned. *
  • If none found FALSE value is returned. *
Added lines 583-661:

} Public Function CANReceiveMessage(ByRef id As LongWord, ByRef Data(), DataLen, flags As Byte) As Boolean Dim i, buf As Byte,

    lbIsItBuffer0 As Boolean  
  Save(FSR1, FSR2)
  flags = 0                         // Start with no error or flags set.
  If RXB0CON_RXFUL = 1 Then         // Find which buffer is ready.    
    CANCON = CANCON And %11110001   // RXBuffer0 is full.
    lbIsItBuffer0 = true
    PIR3_RXB0IF = 0                 // Clear the received flag.    
    If COMSTAT_RX0OVFL = 1 Then     // Record and forget any previous overflow
      flags = flags Or CAN_RX_OVERFLOW
      COMSTAT_RX0OVFL = 0
    End If
    If RXB0CON_RX0DBEN = 1 Then
      flags = (flags Or RXB0CON) And CAN_RX_FILTER_BITS
      flags = flags And $01
    End If
  Else
    FSR2 = AddressOf(RXB1CON)       // For compatibility with SwordfishSE
    If INDF2.bits(RXFUL) = 1 Then

// If RXB1CON_RXFUL = 1 Then

      CANCON = CANCON And %11110001 // RXBuffer1 is full
      CANCON = CANCON Or %00001010
      lbIsItBuffer0 = false      
      PIR3_RXB1IF = 0               // Clear the received flag.
      If COMSTAT_RX1OVFL = 1 Then   // Record and forget any previous overflow
        flags = flags Or CAN_RX_OVERFLOW
        COMSTAT_RX1OVFL = 0
      End If
      FSR2 = AddressOf(RXB1CON)      // For compatibility with SwordfishSE
      flags = (flags Or INDF2) And CAN_RX_FILTER_BITS

// flags = (flags Or RXB1CON) And CAN_RX_FILTER_BITS

      If flags < $02 Then
        flags = flags Or CAN_RX_DBL_BUFFERED
      End If
    Else
      result = false
      Exit
    End If
  End If 
  DataLen = RXB0DLC And %00001111   // Retrieve message length.  
  If RXB0DLC_RTR = 1 Then           // Determine whether this was RTR or not.
    flags = flags Or CAN_RX_RTR_FRAME
  End If 
  If RXB0SIDL_EXID = 1 Then         // Retrieve EIDX bytes only if this is extended message
    flags = flags Or CAN_RX_XTD_FRAME
    id = RegsToCANID(AddressOf(RXB0SIDH), CAN_CONFIG_XTD_MSG)
  Else
    id = RegsToCANID(AddressOf(RXB0SIDH), CAN_CONFIG_STD_MSG)
  End If  
  i = 0
  buf = DataLen                     // Get message data itself
  FSR1 = AddressOf(RXB0D0)
  FSR2 = AddressOf(Data)
  While i < buf 
    POSTINC2 = POSTINC1
    Inc(i)
  Wend  
  CANCON = CANCON And %11110001     // Restore default RXB0 mapping.  
  If PIR3_IRXIF = 1 Then            // Record and Clear any previous invalid message bit flag.
    flags = flags Or CAN_RX_INVALID_MSG
    PIR3_IRXIF = 0
  End If
  If lbIsItBuffer0 = true Then 
    RXB0CON_RXFUL = 0
  Else
    FSR2 = AddressOf(RXB1CON)       // For compatibility with SwordfishSE
    INDF2.bits(RXFUL) = 0

// RXB1CON_RXFUL = 0

  End If
  result = true
  Restore

End Function {

  • Name : String2ID *
  • Purpose : Transform 3 Char String into LongWord id *
Changed lines 50-74 from:
to:

{

  • Name : CANSendMessage *
  • Purpose : If at least one empty transmit buffer is found, *
  • given message is queued to be transmitted. *
  • If none found FALSE value is returned. *

} Public Function CANSendMessage(id As LongWord, ByRef Data() As Byte, DataLen, flags As Byte) As Boolean {

  • Name : CANReceiveMessage *
  • Purpose : If at least one full receive buffer is found, *
  • it is extrated and returned. *
  • If none found FALSE value is returned. *

} Public Function CANReceiveMessage(ByRef id As LongWord, ByRef Data(), DataLen, flags As Byte) As Boolean {

  • Name : String2ID *
  • Purpose : Transform 3 Char String into LongWord id *

} Public Function String2ID(str_in As String) As LongWord

Changed lines 136-147 from:
  • Name : Sensirion.BAS *
  • Author : Medrea Florin Andrei *
  • Notice : Copyright (c) 2007 -YO2LIO- *
  • : All Rights Reserved *
  • Date : 9/26/2007 *
  • *
  • Copyright Notice *
  • *
  • This library For the SHT temperature And humidity sensors is based on the *
  • application datasheet Sample Code humidity sensor SHTxx from Sensirion. *
to:
  • Name : CAN_lib.BAS *
  • Author : Florin Andrei Medrea *
  • Notice : Copyright (c) 2007 - YO2LIO - *
  • : All Rights Reserved *
  • Date : 10/26/2007 *
  • Version : 1.0 *
  • Notes : This module is based on Microchip sample *
  • : CAN Application Note AN738 *
Changed lines 147-168 from:

Module Sensirion

Include "math" Include "system"

Const NoACK As Byte = 1,

      ACK As Byte = 0,
      CMD_STATUS_REG_W As Byte = $06,
      CMD_STATUS_REG_R As Byte = $07,
      CMD_TEMP As Byte = $03,
      CMD_HUMIDITY As Byte = $05,
      CMD_RESET As Byte = $1E

Structure TPin

   Pin As Byte
   PinMask As Byte

End Structure

Structure TPort

   AddrPort As Word
   AddrTRIS As Word

End Structure

to:

Module CAN_lib

Include "SYS_lib"

Public Const

  CAN_TX_PRIORITY_BITS= %00000011,
  CAN_TX_PRIORITY_0   = %11111100,            // XXXXXX00
  CAN_TX_PRIORITY_1   = %11111101,            // XXXXXX01
  CAN_TX_PRIORITY_2   = %11111110,            // XXXXXX10
  CAN_TX_PRIORITY_3   = %11111111,            // XXXXXX11

  CAN_TX_FRAME_BIT    = %00001000,
  CAN_TX_STD_FRAME    = %11111111,            // XXXXX1XX
  CAN_TX_XTD_FRAME    = %11110111,            // XXXXX0XX

  CAN_TX_RTR_BIT      = %01000000,
  CAN_TX_NO_RTR_FRAME = %11111111,            // X1XXXXXX
  CAN_TX_RTR_FRAME    = %10111111,            // X0XXXXXX
Changed lines 166-170 from:

Dim SData,SClock As TPin Dim SPort As TPort Dim data_h,data_l,data_cksum As Byte

Public Sub Sensirion_Init(ByRef pData As Bit, ByRef pClock As Bit)

to:
  CAN_RX_FILTER_BITS  = %00000111,
  CAN_RX_FILTER_1     = %00000000,
  CAN_RX_FILTER_2     = %00000001,
  CAN_RX_FILTER_3     = %00000010,
  CAN_RX_FILTER_4     = %00000011,
  CAN_RX_FILTER_5     = %00000100,
  CAN_RX_FILTER_6     = %00000101,

  CAN_RX_OVERFLOW     = %00001000,            // Set if Overflowed else cleared 
  CAN_RX_INVALID_MSG  = %00010000,            // Set if invalid else cleared
  CAN_RX_XTD_FRAME    = %00100000,            // Set if XTD message else cleared
  CAN_RX_RTR_FRAME    = %01000000,            // Set if RTR message else cleared
  CAN_RX_DBL_BUFFERED = %10000000,            // Set if this message was hardware double-buffered

  CAN_OP_MODE_BITS    = %11100000,
  CAN_OP_MODE_NORMAL  = %00000000,
  CAN_OP_MODE_SLEEP   = %00100000,
  CAN_OP_MODE_LOOP    = %01000000,
  CAN_OP_MODE_LISTEN  = %01100000,
  CAN_OP_MODE_CONFIG  = %10000000,

  CAN_CONFIG_DEFAULT          = %11111111,    // 11111111
  CAN_CONFIG_PHSEG2_PRG_BIT   = %00000001,
  CAN_CONFIG_PHSEG2_PRG_ON    = %11111111,    // XXXXXXX1
  CAN_CONFIG_PHSEG2_PRG_OFF   = %11111110,    // XXXXXXX0

  CAN_CONFIG_LINE_FILTER_BIT  = %00000010,
  CAN_CONFIG_LINE_FILTER_ON   = %11111111,    // XXXXXX1X
  CAN_CONFIG_LINE_FILTER_OFF  = %11111101,    // XXXXXX0X

  CAN_CONFIG_SAMPLE_BIT       = %00000100,
  CAN_CONFIG_SAMPLE_ONCE      = %11111111,    // XXXXX1XX
  CAN_CONFIG_SAMPLE_THRICE    = %11111011,    // XXXXX0XX

  CAN_CONFIG_MSG_TYPE_BIT     = %00001000,
  CAN_CONFIG_STD_MSG          = %11111111,    // XXXX1XXX
  CAN_CONFIG_XTD_MSG          = %11110111,    // XXXX0XXX

  CAN_CONFIG_DBL_BUFFER_BIT   = %00010000,
  CAN_CONFIG_DBL_BUFFER_ON    = %11111111,    // XXX1XXXX
  CAN_CONFIG_DBL_BUFFER_OFF   = %11101111,    // XXX0XXXX

  CAN_CONFIG_MSG_BITS         = %01100000,
  CAN_CONFIG_ALL_MSG          = %11111111,    // X11XXXXX
  CAN_CONFIG_VALID_XTD_MSG    = %11011111,    // X10XXXXX
  CAN_CONFIG_VALID_STD_MSG    = %10111111,    // X01XXXXX
  CAN_CONFIG_ALL_VALID_MSG    = %10011111,    // X00XXXXX

  CAN_MASK_B1           = 1,
  CAN_MASK_B2           = 2,

  CAN_FILTER_B1_F1      = 1,
  CAN_FILTER_B1_F2      = 2,
  CAN_FILTER_B2_F1      = 3,
  CAN_FILTER_B2_F2      = 4,
  CAN_FILTER_B2_F3      = 5,
  CAN_FILTER_B2_F4      = 6

Const

                                              // BRGCON3
  WAKFIL = 6,
                                              // BRGCON2
  SEG2PHTS = 7,
  SAM = 6,
                                              // COMSTAT
  RX1OVFL = 7,
  RXB0OVFL = 7,
  TXBO = 5,
  TXBP = 4,
  RXBP = 3,
                                              // PIR3
  IRXIF = 7,
  RXB1IF = 1,
  RXB0IF = 0,
                                              // CANCON
  ABAT = 4,
                                              // RXBnCON
  RXFUL = 7,
  RXB0DBEN = 2,
                                              // RXBnDLC
  RXRTR = 6,
                                              // RXBnSIDL
  EXID = 3,
                                              // TXBnCON
  TXREQ = 3

Dim

  RXB0CON_RX0DBEN  As RXB0CON.Bits(RXB0DBEN),
  BRGCON2_SAM      As BRGCON2.Bits(SAM),
  BRGCON2_SEG2PHTS As BRGCON2.Bits(SEG2PHTS),
  BRGCON3_WAKFIL   As BRGCON3.Bits(WAKFIL),
  PIR3_RXB0IF      As PIR3.Bits(RXB0IF),
  COMSTAT_RX0OVFL  As COMSTAT.Bits(RXB0OVFL),
  PIR3_RXB1IF      As PIR3.Bits(RXB1IF),
  COMSTAT_RX1OVFL  As COMSTAT.Bits(RX1OVFL),
  RXB0DLC_RTR      As RXB0DLC.Bits(RXRTR),
  RXB0SIDL_EXID    As RXB0SIDL.Bits(EXID),
  PIR3_IRXIF       As PIR3.Bits(IRXIF),

  COMSTAT_TXB0     As COMSTAT.Bits(TXBO),
  COMSTAT_TXBP     As COMSTAT.Bits(TXBP),
  COMSTAT_RXBP     As COMSTAT.Bits(RXBP),
  CANCON_ABAT      As CANCON.Bits(ABAT),
  RXB0CON_RXFUL    As RXB0CON.Bits(RXFUL)

// RXB1CON_RXFUL As RXB1CON.Bits(RXFUL), // TXB0CON_TXREQ As TXB0CON.Bits(TXREQ), // TXB1CON_TXREQ As TXB1CON.Bits(TXREQ), // TXB2CON_TXREQ As TXB2CON.Bits(TXREQ)

{

  • Name : CANSetOperationMode *
  • Purpose : Given mode byte is copied to CANCON *
  • and made sure that requested mode is set. *

} Public Sub CANSetOperationMode(mode As Byte)

  CANCON = mode   // Request desired mode.  
  While((CANSTAT And CAN_OP_MODE_BITS) <> mode)
Changed lines 286-299 from:
    DelayMS(100)
    ClrWDT
    SPort.AddrPort = AddressOf(pData)       // get pin address
    SPort.AddrTRIS = SPort.AddrPort + 18    // get pin TRIS address
    SData.Pin = BitOf(pData)                // get pin number
    SData.PinMask = Not SData.Pin           // create pin number mask
    SClock.Pin = BitOf(pClock)              // get pin number
    SClock.PinMask = Not SClock.Pin         // create pin number mask  
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin
    INDF2 = INDF2 And SClock.PinMask        // clear pin    
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    INDF2 = INDF2 And SClock.PinMask        // make output SClock 
to:
  Wend            // Wait till desired mode is set.
Changed lines 288-304 from:

Public Sub Sensirion_Init_(ByRef pPort As Byte, pData, pClock As Byte)

    ClrWDT
    DelayMS(100)
    ClrWDT
    SPort.AddrPort = AddressOf(pPort)       // get port address
    SPort.AddrTRIS = SPort.AddrPort + 18    // get port TRIS address
    SData.Pin = 1 << pData                  // get pin number
    SData.PinMask = Not SData.Pin           // create pin number mask
    SClock.Pin = 1 << pClock                // get pin number
    SClock.PinMask = Not SClock.Pin         // create pin number mask  
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin
    INDF2 = INDF2 And SClock.PinMask        // clear pin    
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    INDF2 = INDF2 And SClock.PinMask        // make output SClock 
to:

{

  • Name : CANSetBaudRate *
  • Purpose : Given values are bit adjusted to fit in 18CXX8 *
  • BRGCONx registers and copied. *
  • Input : SJW - SJW value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 4) *
  • BRP - BRP value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 64) *
  • PHSEG1 - PHSEG1 value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • PHSEG2 - PHSEG2 value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • PROPSEG - PROPSEG value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • flags - Value of CAN_CONFIG_FLAGS *

} Sub CANSetBaudRate(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, flags As Byte)

  Dec(SJW)
  Dec(BRP)
  Dec(PHSEG1)
  Dec(PHSEG2)
  Dec(PROPSEG)
  BRGCON1 = SJW << 6
  BRGCON1 = BRGCON1 Or BRP
  BRGCON2 = PHSEG1 << 3
  BRGCON2 = BRGCON2 Or PROPSEG
  If (flags And CAN_CONFIG_SAMPLE_BIT) = 0 Then
    BRGCON2_SAM = 1
  End If
  If (flags And CAN_CONFIG_PHSEG2_PRG_BIT) <> 0 Then
    BRGCON2_SEG2PHTS = 1
  End If
  BRGCON3 = PHSEG2
  If (flags And CAN_CONFIG_LINE_FILTER_BIT) <> 0 Then 
    BRGCON3_WAKFIL = 1
  End If   
Changed lines 327-343 from:

Sub Sensirion_Start()

    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin SData
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)
    INDF2 = INDF2 And SData.PinMask         // clear pin SData
    DelayUS(1)
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)    
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)    
    INDF2 = INDF2 Or SData.Pin              // set pin SData
    DelayUS(1)
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock    
to:

{

  • Name : CANIDToRegs *
  • Purpose : If given id is standard identifier, *
  • only SIDH and SIDL are updated *
  • If given id is extended identifier, *
  • bits value<17:0> is copied to EIDH, EIDL and SIDH<1:0> *
  • bits value<28:18> is copied to SIDH and SIDL *

} Sub CANIDToRegs(CANreg As Word, value As LongWord, flags As Byte)

  FSR2 = CANreg
  If (flags And CAN_CONFIG_MSG_TYPE_BIT) <> 0 Then  // Standard Identifier  
    INDF2 = value.Byte0 >> 3                  // Copy SID<7:3> to SIDH<4:0>
    POSTINC2 = INDF2 Or (value.Byte1 << 5)    // Copy SID<10:8> to SIDH<7:5>
    INDF2 = value.Byte0 << 5                  // Copy SID<2:0> to SIDL<7:5>
  Else                                              // Extended Identifier
    INDF2 = value.Byte2 >> 5                  // Copy EID<23:21> to SIDH<2:0>
    POSTINC2 = INDF2 Or (value.Byte3 << 3)    // Copy EID<28:24> to SIDH<7:3>
    INDF2 = (value.Byte2 << 3) And $E0        // Copy EID<20:18> to SIDL<7:5>
    INDF2 = INDF2 Or %00001000                // Set EXIDEN bit  to SIDL<3>
    POSTINC2 = INDF2 Or (value.Byte2 And $03) // Copy EID<17:16> to SIDL<1:0>
    POSTINC2 = value.Byte1                    // Copy EID<15:8> to EIDH<7:0>
    INDF2 = value.Byte0                       // Copy EID<7:0> to EIDL<7:0>
  End If
Changed lines 353-376 from:

Function Sensirion_Get_Byte(ack_ As Byte) As Byte Dim i,buf As Byte

    buf = 0
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 Or SData.Pin              // make input SData
    FSR2 = SPort.AddrPort
    i = 0
    While i < 8
        INDF2 = INDF2 Or SClock.Pin         // set pin SClock
        DelayUS(1)        
        If (INDF2 And SData.Pin) > 0 Then
            buf = buf Or 1
        End If
        INDF2 = INDF2 And SClock.PinMask    // clear pin SClock
        DelayUS(1)
        Inc(i)
        If i < 8 Then buf = buf << 1 End If
    Wend
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    FSR2 = SPort.AddrPort
    If ack_ = 0 Then 
        INDF2 = INDF2 And SData.PinMask     // clear pin SData
to:

{

  • Name : RegsToCANID *
  • Purpose : If given id is standard identifier, *
  • only SIDH and SIDL are used *
  • If given id is extended identifier, *
  • EIDH, EIDL And SIDH<1:0> is copied To bits value<17:0> *
  • SIDH And SIDL is copied To bits value<28:18> *

} Function RegsToCANID(CANreg As Word, flags As Byte) As LongWord

  FSR2 = CANreg 
  If (flags And CAN_CONFIG_MSG_TYPE_BIT) <> 0 Then  // Standard Identifier
    result.Byte0 = INDF2 << 3                   // Copy SIDH<4:0> to SID<7:3>
    result.Byte1 = POSTINC2 >> 5                // Copy SIDH<7:5> to SID<10:8>
    result.Byte0 = result.Byte0 Or (INDF2 >> 5) // Copy SIDL<7:6> to SID<2:0>
    result.Byte2 = $00
    result.Byte3 = $00                               
  Else                                              // Extended Identifier
    result.Byte2 = INDF2 << 5                   // Copy SIDH<2:0> to EID<23:21>
    result.Byte3 = POSTINC2 >> 3                // Copy SIDH<7:3> to EID<29:25>
    result.Byte2 = result.Byte2 Or (INDF2 And $03) // Copy SIDH<1:0> to EID<17:16>
    result.Byte2 = result.Byte2 Or ((POSTINC2 And $E0) >> 3) // Copy SIDL<7:6> to EID<20:18>
    result.Byte1 = POSTINC2                     // Copy EIDH<15:8> to EID<15:8>
    result.Byte0 = INDF2                        // Copy EIDH<7:0> to EID<7:0>
  End If  

End Function {

  • Name : CANSetMask *
  • Purpose : Given value is bit adjusted to appropriate buffer *
  • mask registers. *

} Public Sub CANSetMask(mask As Byte, value As LongWord, flags As Byte) Dim buf As Word

  Save(FSR1, FSR2)
  If mask = CAN_MASK_B1 Then // Select appropriate starting address based on given CAN_MASK value.
    buf = AddressOf(RXM0SIDH)
  Else
    buf = AddressOf(RXM1SIDH)
  End If
  CANIDToRegs(buf, value, flags)
  Restore

End Sub {

  • Name : CANSetFilter *
  • Purpose : Given value is bit adjusted to appropriate buffer *
  • filter registers. *

} Public Sub CANSetFilter(filter As Byte, value As LongWord, flags As Byte) Dim buf As Word

  Save(FSR1, FSR2)
  Select filter
    Case CAN_FILTER_B1_F1
      buf = AddressOf(RXF0SIDH)
    Case CAN_FILTER_B1_F2
      buf = AddressOf(RXF1SIDH)
    Case CAN_FILTER_B2_F1
      buf = AddressOf(RXF2SIDH)
    Case CAN_FILTER_B2_F2
      buf = AddressOf(RXF3SIDH)
    Case CAN_FILTER_B2_F3
      buf = AddressOf(RXF4SIDH)
Changed lines 420-476 from:
        INDF2 = INDF2 Or SData.Pin          // Set pin SData            
    End If    
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)        
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)  
    result = buf

End Function

Function Sensirion_Put_Byte(data As Byte) As Boolean Dim i As Byte

    result = false
    FSR2 = SPort.AddrPort
    i = 0
    While i < 8 
        If (data And 128) > 0 Then
            INDF2 = INDF2 Or SData.Pin      // Set pin SData
        Else
            INDF2 = INDF2 And SData.PinMask // clear pin SData     
        End If
        INDF2 = INDF2 Or SClock.Pin         // set pin SClock
        DelayUS(1)        
        INDF2 = INDF2 And SClock.PinMask    // clear pin SClock
        DelayUS(1)
        Inc(i)
        If i < 8 Then data = data << 1 End If        
    Wend
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 Or SData.Pin              // make input SData
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)        
    If (INDF2 And SData.Pin) = 0 Then
        result = true
    End If
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    FSR2 = SPort.AddrPort   
    INDF2 = INDF2 And SData.PinMask         // clear pin SData

End Function

Sub Sensirion_Reset() Dim i As Byte

    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin SData
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    i = 0
    While i < 9
        INDF2 = INDF2 Or SClock.Pin         // set pin SClock
        DelayUS(1)        
        INDF2 = INDF2 And SClock.PinMask    // clear pin SClock
        DelayUS(1)
        Inc(i)
    Wend    
    Sensirion_Start
to:
      buf = AddressOf(RXF5SIDH)
  End Select
  CANIDToRegs(buf, value, flags)
  Restore

End Sub {

  • Name : CANInitialize *
  • Purpose : Initialize CAN module, Filters, Mask *
  • Input : SJW - SJW value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 4) *
  • BRP - BRP value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 64) *
  • PHSEG1 - PHSEG1 value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • PHSEG2 - PHSEG2 value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • PROPSEG - PROPSEG value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • flags - Value of CAN_CONFIG_FLAGS *

} Public Sub CANInitialize(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, flags As Byte) Dim FilterConfig1 As Byte,

    FilterConfig2 As Byte
  Save(FSR1, FSR2)
  #if _device in (18F248, 18F258, 18F448, 18F458, 18F2480, 18F2580, 18F4480, 18F4580, 18F2682, 18F2685, 18F4682, 18F4685)
  TRISB.2 = 0 'TX CAN
  TRISB.3 = 1 'RX CAN
  #else
  TRISG.0 = 0 'TX CAN
  TRISG.2 = 1 'RX CAN
  #endif
  CIOCON = 0
  CANSetOperationMode(CAN_OP_MODE_CONFIG) // In order to setup necessary config parameters of CAN module, it must be in Config mode. 
  #if _device in (18F248, 18F258, 18F448, 18F458)
  Nop
  #else
  ECANCON = ECANCON And %00111111
  #endif    
  CANSetBaudRate(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, flags) // Now set the baud rate.
  RXB0CON = flags And CAN_CONFIG_MSG_BITS
  If (flags And CAN_CONFIG_DBL_BUFFER_BIT) = CAN_CONFIG_DBL_BUFFER_ON Then
    RXB0CON_RX0DBEN = 1
  End If
  RXB1CON = RXB0CON  
  CANSetMask(CAN_MASK_B1, 0, CAN_CONFIG_XTD_MSG)  // Set default filter and mask registers for all receive buffers.
  CANSetMask(CAN_MASK_B2, 0, CAN_CONFIG_XTD_MSG)
  Select ((flags And CAN_CONFIG_MSG_BITS) Or (Not(CAN_CONFIG_MSG_BITS)))
    Case CAN_CONFIG_VALID_XTD_MSG
      FilterConfig1 = CAN_CONFIG_XTD_MSG
      FilterConfig2 = CAN_CONFIG_XTD_MSG
    Case CAN_CONFIG_VALID_STD_MSG
      FilterConfig1 = CAN_CONFIG_STD_MSG
      FilterConfig2 = CAN_CONFIG_STD_MSG
    Else
      FilterConfig1 = CAN_CONFIG_STD_MSG
      FilterConfig2 = CAN_CONFIG_XTD_MSG
  End Select 
  CANSetFilter(CAN_FILTER_B1_F1, 0, FilterConfig1) // By default, there will be no mask on any receive filters, hence filter value of '0' will be ignored.
  CANSetFilter(CAN_FILTER_B1_F2, 0, FilterConfig1)
  CANSetFilter(CAN_FILTER_B2_F1, 0, FilterConfig2)
  CANSetFilter(CAN_FILTER_B2_F2, 0, FilterConfig2)
  CANSetFilter(CAN_FILTER_B2_F3, 0, FilterConfig2)
  CANSetFilter(CAN_FILTER_B2_F4, 0, FilterConfig2)  
  CANSetOperationMode(CAN_OP_MODE_NORMAL)         // Restore to Normal mode.
  Restore
Changed lines 488-491 from:

Function Sensirion_Soft_Reset() As Boolean

    Sensirion_Reset
    result = Sensirion_Put_Byte(CMD_RESET)
to:

{

  • Name : CANSendMessage *
  • Purpose : If at least one empty transmit buffer is found, *
  • given message is queued to be transmitted. *
  • If none found FALSE value is returned. *

} Public Function CANSendMessage(id As LongWord, ByRef Data() As Byte, DataLen, flags As Byte) As Boolean Dim i As Byte

  Save(FSR1, FSR2)
  FSR2 = AddressOf(TXB0CON)           // For compatibility with SwordfishSE
  If INDF2.bits(TXREQ) = 0 Then       // Find the first empty transmitter.

// If TXB0CON_TXREQ = 0 Then

    CANCON = CANCON And %11110001     // TxBuffer0 is empty.  Set WIN bits to point to TXB0
    CANCON = CANCON Or %00001000
  Else
    FSR2 = AddressOf(TXB1CON)         // For compatibility with SwordfishSE
    If INDF2.bits(TXREQ) = 0 Then  

// If TXB1CON_TXREQ = 0 Then

      CANCON = CANCON And %11110001   // TxBuffer1 is empty. Set WIN bits to point to TXB1
      CANCON = CANCON Or %00000110
    Else
      FSR2 = AddressOf(TXB2CON)       // For compatibility with SwordfishSE
      If INDF2.bits(TXREQ) = 0 Then

// If TXB2CON_TXREQ = 0 Then

        CANCON = CANCON And %11110001 // TxBuffer2 is empty. Set WIN bits to point to TXB2
        CANCON = CANCON Or %00000100
      Else
        result = false                // None of the transmit buffers were empty.
        Exit
      End If
    End If
  End If      
  RXB0CON = flags And CAN_TX_PRIORITY_BITS  // Set transmit priority.
  If (flags And CAN_TX_FRAME_BIT) = 0 Then  // Populate Extended identifier information only if it is desired.
    CANIDToRegs(AddressOf(RXB0SIDH), id, CAN_CONFIG_XTD_MSG)
  Else
    CANIDToRegs(AddressOf(RXB0SIDH), id, CAN_CONFIG_STD_MSG)
  End If
  RXB0DLC = DataLen
  If (flags And CAN_TX_RTR_BIT) = 0 Then
    RXB0DLC = RXB0DLC Or %01000000
  End If
  i = 0
  FSR2 = AddressOf(RXB0D0)            // Populate data values.
  FSR1 = AddressOf(Data)
  While i < DataLen 
    POSTINC2 = POSTINC1
    Inc(i)
  Wend
  ASM
    bsf RXB0CON, 3
  End ASM
  CANCON = CANCON And %11110001
  result = true
  Restore
Changed lines 546-551 from:

Function Sensirion_Read_Status(ByRef sensirion_status, sensirion_cksum As Byte) As Boolean

    Sensirion_Reset
    result = Sensirion_Put_Byte(CMD_STATUS_REG_R)
    sensirion_status = Sensirion_Get_Byte(ACK)
    sensirion_cksum = Sensirion_Get_Byte(NoACK)
to:

{

  • Name : CANReceiveMessage *
  • Purpose : If at least one full receive buffer is found, *
  • it is extrated and returned. *
  • If none found FALSE value is returned. *

} Public Function CANReceiveMessage(ByRef id As LongWord, ByRef Data(), DataLen, flags As Byte) As Boolean Dim i, buf As Byte,

    lbIsItBuffer0 As Boolean  
  Save(FSR1, FSR2)
  flags = 0                         // Start with no error or flags set.
  If RXB0CON_RXFUL = 1 Then         // Find which buffer is ready.    
    CANCON = CANCON And %11110001   // RXBuffer0 is full.
    lbIsItBuffer0 = true
    PIR3_RXB0IF = 0                 // Clear the received flag.    
    If COMSTAT_RX0OVFL = 1 Then     // Record and forget any previous overflow
      flags = flags Or CAN_RX_OVERFLOW
      COMSTAT_RX0OVFL = 0
    End If
    If RXB0CON_RX0DBEN = 1 Then
      flags = (flags Or RXB0CON) And CAN_RX_FILTER_BITS
      flags = flags And $01
    End If
  Else
    FSR2 = AddressOf(RXB1CON)       // For compatibility with SwordfishSE
    If INDF2.bits(RXFUL) = 1 Then

// If RXB1CON_RXFUL = 1 Then

      CANCON = CANCON And %11110001 // RXBuffer1 is full
      CANCON = CANCON Or %00001010
      lbIsItBuffer0 = false      
      PIR3_RXB1IF = 0               // Clear the received flag.
      If COMSTAT_RX1OVFL = 1 Then   // Record and forget any previous overflow
        flags = flags Or CAN_RX_OVERFLOW
        COMSTAT_RX1OVFL = 0
      End If
      FSR2 = AddressOf(RXB1CON)      // For compatibility with SwordfishSE
      flags = (flags Or INDF2) And CAN_RX_FILTER_BITS

// flags = (flags Or RXB1CON) And CAN_RX_FILTER_BITS

      If flags < $02 Then
        flags = flags Or CAN_RX_DBL_BUFFERED
      End If
    Else
      result = false
      Exit
    End If
  End If 
  DataLen = RXB0DLC And %00001111   // Retrieve message length.  
  If RXB0DLC_RTR = 1 Then           // Determine whether this was RTR or not.
    flags = flags Or CAN_RX_RTR_FRAME
  End If 
  If RXB0SIDL_EXID = 1 Then         // Retrieve EIDX bytes only if this is extended message
    flags = flags Or CAN_RX_XTD_FRAME
    id = RegsToCANID(AddressOf(RXB0SIDH), CAN_CONFIG_XTD_MSG)
  Else
    id = RegsToCANID(AddressOf(RXB0SIDH), CAN_CONFIG_STD_MSG)
  End If  
  i = 0
  buf = DataLen                     // Get message data itself
  FSR1 = AddressOf(RXB0D0)
  FSR2 = AddressOf(Data)
  While i < buf 
    POSTINC2 = POSTINC1
    Inc(i)
  Wend  
  CANCON = CANCON And %11110001     // Restore default RXB0 mapping.  
  If PIR3_IRXIF = 1 Then            // Record and Clear any previous invalid message bit flag.
    flags = flags Or CAN_RX_INVALID_MSG
    PIR3_IRXIF = 0
  End If
  If lbIsItBuffer0 = true Then 
    RXB0CON_RXFUL = 0
  Else
    FSR2 = AddressOf(RXB1CON)       // For compatibility with SwordfishSE
    INDF2.bits(RXFUL) = 0

// RXB1CON_RXFUL = 0

  End If
  result = true
  Restore
Deleted lines 626-797:

Function Sensirion_Write_Status(data As Byte) As Boolean Dim result1 As Boolean

    Sensirion_Reset
    result1 = Sensirion_Put_Byte(CMD_STATUS_REG_W)
    result = result1 And Sensirion_Put_Byte(data)

End Function

Function Sensirion_Get(data As Byte, ByRef result_h,result_l,sensirion_cksum As Byte) As Boolean Dim i As Word

    result = false
    Sensirion_Reset
    Select data 
        Case CMD_TEMP result = Sensirion_Put_Byte(CMD_TEMP)
        Case CMD_HUMIDITY result = Sensirion_Put_Byte(CMD_HUMIDITY)
    Else Exit
    End Select
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 Or SData.Pin              // make input SData
    FSR2 = SPort.AddrPort
    i = 0
    Repeat
        ClrWDT        
        If (INDF2 And SData.Pin) = 0 Then
            Break
        End If
        Inc(i)
        DelayMS(1)        
    Until i > 500
    If i > 500 Then
        result = false
        Exit
    End If    
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    FSR2 = SPort.AddrPort   
    INDF2 = INDF2 And SData.PinMask         // clear pin SData
    result_h = Sensirion_Get_Byte(ACK)
    result_l = Sensirion_Get_Byte(ACK)
    sensirion_cksum = Sensirion_Get_Byte(NoACK)

End Function

Public Function Sensirion_Get_Temp_Hum(ByRef temp, hum As Float) As Boolean Const T1 As Float = 0.01,

      T2 As Float = 0.00008,
      C1 As Float = -4.0,
      C2 As Float = 0.0405,
      C3 As Float = -0.0000028

Dim rh_lin, rh_true, tx As Float Dim result1 As Boolean Dim buf As Word

    result1 = Sensirion_Get(CMD_TEMP, data_h, data_l, data_cksum)
    buf.Byte0 = data_l
    buf.Byte1 = data_h    
    tx = (buf * 0.01) - 40.0
    result = result1 And Sensirion_Get(CMD_HUMIDITY, data_h, data_l, data_cksum)
    If result = false Then
        temp = 0
        hum = 0
        Exit
    End If
    buf.Byte0 = data_l
    buf.Byte1 = data_h      
    rh_lin = (C3 * buf * buf) + (C2 * buf) + C1
    rh_true = ((tx - 25.0) * (T1 + T2 * buf)) + rh_lin
    If rh_true > 99.9 Then rh_true = 99.9 End If
    If rh_true < 0.0 Then rh_true = 0.0 End If
    temp = tx + 0.00001
    hum = rh_true

End Function

Public Function Sensirion_Get_Temp_Hum_Dec(ByRef temp_d, hum_d As Integer) As Boolean Const C1d As LongInt = -40000,

      C2d As LongInt = 405,
      C3d As LongInt = -28

Dim rh_lin, rh_true As LongInt Dim result1 As Boolean Dim buf As Word

  result1 = Sensirion_Get(CMD_TEMP, data_h, data_l, data_cksum)
  temp_d.Byte0 = data_l
  temp_d.Byte1 = data_h 
  temp_d = temp_d - 4000
  result = result1 And Sensirion_Get(CMD_HUMIDITY, data_h, data_l, data_cksum)
  If result = false Then
    temp_d = 0
    hum_d = 0
    Exit
  End If
  buf.Byte0 = data_l
  buf.Byte1 = data_h 
  rh_lin = (((C3d * buf * buf) / 1000) + (C2d * buf) + C1d) / 100
  rh_true = (((temp_d - 2500) * buf) / 12500) + rh_lin
  If rh_true > 9999 Then rh_true = 9999 End If
  If rh_true < 0 Then rh_true = 0 End If
  hum_d = Integer(rh_true)

End Function

Public Function Sensirion_Get_Dew_Point(ByRef temp, hum As Float) As Float Dim k As Float

    k = ((log10(hum) - 2.0) / 0.4343) + ((17.62 * temp) / (243.12 + temp))
    result = (243.12 * k) / (17.62 - k)

End Function =] : 2 Home Made, MCU PIC18F458, MCP2515 CAN transceiver.

Available functions

Sub Sensirion_Init(ByRef Port.(Data_Pin) As Bit, ByRef Port.(Clock_Pin) As Bit)
Sub Sensirion_Init_(ByRef Port As Byte, Data_Pin, Clock_Pin As Byte)
Function Sensirion_Get_Temp_Hum(ByRef temperature, humidity As Float) As Boolean
Function Sensirion_Get_Temp_Hum_Dec(ByRef temp_d, hum_d As Integer) As Boolean // result will be multiplied by 100
Function Sensirion_Get_Dew_Point(ByRef temperature, humidity As Float) As Float

For initialization you can choice between Sensirion_Init or Sensirion_Init_

You can download source code from : http://www.microelemente.ro/Swordfish/Sensirion.zip

Example Code

Device = 18F8520
Clock = 40
Config OSC = HSPLL

// some LCD options...
#option LCD_DATA = PORTH.4
#option LCD_RS = PORTH.2
#option LCD_EN = PORTH.3

// import LCD library...
Include "LCD.bas" 
Include "Sensirion"
Include "convert.bas"

Dim NoError As Boolean
Dim temperature, humidity, dew_point As Float
Dim TempA, TempB As Byte
Dim buf As Integer

ADCON0 = 0
CMCON  = $07                    // turn off comparators
ADCON1 = $0F                    // turn off analog inputs
MEMCON.7 = 1                    // disable external memory bus

Cls
//Sensirion.Sensirion_Init(PORTC.1, PORTC.2)  
                                          // Sensirion.Sensirion_Init(Port.(Data Pin), Port.(Clock pin))
                                          // Data an Clock Pin must be at the same Port
                                          // This is a wrong configuration : 
                                          // Sensirion.Sensirion_Init(PORTB.1, PORTD.2) 
Sensirion.Sensirion_Init_(PORTC, 0, 1)    // Sensirion.Sensirion_Init(Port, Data Pin, Clock Pin)
While true
    NoError = Sensirion.Sensirion_Get_Temp_Hum(temperature, humidity)
    If NoError Then
        buf = temperature * 100
        TempA = buf / 100
        TempB = buf Mod 100
        LCD.WriteAt(1,1, " TS = ",DecToStr(TempA,2),".",DecToStr(TempB,2)," ", 223, "C  ")
        buf = humidity * 100
        TempA = buf / 100
        TempB = buf Mod 100
        LCD.WriteAt(2,1, " Rh = ",DecToStr(TempA,2),".",DecToStr(TempB,2)," "," %  ")
        dew_point = Sensirion.Sensirion_Get_Dew_Point(temperature, humidity)       
    Else 
        LCD.WriteAt(1,1, " Error detected ")
        LCD.WriteAt(2,1, " Error detected ")        
    End If
    DelayMS(2000)
Wend

Module Code

=code [=

Changed lines 628-639 from:
  • Name : Sensirion.BAS *
  • Author : Medrea Florin Andrei *
  • Notice : Copyright (c) 2007 -YO2LIO- *
  • : All Rights Reserved *
  • Date : 9/26/2007 *
  • *
  • Copyright Notice *
  • *
  • This library For the SHT temperature And humidity sensors is based on the *
  • application datasheet Sample Code humidity sensor SHTxx from Sensirion. *
to:
  • Name : String2ID *
  • Purpose : Transform 3 Char String into LongWord id *
Changed lines 633-909 from:

Module Sensirion

Include "math" Include "system"

Const NoACK As Byte = 1,

      ACK As Byte = 0,
      CMD_STATUS_REG_W As Byte = $06,
      CMD_STATUS_REG_R As Byte = $07,
      CMD_TEMP As Byte = $03,
      CMD_HUMIDITY As Byte = $05,
      CMD_RESET As Byte = $1E

Structure TPin

   Pin As Byte
   PinMask As Byte

End Structure

Structure TPort

   AddrPort As Word
   AddrTRIS As Word

End Structure

Dim SData,SClock As TPin Dim SPort As TPort Dim data_h,data_l,data_cksum As Byte

Public Sub Sensirion_Init(ByRef pData As Bit, ByRef pClock As Bit)

    ClrWDT
    DelayMS(100)
    ClrWDT
    SPort.AddrPort = AddressOf(pData)       // get pin address
    SPort.AddrTRIS = SPort.AddrPort + 18    // get pin TRIS address
    SData.Pin = BitOf(pData)                // get pin number
    SData.PinMask = Not SData.Pin           // create pin number mask
    SClock.Pin = BitOf(pClock)              // get pin number
    SClock.PinMask = Not SClock.Pin         // create pin number mask  
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin
    INDF2 = INDF2 And SClock.PinMask        // clear pin    
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    INDF2 = INDF2 And SClock.PinMask        // make output SClock 

End Sub

Public Sub Sensirion_Init_(ByRef pPort As Byte, pData, pClock As Byte)

    ClrWDT
    DelayMS(100)
    ClrWDT
    SPort.AddrPort = AddressOf(pPort)       // get port address
    SPort.AddrTRIS = SPort.AddrPort + 18    // get port TRIS address
    SData.Pin = 1 << pData                  // get pin number
    SData.PinMask = Not SData.Pin           // create pin number mask
    SClock.Pin = 1 << pClock                // get pin number
    SClock.PinMask = Not SClock.Pin         // create pin number mask  
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin
    INDF2 = INDF2 And SClock.PinMask        // clear pin    
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    INDF2 = INDF2 And SClock.PinMask        // make output SClock 

End Sub

Sub Sensirion_Start()

    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin SData
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)
    INDF2 = INDF2 And SData.PinMask         // clear pin SData
    DelayUS(1)
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)    
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)    
    INDF2 = INDF2 Or SData.Pin              // set pin SData
    DelayUS(1)
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock    

End Sub

Function Sensirion_Get_Byte(ack_ As Byte) As Byte Dim i,buf As Byte

    buf = 0
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 Or SData.Pin              // make input SData
    FSR2 = SPort.AddrPort
    i = 0
    While i < 8
        INDF2 = INDF2 Or SClock.Pin         // set pin SClock
        DelayUS(1)        
        If (INDF2 And SData.Pin) > 0 Then
            buf = buf Or 1
        End If
        INDF2 = INDF2 And SClock.PinMask    // clear pin SClock
        DelayUS(1)
        Inc(i)
        If i < 8 Then buf = buf << 1 End If
    Wend
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    FSR2 = SPort.AddrPort
    If ack_ = 0 Then 
        INDF2 = INDF2 And SData.PinMask     // clear pin SData
    Else
        INDF2 = INDF2 Or SData.Pin          // Set pin SData            
    End If    
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)        
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)  
    result = buf

End Function

Function Sensirion_Put_Byte(data As Byte) As Boolean Dim i As Byte

    result = false
    FSR2 = SPort.AddrPort
    i = 0
    While i < 8 
        If (data And 128) > 0 Then
            INDF2 = INDF2 Or SData.Pin      // Set pin SData
        Else
            INDF2 = INDF2 And SData.PinMask // clear pin SData     
        End If
        INDF2 = INDF2 Or SClock.Pin         // set pin SClock
        DelayUS(1)        
        INDF2 = INDF2 And SClock.PinMask    // clear pin SClock
        DelayUS(1)
        Inc(i)
        If i < 8 Then data = data << 1 End If        
    Wend
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 Or SData.Pin              // make input SData
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)        
    If (INDF2 And SData.Pin) = 0 Then
        result = true
    End If
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    FSR2 = SPort.AddrPort   
    INDF2 = INDF2 And SData.PinMask         // clear pin SData

End Function

Sub Sensirion_Reset() Dim i As Byte

    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin SData
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    i = 0
    While i < 9
        INDF2 = INDF2 Or SClock.Pin         // set pin SClock
        DelayUS(1)        
        INDF2 = INDF2 And SClock.PinMask    // clear pin SClock
        DelayUS(1)
        Inc(i)
    Wend    
    Sensirion_Start

End Sub

Function Sensirion_Soft_Reset() As Boolean

    Sensirion_Reset
    result = Sensirion_Put_Byte(CMD_RESET)

End Function

Function Sensirion_Read_Status(ByRef sensirion_status, sensirion_cksum As Byte) As Boolean

    Sensirion_Reset
    result = Sensirion_Put_Byte(CMD_STATUS_REG_R)
    sensirion_status = Sensirion_Get_Byte(ACK)
    sensirion_cksum = Sensirion_Get_Byte(NoACK)

End Function

Function Sensirion_Write_Status(data As Byte) As Boolean Dim result1 As Boolean

    Sensirion_Reset
    result1 = Sensirion_Put_Byte(CMD_STATUS_REG_W)
    result = result1 And Sensirion_Put_Byte(data)

End Function

Function Sensirion_Get(data As Byte, ByRef result_h,result_l,sensirion_cksum As Byte) As Boolean Dim i As Word

    result = false
    Sensirion_Reset
    Select data 
        Case CMD_TEMP result = Sensirion_Put_Byte(CMD_TEMP)
        Case CMD_HUMIDITY result = Sensirion_Put_Byte(CMD_HUMIDITY)
    Else Exit
    End Select
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 Or SData.Pin              // make input SData
    FSR2 = SPort.AddrPort
    i = 0
    Repeat
        ClrWDT        
        If (INDF2 And SData.Pin) = 0 Then
            Break
        End If
        Inc(i)
        DelayMS(1)        
    Until i > 500
    If i > 500 Then
        result = false
        Exit
    End If    
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    FSR2 = SPort.AddrPort   
    INDF2 = INDF2 And SData.PinMask         // clear pin SData
    result_h = Sensirion_Get_Byte(ACK)
    result_l = Sensirion_Get_Byte(ACK)
    sensirion_cksum = Sensirion_Get_Byte(NoACK)

End Function

Public Function Sensirion_Get_Temp_Hum(ByRef temp, hum As Float) As Boolean Const T1 As Float = 0.01,

      T2 As Float = 0.00008,
      C1 As Float = -4.0,
      C2 As Float = 0.0405,
      C3 As Float = -0.0000028

Dim rh_lin, rh_true, tx As Float Dim result1 As Boolean Dim buf As Word

    result1 = Sensirion_Get(CMD_TEMP, data_h, data_l, data_cksum)
    buf.Byte0 = data_l
    buf.Byte1 = data_h    
    tx = (buf * 0.01) - 40.0
    result = result1 And Sensirion_Get(CMD_HUMIDITY, data_h, data_l, data_cksum)
    If result = false Then
        temp = 0
        hum = 0
        Exit
    End If
    buf.Byte0 = data_l
    buf.Byte1 = data_h      
    rh_lin = (C3 * buf * buf) + (C2 * buf) + C1
    rh_true = ((tx - 25.0) * (T1 + T2 * buf)) + rh_lin
    If rh_true > 99.9 Then rh_true = 99.9 End If
    If rh_true < 0.0 Then rh_true = 0.0 End If
    temp = tx + 0.00001
    hum = rh_true

End Function

Public Function Sensirion_Get_Temp_Hum_Dec(ByRef temp_d, hum_d As Integer) As Boolean Const C1d As LongInt = -40000,

      C2d As LongInt = 405,
      C3d As LongInt = -28

Dim rh_lin, rh_true As LongInt Dim result1 As Boolean Dim buf As Word

  result1 = Sensirion_Get(CMD_TEMP, data_h, data_l, data_cksum)
  temp_d.Byte0 = data_l
  temp_d.Byte1 = data_h 
  temp_d = temp_d - 4000
  result = result1 And Sensirion_Get(CMD_HUMIDITY, data_h, data_l, data_cksum)
  If result = false Then
    temp_d = 0
    hum_d = 0
    Exit
  End If
  buf.Byte0 = data_l
  buf.Byte1 = data_h 
  rh_lin = (((C3d * buf * buf) / 1000) + (C2d * buf) + C1d) / 100
  rh_true = (((temp_d - 2500) * buf) / 12500) + rh_lin
  If rh_true > 9999 Then rh_true = 9999 End If
  If rh_true < 0 Then rh_true = 0 End If
  hum_d = Integer(rh_true)

End Function

Public Function Sensirion_Get_Dew_Point(ByRef temp, hum As Float) As Float Dim k As Float

    k = ((log10(hum) - 2.0) / 0.4343) + ((17.62 * temp) / (243.12 + temp))
    result = (243.12 * k) / (17.62 - k)

End Function

to:

Public Function String2ID(str_in As String) As LongWord

  Save(FSR2)
  FSR2 = AddressOf(str_in)
  result.Byte3 = 0
  result.Byte2 = POSTINC2
  result.Byte1 = POSTINC2
  result.Byte0 = INDF2
  Restore

End Function

Changed lines 8-12 from:

Sub Sensirion_Init(ByRef Port.(Data_Pin) As Bit, ByRef Port.(Clock_Pin) As Bit) Sub Sensirion_Init_(ByRef Port As Byte, Data_Pin, Clock_Pin As Byte) Function Sensirion_Get_Temp_Hum(ByRef temperature, humidity As Float) As Boolean Function Sensirion_Get_Temp_Hum_Dec(ByRef temp_d, hum_d As Integer) As Boolean // result will be multiplied by 100 Function Sensirion_Get_Dew_Point(ByRef temperature, humidity As Float) As Float

to:

{

  • Name : CANInitialize *
  • Purpose : Initialize CAN module, Filters, Mask *
  • Input : SJW - SJW value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 4) *
  • BRP - BRP value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 64) *
  • PHSEG1 - PHSEG1 value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • PHSEG2 - PHSEG2 value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • PROPSEG - PROPSEG value as defined in 18CXX8 datasheet *
  • (Must be between 1 thru 8) *
  • flags - Value of CAN_CONFIG_FLAGS *

} Public Sub CANInitialize(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, flags As Byte) {

  • Name : CANSetFilter *
  • Purpose : Given value is bit adjusted to appropriate buffer *
  • filter registers. *

} Public Sub CANSetFilter(filter As Byte, value As LongWord, flags As Byte) {

  • Name : CANSetMask *
  • Purpose : Given value is bit adjusted to appropriate buffer *
  • mask registers. *

} Public Sub CANSetMask(mask As Byte, value As LongWord, flags As Byte) {

  • Name : CANSetOperationMode *
  • Purpose : Given mode byte is copied to CANCON *
  • and made sure that requested mode is set. *

} Public Sub CANSetOperationMode(mode As Byte)

Added lines 1-725:

CAN BUS module available for Swordfish.

Test equipment : 2 Home Made boards, MCU PIC18F458, MCP2551 CAN transceiver.

Available functions

Sub Sensirion_Init(ByRef Port.(Data_Pin) As Bit, ByRef Port.(Clock_Pin) As Bit)
Sub Sensirion_Init_(ByRef Port As Byte, Data_Pin, Clock_Pin As Byte)
Function Sensirion_Get_Temp_Hum(ByRef temperature, humidity As Float) As Boolean
Function Sensirion_Get_Temp_Hum_Dec(ByRef temp_d, hum_d As Integer) As Boolean // result will be multiplied by 100
Function Sensirion_Get_Dew_Point(ByRef temperature, humidity As Float) As Float

For initialization you can choice between Sensirion_Init or Sensirion_Init_

You can download source code from : http://www.microelemente.ro/Swordfish/Sensirion.zip

Example Code

Device = 18F8520
Clock = 40
Config OSC = HSPLL

// some LCD options...
#option LCD_DATA = PORTH.4
#option LCD_RS = PORTH.2
#option LCD_EN = PORTH.3

// import LCD library...
Include "LCD.bas" 
Include "Sensirion"
Include "convert.bas"

Dim NoError As Boolean
Dim temperature, humidity, dew_point As Float
Dim TempA, TempB As Byte
Dim buf As Integer

ADCON0 = 0
CMCON  = $07                    // turn off comparators
ADCON1 = $0F                    // turn off analog inputs
MEMCON.7 = 1                    // disable external memory bus

Cls
//Sensirion.Sensirion_Init(PORTC.1, PORTC.2)  
                                          // Sensirion.Sensirion_Init(Port.(Data Pin), Port.(Clock pin))
                                          // Data an Clock Pin must be at the same Port
                                          // This is a wrong configuration : 
                                          // Sensirion.Sensirion_Init(PORTB.1, PORTD.2) 
Sensirion.Sensirion_Init_(PORTC, 0, 1)    // Sensirion.Sensirion_Init(Port, Data Pin, Clock Pin)
While true
    NoError = Sensirion.Sensirion_Get_Temp_Hum(temperature, humidity)
    If NoError Then
        buf = temperature * 100
        TempA = buf / 100
        TempB = buf Mod 100
        LCD.WriteAt(1,1, " TS = ",DecToStr(TempA,2),".",DecToStr(TempB,2)," ", 223, "C  ")
        buf = humidity * 100
        TempA = buf / 100
        TempB = buf Mod 100
        LCD.WriteAt(2,1, " Rh = ",DecToStr(TempA,2),".",DecToStr(TempB,2)," "," %  ")
        dew_point = Sensirion.Sensirion_Get_Dew_Point(temperature, humidity)       
    Else 
        LCD.WriteAt(1,1, " Error detected ")
        LCD.WriteAt(2,1, " Error detected ")        
    End If
    DelayMS(2000)
Wend

Module Code

{
******************************************************************************
*  Name    : Sensirion.BAS                                                   *
*  Author  : Medrea Florin Andrei                                            *
*  Notice  : Copyright (c) 2007 -YO2LIO-                                     *
*          : All Rights Reserved                                             *
*  Date    : 9/26/2007                                                       *
*                                                                            *
*  Copyright Notice                                                          *
*                                                                            *
*  This library For the SHT temperature And humidity sensors is based on the *
*  application datasheet Sample Code humidity sensor SHTxx from Sensirion.   *
******************************************************************************
}
Module Sensirion

Include "math"
Include "system"

Const NoACK As Byte = 1,
      ACK As Byte = 0,
      CMD_STATUS_REG_W As Byte = $06,
      CMD_STATUS_REG_R As Byte = $07,
      CMD_TEMP As Byte = $03,
      CMD_HUMIDITY As Byte = $05,
      CMD_RESET As Byte = $1E

Structure TPin
   Pin As Byte
   PinMask As Byte
End Structure

Structure TPort
   AddrPort As Word
   AddrTRIS As Word
End Structure

Dim SData,SClock As TPin
Dim SPort As TPort
Dim data_h,data_l,data_cksum As Byte

Public Sub Sensirion_Init(ByRef pData As Bit, ByRef pClock As Bit)
    ClrWDT
    DelayMS(100)
    ClrWDT
    SPort.AddrPort = AddressOf(pData)       // get pin address
    SPort.AddrTRIS = SPort.AddrPort + 18    // get pin TRIS address
    SData.Pin = BitOf(pData)                // get pin number
    SData.PinMask = Not SData.Pin           // create pin number mask
    SClock.Pin = BitOf(pClock)              // get pin number
    SClock.PinMask = Not SClock.Pin         // create pin number mask  
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin
    INDF2 = INDF2 And SClock.PinMask        // clear pin    
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    INDF2 = INDF2 And SClock.PinMask        // make output SClock 
End Sub

Public Sub Sensirion_Init_(ByRef pPort As Byte, pData, pClock As Byte)
    ClrWDT
    DelayMS(100)
    ClrWDT
    SPort.AddrPort = AddressOf(pPort)       // get port address
    SPort.AddrTRIS = SPort.AddrPort + 18    // get port TRIS address
    SData.Pin = 1 << pData                  // get pin number
    SData.PinMask = Not SData.Pin           // create pin number mask
    SClock.Pin = 1 << pClock                // get pin number
    SClock.PinMask = Not SClock.Pin         // create pin number mask  
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin
    INDF2 = INDF2 And SClock.PinMask        // clear pin    
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    INDF2 = INDF2 And SClock.PinMask        // make output SClock 
End Sub

Sub Sensirion_Start()
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin SData
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)
    INDF2 = INDF2 And SData.PinMask         // clear pin SData
    DelayUS(1)
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)    
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)    
    INDF2 = INDF2 Or SData.Pin              // set pin SData
    DelayUS(1)
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock    
End Sub

Function Sensirion_Get_Byte(ack_ As Byte) As Byte
Dim i,buf As Byte
    buf = 0
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 Or SData.Pin              // make input SData
    FSR2 = SPort.AddrPort
    i = 0
    While i < 8
        INDF2 = INDF2 Or SClock.Pin         // set pin SClock
        DelayUS(1)        
        If (INDF2 And SData.Pin) > 0 Then
            buf = buf Or 1
        End If
        INDF2 = INDF2 And SClock.PinMask    // clear pin SClock
        DelayUS(1)
        Inc(i)
        If i < 8 Then buf = buf << 1 End If
    Wend
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    FSR2 = SPort.AddrPort
    If ack_ = 0 Then 
        INDF2 = INDF2 And SData.PinMask     // clear pin SData
    Else
        INDF2 = INDF2 Or SData.Pin          // Set pin SData            
    End If    
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)        
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)  
    result = buf
End Function

Function Sensirion_Put_Byte(data As Byte) As Boolean
Dim i As Byte
    result = false
    FSR2 = SPort.AddrPort
    i = 0
    While i < 8 
        If (data And 128) > 0 Then
            INDF2 = INDF2 Or SData.Pin      // Set pin SData
        Else
            INDF2 = INDF2 And SData.PinMask // clear pin SData     
        End If
        INDF2 = INDF2 Or SClock.Pin         // set pin SClock
        DelayUS(1)        
        INDF2 = INDF2 And SClock.PinMask    // clear pin SClock
        DelayUS(1)
        Inc(i)
        If i < 8 Then data = data << 1 End If        
    Wend
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 Or SData.Pin              // make input SData
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)        
    If (INDF2 And SData.Pin) = 0 Then
        result = true
    End If
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    FSR2 = SPort.AddrPort   
    INDF2 = INDF2 And SData.PinMask         // clear pin SData
End Function

Sub Sensirion_Reset()
Dim i As Byte
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin SData
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    i = 0
    While i < 9
        INDF2 = INDF2 Or SClock.Pin         // set pin SClock
        DelayUS(1)        
        INDF2 = INDF2 And SClock.PinMask    // clear pin SClock
        DelayUS(1)
        Inc(i)
    Wend    
    Sensirion_Start
End Sub

Function Sensirion_Soft_Reset() As Boolean
    Sensirion_Reset
    result = Sensirion_Put_Byte(CMD_RESET)
End Function

Function Sensirion_Read_Status(ByRef sensirion_status, sensirion_cksum As Byte) As Boolean
    Sensirion_Reset
    result = Sensirion_Put_Byte(CMD_STATUS_REG_R)
    sensirion_status = Sensirion_Get_Byte(ACK)
    sensirion_cksum = Sensirion_Get_Byte(NoACK)
End Function

Function Sensirion_Write_Status(data As Byte) As Boolean
Dim result1 As Boolean
    Sensirion_Reset
    result1 = Sensirion_Put_Byte(CMD_STATUS_REG_W)
    result = result1 And Sensirion_Put_Byte(data)
End Function

Function Sensirion_Get(data As Byte, ByRef result_h,result_l,sensirion_cksum As Byte) As Boolean
Dim i As Word
    result = false
    Sensirion_Reset
    Select data 
        Case CMD_TEMP result = Sensirion_Put_Byte(CMD_TEMP)
        Case CMD_HUMIDITY result = Sensirion_Put_Byte(CMD_HUMIDITY)
    Else Exit
    End Select
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 Or SData.Pin              // make input SData
    FSR2 = SPort.AddrPort
    i = 0
    Repeat
        ClrWDT        
        If (INDF2 And SData.Pin) = 0 Then
            Break
        End If
        Inc(i)
        DelayMS(1)        
    Until i > 500
    If i > 500 Then
        result = false
        Exit
    End If    
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    FSR2 = SPort.AddrPort   
    INDF2 = INDF2 And SData.PinMask         // clear pin SData
    result_h = Sensirion_Get_Byte(ACK)
    result_l = Sensirion_Get_Byte(ACK)
    sensirion_cksum = Sensirion_Get_Byte(NoACK)
End Function

Public Function Sensirion_Get_Temp_Hum(ByRef temp, hum As Float) As Boolean
Const T1 As Float = 0.01,
      T2 As Float = 0.00008,
      C1 As Float = -4.0,
      C2 As Float = 0.0405,
      C3 As Float = -0.0000028
Dim rh_lin, rh_true, tx As Float
Dim result1 As Boolean
Dim buf As Word
    result1 = Sensirion_Get(CMD_TEMP, data_h, data_l, data_cksum)
    buf.Byte0 = data_l
    buf.Byte1 = data_h    
    tx = (buf * 0.01) - 40.0
    result = result1 And Sensirion_Get(CMD_HUMIDITY, data_h, data_l, data_cksum)
    If result = false Then
        temp = 0
        hum = 0
        Exit
    End If
    buf.Byte0 = data_l
    buf.Byte1 = data_h      
    rh_lin = (C3 * buf * buf) + (C2 * buf) + C1
    rh_true = ((tx - 25.0) * (T1 + T2 * buf)) + rh_lin
    If rh_true > 99.9 Then rh_true = 99.9 End If
    If rh_true < 0.0 Then rh_true = 0.0 End If
    temp = tx + 0.00001
    hum = rh_true
End Function

Public Function Sensirion_Get_Temp_Hum_Dec(ByRef temp_d, hum_d As Integer) As Boolean
Const C1d As LongInt = -40000,
      C2d As LongInt = 405,
      C3d As LongInt = -28
Dim rh_lin, rh_true As LongInt
Dim result1 As Boolean
Dim buf As Word
  result1 = Sensirion_Get(CMD_TEMP, data_h, data_l, data_cksum)
  temp_d.Byte0 = data_l
  temp_d.Byte1 = data_h 
  temp_d = temp_d - 4000
  result = result1 And Sensirion_Get(CMD_HUMIDITY, data_h, data_l, data_cksum)
  If result = false Then
    temp_d = 0
    hum_d = 0
    Exit
  End If
  buf.Byte0 = data_l
  buf.Byte1 = data_h 
  rh_lin = (((C3d * buf * buf) / 1000) + (C2d * buf) + C1d) / 100
  rh_true = (((temp_d - 2500) * buf) / 12500) + rh_lin
  If rh_true > 9999 Then rh_true = 9999 End If
  If rh_true < 0 Then rh_true = 0 End If
  hum_d = Integer(rh_true)
End Function

Public Function Sensirion_Get_Dew_Point(ByRef temp, hum As Float) As Float
Dim k As Float
    k = ((log10(hum) - 2.0) / 0.4343) + ((17.62 * temp) / (243.12 + temp))
    result = (243.12 * k) / (17.62 - k)
End Function
: 2 Home Made, MCU PIC18F458, MCP2515 CAN transceiver.

Available functions

Sub Sensirion_Init(ByRef Port.(Data_Pin) As Bit, ByRef Port.(Clock_Pin) As Bit)
Sub Sensirion_Init_(ByRef Port As Byte, Data_Pin, Clock_Pin As Byte)
Function Sensirion_Get_Temp_Hum(ByRef temperature, humidity As Float) As Boolean
Function Sensirion_Get_Temp_Hum_Dec(ByRef temp_d, hum_d As Integer) As Boolean // result will be multiplied by 100
Function Sensirion_Get_Dew_Point(ByRef temperature, humidity As Float) As Float

For initialization you can choice between Sensirion_Init or Sensirion_Init_

You can download source code from : http://www.microelemente.ro/Swordfish/Sensirion.zip

Example Code

Device = 18F8520
Clock = 40
Config OSC = HSPLL

// some LCD options...
#option LCD_DATA = PORTH.4
#option LCD_RS = PORTH.2
#option LCD_EN = PORTH.3

// import LCD library...
Include "LCD.bas" 
Include "Sensirion"
Include "convert.bas"

Dim NoError As Boolean
Dim temperature, humidity, dew_point As Float
Dim TempA, TempB As Byte
Dim buf As Integer

ADCON0 = 0
CMCON  = $07                    // turn off comparators
ADCON1 = $0F                    // turn off analog inputs
MEMCON.7 = 1                    // disable external memory bus

Cls
//Sensirion.Sensirion_Init(PORTC.1, PORTC.2)  
                                          // Sensirion.Sensirion_Init(Port.(Data Pin), Port.(Clock pin))
                                          // Data an Clock Pin must be at the same Port
                                          // This is a wrong configuration : 
                                          // Sensirion.Sensirion_Init(PORTB.1, PORTD.2) 
Sensirion.Sensirion_Init_(PORTC, 0, 1)    // Sensirion.Sensirion_Init(Port, Data Pin, Clock Pin)
While true
    NoError = Sensirion.Sensirion_Get_Temp_Hum(temperature, humidity)
    If NoError Then
        buf = temperature * 100
        TempA = buf / 100
        TempB = buf Mod 100
        LCD.WriteAt(1,1, " TS = ",DecToStr(TempA,2),".",DecToStr(TempB,2)," ", 223, "C  ")
        buf = humidity * 100
        TempA = buf / 100
        TempB = buf Mod 100
        LCD.WriteAt(2,1, " Rh = ",DecToStr(TempA,2),".",DecToStr(TempB,2)," "," %  ")
        dew_point = Sensirion.Sensirion_Get_Dew_Point(temperature, humidity)       
    Else 
        LCD.WriteAt(1,1, " Error detected ")
        LCD.WriteAt(2,1, " Error detected ")        
    End If
    DelayMS(2000)
Wend

Module Code

{
******************************************************************************
*  Name    : Sensirion.BAS                                                   *
*  Author  : Medrea Florin Andrei                                            *
*  Notice  : Copyright (c) 2007 -YO2LIO-                                     *
*          : All Rights Reserved                                             *
*  Date    : 9/26/2007                                                       *
*                                                                            *
*  Copyright Notice                                                          *
*                                                                            *
*  This library For the SHT temperature And humidity sensors is based on the *
*  application datasheet Sample Code humidity sensor SHTxx from Sensirion.   *
******************************************************************************
}
Module Sensirion

Include "math"
Include "system"

Const NoACK As Byte = 1,
      ACK As Byte = 0,
      CMD_STATUS_REG_W As Byte = $06,
      CMD_STATUS_REG_R As Byte = $07,
      CMD_TEMP As Byte = $03,
      CMD_HUMIDITY As Byte = $05,
      CMD_RESET As Byte = $1E

Structure TPin
   Pin As Byte
   PinMask As Byte
End Structure

Structure TPort
   AddrPort As Word
   AddrTRIS As Word
End Structure

Dim SData,SClock As TPin
Dim SPort As TPort
Dim data_h,data_l,data_cksum As Byte

Public Sub Sensirion_Init(ByRef pData As Bit, ByRef pClock As Bit)
    ClrWDT
    DelayMS(100)
    ClrWDT
    SPort.AddrPort = AddressOf(pData)       // get pin address
    SPort.AddrTRIS = SPort.AddrPort + 18    // get pin TRIS address
    SData.Pin = BitOf(pData)                // get pin number
    SData.PinMask = Not SData.Pin           // create pin number mask
    SClock.Pin = BitOf(pClock)              // get pin number
    SClock.PinMask = Not SClock.Pin         // create pin number mask  
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin
    INDF2 = INDF2 And SClock.PinMask        // clear pin    
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    INDF2 = INDF2 And SClock.PinMask        // make output SClock 
End Sub

Public Sub Sensirion_Init_(ByRef pPort As Byte, pData, pClock As Byte)
    ClrWDT
    DelayMS(100)
    ClrWDT
    SPort.AddrPort = AddressOf(pPort)       // get port address
    SPort.AddrTRIS = SPort.AddrPort + 18    // get port TRIS address
    SData.Pin = 1 << pData                  // get pin number
    SData.PinMask = Not SData.Pin           // create pin number mask
    SClock.Pin = 1 << pClock                // get pin number
    SClock.PinMask = Not SClock.Pin         // create pin number mask  
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin
    INDF2 = INDF2 And SClock.PinMask        // clear pin    
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    INDF2 = INDF2 And SClock.PinMask        // make output SClock 
End Sub

Sub Sensirion_Start()
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin SData
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)
    INDF2 = INDF2 And SData.PinMask         // clear pin SData
    DelayUS(1)
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)    
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)    
    INDF2 = INDF2 Or SData.Pin              // set pin SData
    DelayUS(1)
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock    
End Sub

Function Sensirion_Get_Byte(ack_ As Byte) As Byte
Dim i,buf As Byte
    buf = 0
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 Or SData.Pin              // make input SData
    FSR2 = SPort.AddrPort
    i = 0
    While i < 8
        INDF2 = INDF2 Or SClock.Pin         // set pin SClock
        DelayUS(1)        
        If (INDF2 And SData.Pin) > 0 Then
            buf = buf Or 1
        End If
        INDF2 = INDF2 And SClock.PinMask    // clear pin SClock
        DelayUS(1)
        Inc(i)
        If i < 8 Then buf = buf << 1 End If
    Wend
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    FSR2 = SPort.AddrPort
    If ack_ = 0 Then 
        INDF2 = INDF2 And SData.PinMask     // clear pin SData
    Else
        INDF2 = INDF2 Or SData.Pin          // Set pin SData            
    End If    
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)        
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)  
    result = buf
End Function

Function Sensirion_Put_Byte(data As Byte) As Boolean
Dim i As Byte
    result = false
    FSR2 = SPort.AddrPort
    i = 0
    While i < 8 
        If (data And 128) > 0 Then
            INDF2 = INDF2 Or SData.Pin      // Set pin SData
        Else
            INDF2 = INDF2 And SData.PinMask // clear pin SData     
        End If
        INDF2 = INDF2 Or SClock.Pin         // set pin SClock
        DelayUS(1)        
        INDF2 = INDF2 And SClock.PinMask    // clear pin SClock
        DelayUS(1)
        Inc(i)
        If i < 8 Then data = data << 1 End If        
    Wend
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 Or SData.Pin              // make input SData
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(1)        
    If (INDF2 And SData.Pin) = 0 Then
        result = true
    End If
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(1)
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    FSR2 = SPort.AddrPort   
    INDF2 = INDF2 And SData.PinMask         // clear pin SData
End Function

Sub Sensirion_Reset()
Dim i As Byte
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin SData
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    i = 0
    While i < 9
        INDF2 = INDF2 Or SClock.Pin         // set pin SClock
        DelayUS(1)        
        INDF2 = INDF2 And SClock.PinMask    // clear pin SClock
        DelayUS(1)
        Inc(i)
    Wend    
    Sensirion_Start
End Sub

Function Sensirion_Soft_Reset() As Boolean
    Sensirion_Reset
    result = Sensirion_Put_Byte(CMD_RESET)
End Function

Function Sensirion_Read_Status(ByRef sensirion_status, sensirion_cksum As Byte) As Boolean
    Sensirion_Reset
    result = Sensirion_Put_Byte(CMD_STATUS_REG_R)
    sensirion_status = Sensirion_Get_Byte(ACK)
    sensirion_cksum = Sensirion_Get_Byte(NoACK)
End Function

Function Sensirion_Write_Status(data As Byte) As Boolean
Dim result1 As Boolean
    Sensirion_Reset
    result1 = Sensirion_Put_Byte(CMD_STATUS_REG_W)
    result = result1 And Sensirion_Put_Byte(data)
End Function

Function Sensirion_Get(data As Byte, ByRef result_h,result_l,sensirion_cksum As Byte) As Boolean
Dim i As Word
    result = false
    Sensirion_Reset
    Select data 
        Case CMD_TEMP result = Sensirion_Put_Byte(CMD_TEMP)
        Case CMD_HUMIDITY result = Sensirion_Put_Byte(CMD_HUMIDITY)
    Else Exit
    End Select
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 Or SData.Pin              // make input SData
    FSR2 = SPort.AddrPort
    i = 0
    Repeat
        ClrWDT        
        If (INDF2 And SData.Pin) = 0 Then
            Break
        End If
        Inc(i)
        DelayMS(1)        
    Until i > 500
    If i > 500 Then
        result = false
        Exit
    End If    
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    FSR2 = SPort.AddrPort   
    INDF2 = INDF2 And SData.PinMask         // clear pin SData
    result_h = Sensirion_Get_Byte(ACK)
    result_l = Sensirion_Get_Byte(ACK)
    sensirion_cksum = Sensirion_Get_Byte(NoACK)
End Function

Public Function Sensirion_Get_Temp_Hum(ByRef temp, hum As Float) As Boolean
Const T1 As Float = 0.01,
      T2 As Float = 0.00008,
      C1 As Float = -4.0,
      C2 As Float = 0.0405,
      C3 As Float = -0.0000028
Dim rh_lin, rh_true, tx As Float
Dim result1 As Boolean
Dim buf As Word
    result1 = Sensirion_Get(CMD_TEMP, data_h, data_l, data_cksum)
    buf.Byte0 = data_l
    buf.Byte1 = data_h    
    tx = (buf * 0.01) - 40.0
    result = result1 And Sensirion_Get(CMD_HUMIDITY, data_h, data_l, data_cksum)
    If result = false Then
        temp = 0
        hum = 0
        Exit
    End If
    buf.Byte0 = data_l
    buf.Byte1 = data_h      
    rh_lin = (C3 * buf * buf) + (C2 * buf) + C1
    rh_true = ((tx - 25.0) * (T1 + T2 * buf)) + rh_lin
    If rh_true > 99.9 Then rh_true = 99.9 End If
    If rh_true < 0.0 Then rh_true = 0.0 End If
    temp = tx + 0.00001
    hum = rh_true
End Function

Public Function Sensirion_Get_Temp_Hum_Dec(ByRef temp_d, hum_d As Integer) As Boolean
Const C1d As LongInt = -40000,
      C2d As LongInt = 405,
      C3d As LongInt = -28
Dim rh_lin, rh_true As LongInt
Dim result1 As Boolean
Dim buf As Word
  result1 = Sensirion_Get(CMD_TEMP, data_h, data_l, data_cksum)
  temp_d.Byte0 = data_l
  temp_d.Byte1 = data_h 
  temp_d = temp_d - 4000
  result = result1 And Sensirion_Get(CMD_HUMIDITY, data_h, data_l, data_cksum)
  If result = false Then
    temp_d = 0
    hum_d = 0
    Exit
  End If
  buf.Byte0 = data_l
  buf.Byte1 = data_h 
  rh_lin = (((C3d * buf * buf) / 1000) + (C2d * buf) + C1d) / 100
  rh_true = (((temp_d - 2500) * buf) / 12500) + rh_lin
  If rh_true > 9999 Then rh_true = 9999 End If
  If rh_true < 0 Then rh_true = 0 End If
  hum_d = Integer(rh_true)
End Function

Public Function Sensirion_Get_Dew_Point(ByRef temp, hum As Float) As Float
Dim k As Float
    k = ((log10(hum) - 2.0) / 0.4343) + ((17.62 * temp) / (243.12 + temp))
    result = (243.12 * k) / (17.62 - k)
End Function