CanBus
SwordfishUser.CanBus History
Hide minor edits - Show changes to markup
For initialization you can choice between Sensirion_Init or Sensirion_Init_
You can download source code from : http://www.microelemente.ro/Swordfish/Sensirion.zip
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.
Device = 18F8520
{
- 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
// 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 [= {
- 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
Include "CAN_lib" Include "usart"
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
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
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,
ADCON1 = %11000110 // AD off CMCON = $07 // Comparator off WDTCON = 1
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),
ClrWDT SetBaudrate(br115200)
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)
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
Wend // Wait till desired mode is set.
End Sub
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 [=
- 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 *
- 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 *
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
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)
- 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 *
- Name : CANSetOperationMode *
- Purpose : Given mode byte is copied to CANCON *
- and made sure that requested mode is set. *
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
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.
- 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> *
- 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 *
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
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
- Name : CANSetMask *
- Purpose : Given value is bit adjusted to appropriate buffer *
- mask registers. *
- 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 *
} 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) Else buf = AddressOf(RXF5SIDH) End Select CANIDToRegs(buf, value, flags) Restore
End Sub
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
- 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 *
- 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> *
Public Sub CANInitialize(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, flags As Byte) Dim FilterConfig1 As Byte,
FilterConfig2 As Byte
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
#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
If mask = CAN_MASK_B1 Then // Select appropriate starting address based on given CAN_MASK value. buf = AddressOf(RXM0SIDH) Else buf = AddressOf(RXM1SIDH)
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.
CANIDToRegs(buf, value, flags)
- 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. *
- Name : CANSetFilter *
- Purpose : Given value is bit adjusted to appropriate buffer *
- filter registers. *
} Public Function CANSendMessage(id As LongWord, ByRef Data() As Byte, DataLen, flags As Byte) As Boolean Dim i As Byte
} Public Sub CANSetFilter(filter As Byte, value As LongWord, flags As Byte) Dim buf As Word
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
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)
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
buf = AddressOf(RXF5SIDH) End Select CANIDToRegs(buf, value, flags)
End Function
End Sub
- Name : CANReceiveMessage *
- Purpose : If at least one full receive buffer is found, *
- it is extrated and returned. *
- If none found FALSE value is returned. *
- 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 Function CANReceiveMessage(ByRef id As LongWord, ByRef Data(), DataLen, flags As Byte) As Boolean Dim i, buf As Byte,
lbIsItBuffer0 As Boolean
} Public Sub CANInitialize(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, flags As Byte) Dim FilterConfig1 As Byte,
FilterConfig2 As Byte
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
#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
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)
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
id = RegsToCANID(AddressOf(RXB0SIDH), CAN_CONFIG_STD_MSG) End If
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
buf = DataLen // Get message data itself FSR1 = AddressOf(RXB0D0) FSR2 = AddressOf(Data) While i < buf
FSR2 = AddressOf(RXB0D0) // Populate data values. FSR1 = AddressOf(Data) While i < DataLen
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
Wend ASM bsf RXB0CON, 3 End ASM CANCON = CANCON And %11110001
- Name : String2ID *
- Purpose : Transform 3 Char String into LongWord id *
- 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
End Function {
- Name : String2ID *
- Purpose : Transform 3 Char String into LongWord id *
{
- 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
- 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. *
- 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 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
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
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)
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)
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
Wend // Wait till desired mode is set.
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
{
- 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
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
{
- 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
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
{
- 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)
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
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
Function Sensirion_Soft_Reset() As Boolean
Sensirion_Reset result = Sensirion_Put_Byte(CMD_RESET)
{
- 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
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)
{
- 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
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 [=
- 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. *
- Name : String2ID *
- Purpose : Transform 3 Char String into LongWord id *
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
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
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
{
- 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)
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