📄 can_drv.c
字号:
//****************************************************************************
// Module On-Chip CAN Interface
// Filename Can_drv.C
// Controller AtmelWM 89C51CC01
//****************************************************************************
#include <REG51CC01.H>
#include <string.h>
#include "can_drv.h" // define user CAN id
// Macros for CAN Message Object Control and DLC register (CANCONCH)
#define CanTX 0x40 // Transmit
#define CanRX 0x80 // Receive
#define CanRXB 0xC0 // Receive in buffered mode
#define CanCONCH 0xC0 // Mask for the CONCH field
#define CanRPLV 0x20 // Remote Transmission Reply ready & valid
#define CanIDE 0x10 // ID extended (29-bit)
// Macros for CAN General Control register (CANGCON)
#define CanABRQ 0x80 // Abort request
#define CanOVRQ 0x40 // Overload frame request
#define CanTTC 0x20 // Network in Timer Trigger communication
#define CanSYNCTTC 0x10 // Synchronisation of TTC
#define CanAUTOBAUD 0x08 // autobaud mode
#define CanENA 0x02 // enable CAN controller
#define CanGRES 0x01 // general reset
// Macros for CAN General Interrupt Enable register (CANGIE)
#define CanENRX 0x20 // Enable receive interrupt
#define CanENTX 0x10 // Enable transmit interrupt
#define CanENERCH 0x08 // Enable message object error interrupt
#define CanENBUF 0x04 // Enable BUF interrupt
#define CanENERG 0x02 // Enable general error interrupt
// Macros for CAN General Interrupt register (CANGIT)
#define CanCANIT 0x80 // General Interrupt Flag
#define CanOVRTIM 0x20 // Overrun CAN Timer
#define CanOVRBUF 0x10 // Overrun Buffer
#define CanSERG 0x08 // Stuff error General
#define CanCERG 0x04 // CRC error General
#define CanFERG 0x02 // Form error General
#define CanAERG 0x01 // Acknowledgement error General
// Macros for CAN Message Object Status register (CANSTCH)
#define CanDLCW 0x80 // Data length code warning
#define CanTXOK 0x40 // Transmit OK
#define CanRXOK 0x20 // Receive OK
#define CanBERR 0x10 // Bit error
#define CanSERR 0x08 // Stuff error
#define CanCERR 0x04 // CRC error
#define CanFERR 0x02 // Form error
#define CanAERR 0x01 // Acknowledgement error
// Macros for ID initilisiation in CANIDTx, CANIDMx registers
#define CanID29(v) (((unsigned long)(v))<<3)
#define CanID11(v) (((unsigned long)(v))<<22)
#define CanIDEMSK 0x01 // enable comparison in CANIDM register
#define CanRTRMSK 0x04 // enable Remote Transmission request in CANIDM register
// Set value in CANIDTx registers
#define CanSetIDT(v) CANIDT1=((unsigned char)((v)>>24)); \
CANIDT2=((unsigned char)((v)>>16)); \
CANIDT3=((unsigned char)((v)>> 8)); \
CANIDT4=((unsigned char)(v)) ^ conf;
// Set value in CANIDMx registers
#define CanSetIDM(v) CANIDM1=((unsigned char)((v)>>24)); \
CANIDM2=((unsigned char)((v)>>16)); \
CANIDM3=((unsigned char)((v)>> 8)); \
CANIDM4=((unsigned char)(v));
// Convert Channel No. for CANPAGE register
#define CanChannel(v) ((v)<<4)
/****** C A N I D D E F I N I T I O N S *****************************************/
// Define Channel 0 Object Identifiers (handled in polling mode)
#define ID0 (CanID29(0x00000100))
#define ID0MSK (CanID29(0x1FFFFFFF) | CanIDEMSK)
#define ID0TYP (CanTX | CanIDE | 1) // Transmit, ID extended (29-bit),
// 1 Byte message length
// Define Channel 1 Object Identifiers (handled in polling mode)
#define ID1 (CanID29(0x00000101))
#define ID1MSK (CanID29(0x1FFFFFFF) | CanIDEMSK)
#define ID1TYP (CanRX | CanIDE | 1) // Receive, ID extended (29-bit),
// 1 Byte message length
// Define Channel 2 Object Identifiers (handled in interrupt mode)
#define ID2 (CanID29(0x00000102))
#define ID2MSK (CanID29(0x1FFFFFFF) | CanIDEMSK)
#define ID2TYP (CanTX | CanIDE | 8) // Transmit, ID extended (29-bit),
// 8 Byte message length
#define ID2IntChk (CANSIT2 & 0x04) // Interrupt Status for Message Object 2
// Define Channel 3 Object Identifiers (handled in interrupt mode)
#define ID3 (CanID29(0x00000103))
#define ID3MSK (CanID29(0x1FFFFFFF) | CanIDEMSK)
#define ID3TYP (CanRXB | CanIDE | 8) // Receive, ID extended (29-bit),
// 8 Byte message length
#define ID3IntChk (CANSIT2 & 0x08) // Interrupt Status for Message Object 3
// Define Channel 4 Object Identifiers (handled in interrupt mode)
#define ID4 (CanID29(0x00000103))
#define ID4MSK (CanID29(0x1FFFFFFF) | CanIDEMSK)
#define ID4TYP (CanRXB | CanIDE | 8) // Receive, ID extended (29-bit),
// 8 Byte message length
#define ID4IntChk (CANSIT2 & 0x10) // Interrupt Status for Message Object 4
// Define Channel 4 Object Identifiers ('client' for remote frame mode)
#define ID5 (CanID29(0x00000104))
#define ID5MSK (CanID29(0x1FFFFFFF) | CanIDEMSK)
#define ID5TYP (CanTX | CanIDE | 8) // Transmit, ID extended (29-bit),
// 8 Byte message length
// Define Channel 5 Object Identifiers ('server' for remote frame mode)
#define ID6 (CanID29(0x00000105))
#define ID6MSK (CanID29(0x1FFFFFFF) | CanIDEMSK)
#define ID6TYP (CanRX | CanIDE | 8) // Receive, ID extended (29-bit),
// 8 Byte message length
// IDxTYP table for all used message objects
unsigned char code id_typ[] = {
ID0TYP,
ID1TYP,
ID2TYP,
ID3TYP,
ID4TYP,
ID5TYP,
};
// ===== CAN Baudrate Calculation ======================
// Tscl = (1+BRP)/(XTAL) // for X2 Mode = ON
// Tscl = 2*(1+BRP)/(XTAL) // for X2 Mode = OFF
// Tbit = (1 + (PRS+1) + (PHS1+1) + (PHS2+1)) * Tscl
// Examples:
// 500KHz CAN Baudrate, X2 Mode = OFF, XTAL=12MHz
// BRP = 0, PRS = 2, PHS1 = 3, PHS2 = 3
// Tscl = 2/12.0MHz = 0.167 礢ec
// Tbit = (1 + (2+1)+(3+1)+(3+1)) * Tscl = 12 * 0.167uSec = 2 礢ec -> 500KHz Baudrate
// Examples:
// 1MHz CAN Baudrate, X2 Mode = ON, XTAL=20MHz
// BRP = 1, PRS = 1, PHS1 = 3, PHS2 = 2
// Tscl = 2/20.0MHz = 0.100 礢ec
// Tbit = (1 + (1+1)+(3+1)+(2+1)) * Tscl = 10 * 0.100uSec = 1 礢ec -> 1MHz Baudrate
#define BRP 1
#define SJW 0
#define PRS 1
#define PHS1 3
#define PHS2 2
/*
* CAN Initialization:
* - reset CAN controller
* - initialize CAN message object (ID, MSK, control)
* - clear message object status register
* - clear unused message object (ID, MSK, control, status)
* - enable CAN controller
*/
void CanInit (unsigned char conf) {
unsigned char i;
CANGCON |= CanGRES; // Reset CAN controller
ECAN = 0; // disable CAN interupt
ETIM = 0; // disable CAN timer overrun interrupt
// Init CAN Message Object 0 (Transmit)
CANPAGE = CanChannel (0);
CanSetIDT(ID0);
CanSetIDM(ID0MSK);
CANCONCH = 0; // mark no information for transmit objects
CANSTCH = 0;
// Init CAN Message Object 1 (Receive)
CANPAGE = CanChannel (1);
CanSetIDT(ID1);
CanSetIDM(ID1MSK);
CANCONCH = ID1TYP; // Object waits for data
CANSTCH = 0;
// Init CAN Message Object 2 (Transmit)
CANPAGE = CanChannel (2);
CanSetIDT(ID2);
CanSetIDM(ID2MSK);
CANCONCH = 0; // mark no information for transmit objects
CANSTCH = 0;
// Init CAN Message Object 3 (Receive)
CANPAGE = CanChannel (3);
CanSetIDT(ID3);
CanSetIDM(ID3MSK);
CANCONCH = ID3TYP; // Object waits for data
CANSTCH = 0;
// Init CAN Message Object 4 (Receive)
CANPAGE = CanChannel (4);
CanSetIDT(ID4);
CanSetIDM(ID4MSK);
CANCONCH = ID4TYP; // Object waits for data
CANSTCH = 0;
// Init CAN Message Object 5 (for Remote Requests)
CANPAGE = CanChannel (5);
CanSetIDT(ID5);
CanSetIDM(ID5MSK);
CANCONCH = 0; // mark no information for remote request objects
CANSTCH = 0;
// Init CAN Message Object 6 (for Remote Transmits)
CANPAGE = CanChannel (6);
CanSetIDT(ID6);
CanSetIDM(ID6MSK);
CANCONCH = ID6TYP; // mark no information for remote transmit objects
CANSTCH = 0;
// Clear unused Message Object Buffers
for (i = CanChannel (7); i <= CanChannel(14); i += CanChannel(1)) {
CANPAGE = i;
CanSetIDT(0); // Clear Object Buffer
CanSetIDM(0);
CANCONCH = 0;
CANSTCH = 0;
}
// Set CAN Baudrate
CANBT1 = ((BRP)<<1); // set CANBT1 register (BRP timing)
CANBT2 = ((PRS)<<1) | ((SJW)<<5); // set CANBT2 register (PRS & SJW timing)
CANBT3 = ((PHS1)<<1)| ((PHS2)<<4); // set CANBT3 register (PHS1 & PHS1 timing)
CANGCON |= CanENA; // enable CAN controller
// If you are using interrupt driven CAN I/O enable interrupts
ECAN = 1; // enable general CAN interupt
CANGIE |= CanENRX | CanENTX; // enable TX and RX interrupt
CANIE2 |= 0x0C; // enable TX and RX interrupt
}
/***** CAN I/O Routines for Polling Mode ******************************************/
/*
* CanSend:
* Input Parameter: ch := message object channel (0 .. 14)
* p := Pointer to data
*
* Return Value: 0 message transferred to buffer, transmission started
* -1 message object not defined for transmission
* -2 previous message not yet transferred
*
* - check if CAN message object is defined for transmit
* - check if a previous message is transmitted OK
* - copy new message to message object buffer
* - set message object for transmission
*/
char CanSend (unsigned char ch, unsigned char *p) {
unsigned char i;
static unsigned char typ;
// check if CAN message object is defined for transmit
if (ch >= sizeof (id_typ)) return (-1);
typ = id_typ[ch];
if ((typ & CanCONCH) != CanTX) return (-1);
i = typ & 0xF; // message length
CANPAGE = CanChannel(ch); // select CAN message object
if ((CANCONCH & CanCONCH)) { // CAN channel used before?
if (!(CANSTCH & CanTXOK)) {
return (-2); // previous message not yet send!
}
}
CANCONCH = 0; // reset previous status
CANSTCH = 0;
while (i) { // copy information to message buffer
CANMSG = *p++;
i--;
}
CANCONCH = typ; // send information
return (0); // message object copied to buffer
}
/*
* CanRead:
* Input Parameter: ch := message object channel (0 .. 14)
* p := pointer to data buffer
*
* Return Value: 0 n bytes of message transferred to data buffer
* -1 message object not defined for receiving
* -2 no message available
* -3 messsage data length differs from definition
*
* - check if CAN message object is defined for receiving
* - check if a message is received
* - copy received message to data buffer
* - set message object for receiving
*/
char CanRead (unsigned char ch, unsigned char *p) {
unsigned char i, typ;
// check if CAN message object is defined for reception
if (ch >= sizeof (id_typ)) return (-1);
typ = id_typ[ch];
if ((typ & CanCONCH) != CanRX) return (-1);
i = typ & 0xF; // message length
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -