⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can_drv.c

📁 T89c51cc01的CAN通信子程序
💻 C
📖 第 1 页 / 共 2 页
字号:
//****************************************************************************
// 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 + -