📄 can.c
字号:
/*********************************************************************
*
* This file contains CAN drivers for PIC18Fxx8 devices
*
*********************************************************************
* FileName: CAN.C
* Dependencies: CAN.H, PIC18.H or P18CXXX.H
* Processor: PIC18FXX8
* Compiler: MCC18 v2.20 or higher
* HITECH PICC-18 v8.20PL4 or higher
* Linker:
* Company: Microchip Technology, Inc.
*
* Software License Agreement
*
* The software supplied herewith by Microchip Technology Incorporated
* (the "Company") is intended and supplied to you, the Company抯
* customer, for use solely and exclusively with products manufactured
* by the Company.
*
* The software is owned by the Company and/or its supplier, and is
* protected under applicable copyright laws. All rights are reserved.
* Any use in violation of the foregoing restrictions may subject the
* user to criminal sanctions under applicable laws, as well as to
* civil liability for the breach of the terms and conditions of this
* license.
* THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
*
*
*
* Author Date Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Thomas Castmo 06/07/2003 Initial release
* Thomas Castmo 07/07/2003 Cleared up a bit and implemented
* the window function CANCON<3:1>
* for interrupts
* Thomas Castmo 16/07/2003 Added support for the Microchip
* MPLAB C18 compiler
*
********************************************************************/
#include "can.h"
#if defined(HI_TECH_C)
#if defined(_MPC_)
#define HITECH_C18
#else
#error "Unknown part is selected."
#endif
#else
#define MCHP_C18
#endif
#if defined(MCHP_C18) && defined(HITECH_C18)
#error "Invalid Compiler selection."
#endif
#if !defined(MCHP_C18) && !defined(HITECH_C18)
#error "Compiler not supported."
#endif
#if defined(HITECH_C18)
#include <pic18.h>
#elif defined(MCHP_C18)
#include <p18cxxx.h>
#define TRISB2 TRISBbits.TRISB2
#define TRISB3 TRISBbits.TRISB3
#define TXB0REQ TXB0CONbits.TXREQ
#define RXB0FUL RXB0CONbits.RXFUL
#define RXB0RTRRO RXB0CONbits.RXRTRRO
#define RXB0IF PIR3bits.RXB0IF
#define RXB1IF PIR3bits.RXB1IF
#define TXB0IF PIR3bits.TXB0IF
#define TXB1IF PIR3bits.TXB1IF
#define TXB2IF PIR3bits.TXB2IF
#define ERRIF PIR3bits.ERRIF
#define WAKIF PIR3bits.WAKIF
#define RXB0IE PIE3bits.RXB0IE
#define RXB1IE PIE3bits.RXB1IE
#define TXB0IE PIE3bits.TXB0IE
#define TXB1IE PIE3bits.TXB1IE
#define TXB2IE PIE3bits.TXB2IE
#define ERRIE PIE3bits.ERRIE
#define WAKIE PIE3bits.WAKIE
#endif
#define CONFIG_MODE 0x9F
#define LISTEN_MODE 0x7F
#define LOOPBACK_MODE 0x5F
#define DISABLE_MODE 0x3F
#define NORMAL_MODE 0x1F
#define MODE_MASK 0xE0
#define NoInterrupt 0x00
#define ErrorInterrupt 0x02
#define TXB2Interrupt 0x04
#define TXB1Interrupt 0x06
#define TXB0Interrupt 0x08
#define RXB1Interrupt 0x0A
#define RXB0Interrupt 0x0C
#define WakeUpInterrupt 0x0E
#ifdef CAN_ERROR_HANDLER_ENABLE
extern void CANErrorHandler(void);
#define CAN_INT_BITS 0x3F //CAN interrupts which should be enabled, simply what PIE3 is to be loaded with (Note all TXB IE will be set regardless of this value)
#else
#define CAN_INT_BITS 0x1F //CAN interrupts which should be enabled, simply what PIE3 is to be loaded with (Note all TXB IE will be set regardless of this value)
#endif
union RXBuffer { //Receive buffer structure
unsigned char Data[14]; //It has to be a bit messy/strict for
struct { //it to go trough the PICC18 compiler
union {
unsigned char Byte;
struct {
unsigned FILHIT0:1;
unsigned JTOFF:1;
unsigned RXB0DBEN:1;
unsigned RXRTRRO:1;
unsigned :1;
unsigned RXM0:1;
unsigned RXM1:1;
unsigned RXFUL:1;
} Bits;
} RXBCON;
union {
unsigned char Byte;
} RXBSIDH;
union {
unsigned char Byte;
struct {
unsigned EID16:1;
unsigned EID17:1;
unsigned :1;
unsigned EXID:1;
unsigned SRR:1;
unsigned SID0:1;
unsigned SID1:1;
unsigned SID2:1;
} Bits;
} RXBSIDL;
union {
unsigned char Byte;
} RXBEIDH;
union {
unsigned char Byte;
} RXBEIDL;
union {
unsigned char Byte;
struct {
unsigned DLC0:1;
unsigned DLC1:1;
unsigned DLC2:1;
unsigned DLC3:1;
unsigned RB0:1;
unsigned RB1:1;
unsigned RXRTR:1;
unsigned :1;
} Bits;
} RXBDLC;
union {
unsigned char Array[8];
struct {
unsigned char RXBD0;
unsigned char RXBD1;
unsigned char RXBD2;
unsigned char RXBD3;
unsigned char RXBD4;
unsigned char RXBD5;
unsigned char RXBD6;
unsigned char RXBD7;
} Bytes;
} RXBD;
} Specific;
};
union TXBuffer { //Transmit buffer structure
unsigned char Data[14];
struct {
union {
unsigned char Byte;
struct {
unsigned TXPRI0:1;
unsigned TXPRI1:1;
unsigned :1;
unsigned TXREQ:1;
unsigned TXERR:1;
unsigned TXLARB:1;
unsigned TXABT:1;
} Bits;
} TXBCON;
union {
unsigned char Byte;
} TXBSIDH;
union {
unsigned char Byte;
struct {
unsigned EID16:1;
unsigned EID17:1;
unsigned :1;
unsigned EXIDE:1;
unsigned :1;
unsigned SID0:1;
unsigned SID1:1;
unsigned SID2:1;
} Bits;
} TXBSIDL;
union {
unsigned char Byte;
} TXBEIDH;
union {
unsigned char Byte;
} TXBEIDL;
union {
unsigned char Byte;
struct {
unsigned DLC0:1;
unsigned DLC1:1;
unsigned DLC2:1;
unsigned DLC3:1;
unsigned :1;
unsigned :1;
unsigned TXRTR:1;
unsigned :1;
} Bits;
} TXBDLC;
union {
unsigned char Array[8];
struct {
unsigned char TXBD0;
unsigned char TXBD1;
unsigned char TXBD2;
unsigned char TXBD3;
unsigned char TXBD4;
unsigned char TXBD5;
unsigned char TXBD6;
unsigned char TXBD7;
} Bytes;
} TXBD;
} Specific;
};
union RXBuffer RXMessage[RXBUF]; //Received messages FIFO buffer
union TXBuffer TXMessage[TXBUF]; //Pending messages to transmit FIFO buffer
char RXRPtr = 0; //Read pointer for RXMessage buffer
char RXWPtr = 0; //Write pointer for RXMessage buffer
char TXRPtr = 0; //Read pointer for TXMessage buffer
char TXWPtr = 0; //Write pointer for TXMessage buffer
/*********************************************************************
* Function: void CANGetMessage(void)
*
* PreCondition: <WIN2:WIN0> in the CANCON register has to set
* to reflect the desired RXB registers
*
* Input: None
*
* Output: None
*
* Side Effects: Will modify the RX FIFO Write pointer (RXWPtr)
*
* Overview: Gets the registers for a RXB and puts them in the
* CAN Receive buffer
*
* Note: Care is not taken if buffer is full
********************************************************************/
void CANGetMessage(void);
/*********************************************************************
* Function: char CANPutMessage(void)
*
* PreCondition: <WIN2:WIN0> in the CANCON register has to set
* to reflect the desired TXB registers
*
* Input: None
*
* Output: 0 -> A new message has been put in the transmit queue
* 1 -> There was no messages in the TX buffer to send
*
* Side Effects: Will modify the TX buffer磗 Read pointer (TXRPtr)
*
* Overview: Checks if there is any messages to transmit and if so
* place it in the registers reflected by <WIN2:WIN0>
*
* Note: None
********************************************************************/
char CANPutMessage(void);
/*********************************************************************
* Function: char CANOpen(void)
*
* PreCondition: None
*
* Input: Values to be written into BRGCON1 -> BRGCON3
*
* Output: 0 -> Initialasation succeeded
*
* Side Effects: None
*
* Overview: Sets up the appropriate register for the device to act
* as a CAN node
*
* Note: Input values 0x03, 0xAA, 0x05 at Fosc = 16MHz works with
* the default firmware at nodeB on the CAN I/O expander board.
********************************************************************/
char CANOpen(unsigned char CONFIG1, unsigned char CONFIG2, unsigned char CONFIG3)
{
TRISB2 = 0;
TRISB3 = 1;
PIE3 = 0; //Disable all CAN interrupts
PIR3 = 0; //and clear all CAN interrupt flags
CANCON = (CONFIG_MODE & MODE_MASK) | (CANCON & 0x3F); //Set configuration mode
while((CANSTAT & MODE_MASK) != (CONFIG_MODE & MODE_MASK)); //Wait until config mode is set
BRGCON1 = CONFIG1;
BRGCON2 = CONFIG2;
BRGCON3 = CONFIG3;
RXB0CON = 0x04; //Receive all valid messages receive buffer overflow
RXB1CON = 0x00; //writes to RXB1
//Set the acceptance filters for all the filters
#ifdef ACCEPT_STANDARD_FILTER_0
RXF0SIDL = (unsigned char)(ACCEPTANCE_FILTER_0 << 5);
RXF0SIDH = (unsigned char)(ACCEPTANCE_FILTER_0 >> 3);
#else
RXF0EIDL = (unsigned char)(ACCEPTANCE_FILTER_0 & 0xFF);
RXF0EIDH = (unsigned char)((ACCEPTANCE_FILTER_0 >> 8) & 0xFF);
RXF0SIDL = (unsigned char)((ACCEPTANCE_FILTER_0 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_0 >> 13) & 0xE0) | 0x08;
RXF0SIDH = (unsigned char)((ACCEPTANCE_FILTER_0 >> 21) & 0xFF);
#endif
#ifdef ACCEPT_STANDARD_FILTER_1
RXF1SIDL = (unsigned char)(ACCEPTANCE_FILTER_1 << 5);
RXF1SIDH = (unsigned char)(ACCEPTANCE_FILTER_1 >> 3);
#else
RXF1EIDL = (unsigned char)(ACCEPTANCE_FILTER_1 & 0xFF);
RXF1EIDH = (unsigned char)((ACCEPTANCE_FILTER_1 >> 8) & 0xFF);
RXF1SIDL = (unsigned char)((ACCEPTANCE_FILTER_1 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_1 >> 13) & 0xE0) | 0x08;
RXF1SIDH = (unsigned char)((ACCEPTANCE_FILTER_1 >> 21) & 0xFF);
#endif
#ifdef ACCEPT_STANDARD_FILTER_2
RXF2SIDL = (unsigned char)(ACCEPTANCE_FILTER_2 << 5);
RXF2SIDH = (unsigned char)(ACCEPTANCE_FILTER_2 >> 3);
#else
RXF2EIDL = (unsigned char)(ACCEPTANCE_FILTER_2 & 0xFF);
RXF2EIDH = (unsigned char)((ACCEPTANCE_FILTER_2 >> 8) & 0xFF);
RXF2SIDL = (unsigned char)((ACCEPTANCE_FILTER_2 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_2 >> 13) & 0xE0) | 0x08;
RXF2SIDH = (unsigned char)((ACCEPTANCE_FILTER_2 >> 21) & 0xFF);
#endif
#ifdef ACCEPT_STANDARD_FILTER_3
RXF3SIDL = (unsigned char)(ACCEPTANCE_FILTER_3 << 5);
RXF3SIDH = (unsigned char)(ACCEPTANCE_FILTER_3 >> 3);
#else
RXF3EIDL = (unsigned char)(ACCEPTANCE_FILTER_3 & 0xFF);
RXF3EIDH = (unsigned char)((ACCEPTANCE_FILTER_3 >> 8) & 0xFF);
RXF3SIDL = (unsigned char)((ACCEPTANCE_FILTER_3 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_3 >> 13) & 0xE0) | 0x08;
RXF3SIDH = (unsigned char)((ACCEPTANCE_FILTER_3 >> 21) & 0xFF);
#endif
#ifdef ACCEPT_STANDARD_FILTER_4
RXF4SIDL = (unsigned char)(ACCEPTANCE_FILTER_4 << 5);
RXF4SIDH = (unsigned char)(ACCEPTANCE_FILTER_4 >> 3);
#else
RXF4EIDL = (unsigned char)(ACCEPTANCE_FILTER_4 & 0xFF);
RXF4EIDH = (unsigned char)((ACCEPTANCE_FILTER_4 >> 8) & 0xFF);
RXF4SIDL = (unsigned char)((ACCEPTANCE_FILTER_4 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_4 >> 13) & 0xE0) | 0x08;
RXF4SIDH = (unsigned char)((ACCEPTANCE_FILTER_4 >> 21) & 0xFF);
#endif
#ifdef ACCEPT_STANDARD_FILTER_5
RXF5SIDL = (unsigned char)(ACCEPTANCE_FILTER_5 << 5);
RXF5SIDH = (unsigned char)(ACCEPTANCE_FILTER_5 >> 3);
#else
RXF5EIDL = (unsigned char)(ACCEPTANCE_FILTER_5 & 0xFF);
RXF5EIDH = (unsigned char)((ACCEPTANCE_FILTER_5 >> 8) & 0xFF);
RXF5SIDL = (unsigned char)((ACCEPTANCE_FILTER_5 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_4 >> 13) & 0xE0) | 0x08;
RXF5SIDH = (unsigned char)((ACCEPTANCE_FILTER_5 >> 21) & 0xFF);
#endif
//Set the acceptance masks
RXM0EIDL = (unsigned char)(ACCEPTANCE_MASK_0_1 & 0xFF);
RXM0EIDH = (unsigned char)((ACCEPTANCE_MASK_0_1 >> 8) & 0xFF);
RXM0SIDL = (unsigned char)((ACCEPTANCE_MASK_0_1 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_MASK_0_1 >> 13) & 0xE0) | 0x08;
RXM0SIDH = (unsigned char)((ACCEPTANCE_MASK_0_1 >> 21) & 0xFF);
RXM1EIDL = (unsigned char)(ACCEPTANCE_MASK_2_5 & 0xFF);
RXM1EIDH = (unsigned char)((ACCEPTANCE_MASK_2_5 >> 8) & 0xFF);
RXM1SIDL = (unsigned char)((ACCEPTANCE_MASK_2_5 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_MASK_2_5 >> 13) & 0xE0) | 0x08;
RXM1SIDH = (unsigned char)((ACCEPTANCE_MASK_2_5 >> 21) & 0xFF);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -