×
单片机 > 单片机程序设计 > 详情

单片机TwinCAN调试心得

发布时间:2020-06-06 发布时间:
|

1、  帧类型

(1)       数据帧:数据帧将数据从发送器传输到接收器

(2)       远程帧:总线单元发出远程帧,请求发送具有同一标识符的数据帧。/ MSGDRn4。

(3)       错误帧:任何单元检测到总线错误就发出错误帧

(4)       过载帧:过载帧用于在先行和后续数据帧(或远程帧)之间提供一附加的延时。

数据帧和远程帧即可使用标准帧,也可使用扩展帧。

2、  帧格式介绍

1  数据帧

数据帧由7个不同的位场组成,即帧起始、仲裁场、控制场、数据场、CRC场、应答场、帧结束。

2  远程帧

远程帧由6个不同的位场组成,即帧起始、仲裁场、控制场、CRC场、应答场、帧结束。

3  错误帧

错误帧由两个不同的场组成。第一个场是错误标志,用做为不同站提供错误标志的叠加;第二个场是错误界定符。

4  超载帧

超载帧包括两个位场:超载标志和超载界定符。

3、  报文路由:报文的内容由识别符命名。识别符不指出报文的目的地,但解释数据的含义。因此,网络上所有的节点可以通过报文滤波确定是否应对该数据做出反应。

4、  不同的系统,CAN 的速度不同。可是,在一给定的系统里,位速率是唯一的,并且是固定的。

5、  该模块分为两个节点,NODE A和NODE B,32个对象可以通过MSGCFGHn.NODE位来分别选择将该对象分配到哪个节点。

6、  该32个报文对象只能作为接受对象或发送对象,不能在接收和发送之间转换。作为接收对象的必须在初始化的时候首先将其配置成接收对象。

7、  回环模式可方便的用于调试,ABTR.LBM = 1和BBTR.LBM = 1,使能回环模式。在回环模式下,属于节点A的对象发送的报文只能由属于节点B的对象接受,反之亦如此。

8、  报文接收时可对所接收的报文进行验收滤波,称为报文标识符验收滤波。它们分别通过仲裁寄存器(MSGARHn,MSGARLn)(ID)和验收屏蔽寄存器(MSGAMRHn,MSGAMRLn)设置实现。具体过程如下:

 

9、  几个结构体的说明:

(1)       该寄存器用于软件编程,说明如下

typedef struct

  {

     uword  ;   // 消息配置寄存器

     ulong  ulID;       // 扩展标识 (29-bit)

     ulong  ulMask;     // 标准验收屏蔽(11-bit)/扩展验收屏蔽 (29-bit)

     ubyte  ubData[8];  // 八个字节数据

     uword  uwCounter;  // 当前接收对象接收到数据的帧数CAN_BFCRL或//CAN_AFCRL

  }TCAN_SWObj;

uwMsgCfg一般用到低字节,各位代表的意义如下:

         7     6     5      4    3     2     1     0

      |-----------------------------------------------------------------------|

      |        DLC            | DIR | XTD | NODE | RMM |

      |------------------------------------------------------------------------|

(2)       每个CAN对象寄存器结构体

struct stCanObj

{

  ubyte  ubData[8];  // Message Data 0..7

  ulong  ulCANAR;    // Arbitration Register

  ulong  ulCANAMR;   // Acceptance Mask Register

  uword  uwMSGCTR;   // Message Control Register

  uword  uwCounter;  // Frame Counter

  uword  uwMSGCFG;   // Message Configuration Register

  uword  uwINP;      // Interrupt Node Pointer

  uword  uwCANFCR;   // FIFO / Gateway Control Register

  uword  uwCANPTR;   // FIFO Pointer

  ulong  ulReserved; // Reserved

};

 

10、              几个重要寄存器的意义:

 

n.RXIE报文对象接收中断使能(=10)

.TXIE----报文对象发送中断使能(=10)

(3)       MSGCTRHn.MSGVAL---报文对象有效(=10)

(4)       MSGCTRHn.NEWDAT---报文对象中数据已更新(=10)

(5)       MSGCTRHn.MSGLST---NEWDAT仍然置位,CAN控制器已将报文保存到该报文对象中,而先前的报文丢失(=10),仅用于接受

(6)       MSGCTRHn.CPUUPD---报文对象自动发送被禁止(=10);可由CAN控制器自动发送报文对象中的数据(=01)

(7)       MSGCTRHn.TXRQ---CPU或远程帧请求的报文对象数据发送被挂起(=10)。报文成功发送后,TXRQ自动复位;如果存在几个有效的报文对象又挂起的发送请求,报文编号最低的报文对象将被首先发送

(8)       MSGCTRHn.RMTPND---远程节点请求报文对象数据发送,但数据并未发送。当RMTPND被置位时,CAN节点控制器也置位TXRQ.

 

.RMM---该发送报文对象的远程监控模式被使能。带匹配标识符远程帧的标识符和DLC码被复制到发送报文对象中,以监控输入的远程帧。该位仅对发送报文有效,对接受报文无影响。

(2)       MSGCFGHn.NODE---报文对象CAN节点选择,0=A,1=B

(3)       MSGCFGHn.XTD-----报文对象扩展标识符,1=11位,0=29位

(4)       MSGCFGHn.DIR------报文对象方向控制,0=定义该报文为发送对象,1=定义该报文为接受对象

(5)       MSGCFGHn.DLC-----报文对象数据长度码

(6)       MSGCFGHn.RXINP/TXINP---分别为接收/发送中断节点指针,0~7

 

11、              发送后一定要判断TXOK时候置位,确保在发送下一组数据之前将数据发送完成

12、              附程序:

 

H

 

#ifndef _CAN_H_

#define _CAN_H_

 

 

// The following data type serves as a software message object. Each access to

// a hardware message object has to be made by forward a pointer to a software

// message object (TCAN_SWObj). The data type has the following fields:

//

// uwMsgCfg:

// this byte has the same structure as the message configuration register of a

// hardware message object. It contains the "Data Lenght Code" (DLC), the

// "Extended Identifier" (XTD), the "Message Direction" (DIR), the "Node

// Select" and the "Remote Monitoring Mode".

//

//

//         7     6     5      4    3     2     1     0

//      |------------------------------------------------|

//      |        DLC            | DIR | XTD | NODE | RMM |

//      |------------------------------------------------|

//

// ulID:

// this field is four bytes long and contains either the 11-bit identifier

// or the 29-bit identifier

//

// ulMask:

// this field is four bytes long and contains either the 11-bit mask

// or the 29-bit mask

//

// ubData[8]:

// 8 bytes containing the data of a frame

//

// uwCounter:

// this field is two bytes long and contains the counter value

//

 

typedef struct

  {

     uword  uwMsgCfg;   // Message Configuration Register

     ulong  ulID;       // standard (11-bit)/extended (29-bit) identifier

     ulong  ulMask;     // standard (11-bit)/extended (29-bit) mask

     ubyte  ubData[8];  // 8-bit Data Bytes

     uword  uwCounter;  // Frame Counter

  }TCAN_SWObj;

 

 

void CAN_vInit(void);

void CAN_vGetMsgObj(ubyte ubObjNr, TCAN_SWObj *pstObj);

ubyte CAN_ubRequestMsgObj(ubyte ubObjNr);

ubyte CAN_ubNewData(ubyte ubObjNr);

void CAN_vTransmit(ubyte ubObjNr);

void CAN_vConfigMsgObj(ubyte ubObjNr, TCAN_SWObj *pstObj);

void CAN_vLoadData(ubyte ubObjNr, ubyte *pubData);

ubyte CAN_ubMsgLost(ubyte ubObjNr);

ubyte CAN_ubDelMsgObj(ubyte ubObjNr);

void CAN_vReleaseObj(ubyte ubObjNr);

void CAN_vSetMSGVAL(ubyte ubObjNr);

 

 

// USER CODE BEGIN (CAN_Header,8)

//发送一帧数据

 void CAN_vSend1Frame(unsigned char ObjNr, unsigned char XTD, unsigned long ID, unsigned char   *DataBuf, unsigned char LEN);

 //发送N个字节  

void CAN_vSendDataN(unsigned char ObjNr, unsigned char XTD, unsigned long ID, unsigned char *DataBuf, unsigned char LEN);

//报文对象初始化

TCAN_SWObj Init_vSWObj(TCAN_SWObj pstObj);

//接收报文函数

void CAN_vReveiveMsgObj(ubyte ubObjNr, TCAN_SWObj pstObj);

// USER CODE END

 

 

#define CAN_SRN0INT    0x54

 

#endif  // ifndef _CAN_H_

 

(2)    CAN.C

 

 
#include "MAIN.H"
  
  
extern unsigned char data2[8] ; 
extern unsigned char j;
extern unsigned int num;
unsigned char dataa[8] = {0x0a,0x1a,0x2a,0x3a,0x4a,0x5a,0x6a,0x7a};

extern unsigned char CCPdata[8]; 
struct stCanObj 
{
  ubyte  ubData[8];  // Message Data 0..7
  ulong  ulCANAR;    // Arbitration Register
  ulong  ulCANAMR;   // Acceptance Mask Register
  uword  uwMSGCTR;   // Message Control Register
  uword  uwCounter;  // Frame Counter
  uword  uwMSGCFG;   // Message Configuration Register
  uword  uwINP;      // Interrupt Node Pointer
  uword  uwCANFCR;   // FIFO / Gateway Control Register 
  uword  uwCANPTR;   // FIFO Pointer
  ulong  ulReserved; // Reserved
};

#define CAN_HWOBJ ((struct stCanObj volatile far *) 0x200300)  
   
 
void CAN_vInit(void)
{

  // USER CODE BEGIN (Init,2)

  // USER CODE END

  ///  -----------------------------------------------------------------------
  ///  Configuration of CAN Node A:
  ///  -----------------------------------------------------------------------

  ///  General Configuration of the Node A:
  ///  - set INIT and CCE

  CAN_ACR        =  0x0041;      // load global control register

  ///  -----------------------------------------------------------------------
  ///  Configuration of CAN Node B:
  ///  -----------------------------------------------------------------------

  ///  General Configuration of the Node B:
  ///  - set INIT and CCE

  CAN_BCR        =  0x0041;      // load global control register
  CAN_BGINP      =  0x0000;      // load global interrupt node pointer 
                                 // register

  ///  Configuration of the Node B Error Counter:
  ///  - the error warning threshold value (warning level) is 96

  CAN_BECNTH     =  0x0060;      // load error counter register high

  ///  Configuration of the used CAN Port Pins:
  ///  - P4.4 is used for CAN Interface Input (RXDCB)
  ///  - P4.7 is used for CAN Interface Output (TXDCB)

  ALTSEL0P4     |=  0x0080;      // select alternate output function
  DP4  = (DP4  & ~(uword)0x0080) | 0x0080;    //set direction register

  ///  Configuration of the Node B Baud Rate:
  ///  - required baud rate = 1.000 Mbaud
  ///  - real baud rate     = 1.000 Mbaud
  ///  - sample point       = 60.00 %
  ///  - there are 5 time quanta before sample point
  ///  - there are 4 time quanta after sample point
  ///  - the (re)synchronization jump width is 2 time quanta

  CAN_BBTRL      =  0x3443;      // load bit timing register low

  CAN_BBTRH      =  0x0000;      // load bit timing register high

  ///  Configuration of the Frame Counter:
  ///  - the counter is incremented each time a frame was received correctly
  ///  - frame counter: 0x0000

  CAN_BFCRL      =  0x0000;      // load frame counter timing register low

  CAN_BFCRH      =  0x0002;      // load frame counter timing register high

  ///  -----------------------------------------------------------------------
  ///  Configuration of the CAN Message Objects 0 - 31:
  ///  -----------------------------------------------------------------------

  ///  -----------------------------------------------------------------------
  ///  Configuration of Message Object 0:
  ///  -----------------------------------------------------------------------
  ///  - message object 0 is valid
  ///  - enable receive interrupt; bit INTPND is set after successfull 
  ///    reception of a frame

  ///  - message object is used as receive object
  ///  - standard 11-bit identifier
  ///  - 0 valid data bytes
  ///  - this message object works with CAN node B
  ///  - remote monitoring is disabled
  ///  - receive interrupt node pointer: TwinCAN SRN 0

  CAN_MSGCFGL0   =  0x0002;      // load message configuration register low
  CAN_MSGCFGH0   =  0x0000;      // load message configuration register high

  ///  - acceptance mask 11-bit: 0x7FF
  ///  - identifier 11-bit:      0x0B0

  CAN_MSGAMRL0   =  0x0000;      // load acceptance mask register low
  CAN_MSGAMRH0   =  0xFFFC;      // load acceptance mask register high
  CAN_MSGARL0    =  0x0000;      // load arbitration register low
  CAN_MSGARH0    =  0x02C0;      // load arbitration register high
  CAN_MSGDRL00   =  0x0000;      // load data register 0 low
  CAN_MSGDRH00   =  0x0000;      // load data register 0 high
  CAN_MSGDRL04   =  0x0000;      // load data register 4 low
  CAN_MSGDRH04   =  0x0000;      // load data register 4 high

  ///  - functionality of standard message object

  CAN_MSGFGCRL0  =  0x0000;      // load FIFO/gateway control register low
  CAN_MSGFGCRH0  =  0x0000;      // load FIFO/gateway control register high

  CAN_MSGCTRH0   =  0x0000;      // load message control register high
  CAN_MSGCTRL0   =  0x5599;      // load message control register low

  ///  -----------------------------------------------------------------------
  ///  Configuration of Message Object 1:
  ///  -----------------------------------------------------------------------
  ///  - message object 1 is valid

  ///  - message object is used as receive object
  ///  - standard 11-bit identifier
  ///  - 8 valid data bytes
  ///  - this message object works with CAN node B
  ///  - remote monitoring is disabled

  CAN_MSGCFGL1   =  0x0082;      // load message configuration register low
  CAN_MSGCFGH1   =  0x0000;      // load message configuration register high

  ///  - acceptance mask 11-bit: 0x7FF
  ///  - identifier 11-bit:      0x002

  CAN_MSGAMRL1   =  0xFFFF;      // load acceptance mask register low
  CAN_MSGAMRH1   =  0xFFFF;      // load acceptance mask register high
  CAN_MSGARL1    =  0x0000;      // load arbitration register low
  CAN_MSGARH1    =  0x0008;      // load arbitration register high
  CAN_MSGDRL10   =  0x0000;      // load data register 0 low
  CAN_MSGDRH10   =  0x0000;      // load data register 0 high
  CAN_MSGDRL14   =  0x0000;      // load data register 4 low
  CAN_MSGDRH14   =  0x0000;      // load data register 4 high

  ///  - functionality of standard message object

  CAN_MSGFGCRL1  =  0x0000;      // load FIFO/gateway control register low
  CAN_MSGFGCRH1  =  0x0001;      // load FIFO/gateway control register high

  CAN_MSGCTRH1   =  0x0000;      // load message control register high
  CAN_MSGCTRL1   =  0x5595;      // load message control register low


  ///  -----------------------------------------------------------------------
  ///  Configuration of Service Request Nodes 0 - 7:
  ///  -----------------------------------------------------------------------
  ///  SRN0 service request node configuration:
  ///  - SRN0 interrupt priority level (ILVL) = 15
  ///  - SRN0 interrupt group level (GLVL) = 0
  ///  - SRN0 group priority extension (GPX) = 0

  CAN_0IC        =  0x007C;    

  ///  Use PEC channel 4 for CAN INT 0:
  ///  - normal interrupt
  ///  - pointers are not modified
  ///  - transfer a word
  ///  - service End of PEC interrrupt by a EOP interrupt node is disabled
  ///  - channel link mode is disabled

  PECC4          =  0x0000;      // load PECC4 control register

 


  // USER CODE BEGIN (Init,3)

  // USER CODE END


  CAN_PISEL      =  0x0000;      // load port input select register

  //   -----------------------------------------------------------------------
  //   Start the CAN Nodes:
  //   -----------------------------------------------------------------------

  CAN_BCR       &= ~(uword)0x0041; // reset INIT and CCE


  // USER CODE BEGIN (Init,4)

  // USER CODE END

} //  End of function CAN_vInit


 
//****************************************************************************
// @Function      ubyte CAN_ubRequestMsgObj(ubyte ubObjNr) 
//
//----------------------------------------------------------------------------
// @Description   If a TRANSMIT OBJECT is to be reconfigured it must first be 
//                accessed. The access to the transmit object is exclusive. 
//                This function checks whether the choosen message object is 
//                still executing a transmit request, or if the object can be 
//                accessed exclusively.
//                After the message object is reserved, it can be 
//                reconfigured by using the function CAN_vConfigMsgObj or 
//                CAN_vLoadData.
//                Both functions enable access to the object for the CAN 
//                controller. 
//                By calling the function CAN_vTransmit transfering of data 
//                is started.
//
//----------------------------------------------------------------------------
// @Returnvalue   0 message object is busy (a transfer is active), else 1
//
//----------------------------------------------------------------------------
// @Parameters    ubObjNr: 
//                Number of the message object (0-31)
//
//----------------------------------------------------------------------------
// @Date          2010-5-14
//
//**************************************************************************** 
ubyte CAN_ubRequestMsgObj(ubyte ubObjNr)
{
  ubyte ubReturn;

  ubReturn = 0;
  if((CAN_HWOBJ[ubObjNr].uwMSGCTR & 0x3000) == 0x1000)  // if reset TXRQ 
  {
    CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xfbff;               // set CPUUPD 
    ubReturn = 1;
  }
  return(ubReturn);

} //  End of function CAN_ubRequestMsgObj


//****************************************************************************
// @Function      ubyte CAN_ubNewData(ubyte ubObjNr) 
//
//----------------------------------------------------------------------------
// @Description   This function checks whether the selected RECEIVE OBJECT 
//                has received a new message. If so the function returns the 
//                value '1'.
//
//----------------------------------------------------------------------------
// @Returnvalue   1 the message object has received a new message, else 0
//
//----------------------------------------------------------------------------
// @Parameters    ubObjNr: 
//                Number of the message object (0-31)
//
//----------------------------------------------------------------------------
// @Date          2010-5-14
//
//****************************************************************************

// USER CODE BEGIN (NewData,1)

// USER CODE END

ubyte CAN_ubNewData(ubyte ubObjNr)
{
  ubyte ubReturn;

  ubReturn = 0;
  if((CAN_HWOBJ[ubObjNr].uwMSGCTR & 0x0300) == 0x0200)  // if NEWDAT
  {
    ubReturn = 1;
  }
  return(ubReturn);

} //  End of function CAN_ubNewData


//****************************************************************************
// @Function      void CAN_vTransmit(ubyte ubObjNr) 
//
//----------------------------------------------------------------------------
// @Description   This function triggers the CAN controller to send the 
//                selected message.
//                If the selected message object is a TRANSMIT OBJECT then 
//                this function triggers the sending of a data frame. If 
//                however the selected message object is a RECEIVE OBJECT 
//                this function triggers the sending of a remote frame.
//
//----------------------------------------------------------------------------
// @Returnvalue   None
//
//----------------------------------------------------------------------------
// @Parameters    ubObjNr: 
//                Number of the message object (0-31)
//
//----------------------------------------------------------------------------
// @Date          2010-5-14
//
//****************************************************************************

// USER CODE BEGIN (Transmit,1)

// USER CODE END

void CAN_vTransmit(ubyte ubObjNr)
{
  CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xe7ff;  // set TXRQ, reset CPUUPD

} //  End of function CAN_vTransmit


//****************************************************************************
// @Function      void CAN_vConfigMsgObj(ubyte ubObjNr, TCAN_SWObj *pstObj) 
//
//----------------------------------------------------------------------------
// @Description   This function sets up the message objects. This includes 
//                the 8 data bytes, the identifier (11- or 29-bit), the 
//                acceptance mask (11- or 29-bit), the data number (0-8 
//                bytes), the frame counter value and the XTD-bit (standard 
//                or extended identifier).  The direction bit (DIR), the NODE 
//                bit and the RMM (remote monitoring) bit can not be changed. 
//                The message is not sent; for this the function 
//                CAN_vTransmit must be called.
//                
//                The structure of the SW message object is defined in the 
//                header file CAN.H (see TCAN_SWObj).
//
//----------------------------------------------------------------------------
// @Returnvalue   None
//
//----------------------------------------------------------------------------
// @Parameters    ubObjNr: 
//                Number of the message object to be configured (0-31)
// @Parameters    *pstObj: 
//                Pointer on a message object
//
//----------------------------------------------------------------------------
// @Date          2010-5-14
//
//****************************************************************************

// USER CODE BEGIN (ConfigMsgObj,1)

// USER CODE END

void CAN_vConfigMsgObj(ubyte ubObjNr, TCAN_SWObj *pstObj)
{
  ubyte i;

  CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xfb7f;     // set CPUUPD, reset MSGVAL

  if(pstObj->uwMsgCfg & 0x0004)             // extended identifier
  {
    CAN_HWOBJ[ubObjNr].uwMSGCFG |= 0x0004;
    CAN_HWOBJ[ubObjNr].ulCANAR   = pstObj->ulID ;
    CAN_HWOBJ[ubObjNr].ulCANAMR  = pstObj->ulMask ;
  }
  else                                      // standard identifier
  {
    CAN_HWOBJ[ubObjNr].uwMSGCFG &= ~(uword)0x0004;
    CAN_HWOBJ[ubObjNr].ulCANAR   = pstObj->ulID << 18;
    CAN_HWOBJ[ubObjNr].ulCANAMR  = pstObj->ulMask << 18;
  }

  CAN_HWOBJ[ubObjNr].uwCounter = pstObj->uwCounter;

  CAN_HWOBJ[ubObjNr].uwMSGCFG  = (CAN_HWOBJ[ubObjNr].uwMSGCFG & 0x000f) | (pstObj->uwMsgCfg & 0x00f0);

  if(CAN_HWOBJ[ubObjNr].uwMSGCFG & 0x0008)  // if transmit direction
  {
    for(i = 0; i < (pstObj->uwMsgCfg & 0x00f0) >> 4; i++)
    {
      CAN_HWOBJ[ubObjNr].ubData[i] = pstObj->ubData[i];
    }
    CAN_HWOBJ[ubObjNr].uwMSGCTR  = 0xf6bf;  // set NEWDAT, reset CPUUPD, 
  }                                         // set MSGVAL
  else                                      // if receive direction
  {
    CAN_HWOBJ[ubObjNr].uwMSGCTR  = 0xf7bf;  // reset CPUUPD, set MSGVAL
  }

} //  End of function CAN_vConfigMsgObj


//****************************************************************************
// @Function      void CAN_vLoadData(ubyte ubObjNr, ubyte *pubData) 
//
//----------------------------------------------------------------------------
// @Description   If a hardware TRANSMIT OBJECT has to be loaded with data 
//                but not with a new identifier, this function may be used 
//                instead of the function CAN_vConfigMsgObj. The message 
//                object should be accessed by calling the function 
//                CAN_ubRequestMsgObj before calling this function. This 
//                prevents the CAN controller from working with invalid data.
//
//----------------------------------------------------------------------------
// @Returnvalue   None
//
//----------------------------------------------------------------------------
// @Parameters    ubObjNr: 
//                Number of the message object to be configured (0-31)
// @Parameters    *pubData: 
//                Pointer on a data buffer
//
//----------------------------------------------------------------------------
// @Date          2010-5-14
//
//****************************************************************************

// USER CODE BEGIN (LoadData,1)

// USER CODE END

void CAN_vLoadData(ubyte ubObjNr, ubyte *pubData)
{
  ubyte i;

  CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xfaff;       // set CPUUPD and NEWDAT

  for(i = 0; i < (CAN_HWOBJ[ubObjNr].uwMSGCFG & 0xf0) >> 4; i++)
  {
    CAN_HWOBJ[ubObjNr].ubData[i] = *(pubData++);
  }

  CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xf7ff;       // reset CPUUPD

} //  End of function CAN_vLoadData


//****************************************************************************
// @Function      ubyte CAN_ubMsgLost(ubyte ubObjNr) 
//
//----------------------------------------------------------------------------
// @Description   If a RECEIVE OBJECT receives new data before the old object 
//                has been read, the old object is lost. The CAN controller 
//                indicates this by setting the message lost bit (MSGLST). 
//                This function returns the status of this bit. 
//                
//                Note:
//                This function resets the message lost bit (MSGLST).
//
//----------------------------------------------------------------------------
// @Returnvalue   1 the message object has lost a message, else 0
//
//----------------------------------------------------------------------------
// @Parameters    ubObjNr: 
//                Number of the message object (0-31)
//
//----------------------------------------------------------------------------
// @Date          2010-5-14
//
//****************************************************************************

// USER CODE BEGIN (MsgLost,1)

// USER CODE END

ubyte CAN_ubMsgLost(ubyte ubObjNr)
{
  ubyte ubReturn;

  ubReturn = 0;
  if((CAN_HWOBJ[ubObjNr].uwMSGCTR & 0x0c00) == 0x0800)  // if set MSGLST 
  {
    CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xf7ff;               // reset MSGLST 
    ubReturn = 1;
  }
  return(ubReturn);

} //  End of function CAN_ubMsgLost


//****************************************************************************
// @Function      ubyte CAN_ubDelMsgObj(ubyte ubObjNr) 
//
//----------------------------------------------------------------------------
// @Description   This function marks the selected message object as not 
//                valid. This means that this object cannot be sent or 
//                receive data. If the selected object is busy (meaning the 
//                object is transmitting a message or has received a new 
//                message) this function returns the value "0" and the object 
//                is not deleted.
//
//----------------------------------------------------------------------------
// @Returnvalue   1 the message object was deleted, else 0
//
//----------------------------------------------------------------------------
// @Parameters    ubObjNr: 
//                Number of the message object (0-31)
//
//----------------------------------------------------------------------------
// @Date          2010-5-14
//
//****************************************************************************

// USER CODE BEGIN (DelMsgObj,1)

// USER CODE END

ubyte CAN_ubDelMsgObj(ubyte ubObjNr)
{
  ubyte ubReturn;

  ubReturn = 0;
  if(!(CAN_HWOBJ[ubObjNr].uwMSGCTR & 0xa200)) // if set RMTPND, TXRQ or NEWDAT
  {
    CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xff7f;     // reset MSGVAL
    ubReturn = 1;
  }
  return(ubReturn);

} //  End of function CAN_ubDelMsgObj


//****************************************************************************
// @Function      void CAN_vReleaseObj(ubyte ubObjNr) 
//
//----------------------------------------------------------------------------
// @Description   This function resets the NEWDAT flag of the selected 
//                RECEIVE OBJECT, so that the CAN controller have access to 
//                it. This function must be called if the function 
//                CAN_ubNewData detects, that new data are present in the 
//                message object and the actual data have been read by 
//                calling the function CAN_vGetMsgObj. 
//
//----------------------------------------------------------------------------
// @Returnvalue   None
//
//----------------------------------------------------------------------------
// @Parameters    ubObjNr: 
//                Number of the message object (0-31)
//
//----------------------------------------------------------------------------
// @Date          2010-5-14
//
//****************************************************************************

// USER CODE BEGIN (ReleaseObj,1)

// USER CODE END

void CAN_vReleaseObj(ubyte ubObjNr)
{
  CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xfdff;       // reset NEWDAT

} //  End of function CAN_vReleaseObj


//****************************************************************************
// @Function      void CAN_vSetMSGVAL(ubyte ubObjNr) 
//
//----------------------------------------------------------------------------
// @Description   This function sets the MSGVAL flag of the selected object. 
//                This is only necessary if the single data transfer mode 
//                (SDT) for the selected object is enabled. If SDT is set to 
//                '1', the CAN controller automatically resets bit MSGVAL 
//                after receiving or tranmission of a frame.
//
//----------------------------------------------------------------------------
// @Returnvalue   None
//
//----------------------------------------------------------------------------
// @Parameters    ubObjNr: 
//                Number of the message object (0-31)
//
//----------------------------------------------------------------------------
// @Date          2010-5-14
//
//****************************************************************************

// USER CODE BEGIN (SetMSGVAL,1)

// USER CODE END

void CAN_vSetMSGVAL(ubyte ubObjNr)
{
  CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xffbf;  // set MSGVAL

} //  End of function CAN_vSetMSGVAL


//****************************************************************************
// @Function      void CAN_viSRN0(void) 
//
//----------------------------------------------------------------------------
// @Description   This is the interrupt service routine for the Service 
//                Request Node 0 of the TwinCAN module.
//
//----------------------------------------------------------------------------
// @Returnvalue   None
//
//----------------------------------------------------------------------------
// @Parameters    None
//
//----------------------------------------------------------------------------
// @Date          2010-5-14
//
//****************************************************************************

// USER CODE BEGIN (SRN0,1)

// USER CODE END

void CAN_viSRN0(void) interrupt CAN_SRN0INT using RB_LEVEL15
{

  // USER CODE BEGIN (SRN0,2) 
 TCAN_SWObj pstObj0;
  // USER CODE END

  while((( ((ulong)CAN_RXIPNDH << 16) + CAN_RXIPNDL) & 0x00000003))
  {

    // message object 0 interrupt

    if((CAN_HWOBJ[0].uwMSGCTR & 0x0003) == 0x0002)         // if INTPND 
    {
      if(CAN_RXIPNDL & CAN_RXIPNDL_RXIPND0)   // message object 0 receive interrupt
      {

        if((CAN_HWOBJ[0].uwMSGCTR & 0x0300) == 0x0200)     // if NEWDAT is set
        {

          if ((CAN_HWOBJ[0].uwMSGCTR & 0x0c00) == 0x0800)  // if MSGLST is set
          {
            // Indicates that the CAN controller has stored a new 
            // message into this object, while NEWDAT was still set,
            // ie. the previously stored message is lost.

            CAN_HWOBJ[0].uwMSGCTR = 0xf7ff;  // reset MSGLST

            // USER CODE BEGIN (SRN0_OBJ0,1)

            // USER CODE END
          }
          else
          {
            // The CAN controller has stored a new message
            // into this object.

            // USER CODE BEGIN (SRN0_OBJ0,2)
   
    CAN_vReveiveMsgObj(0, pstObj0);
            // USER CODE END
          }

          CAN_HWOBJ[0].uwMSGCTR = 0xfdff;    // reset NEWDAT
        }

      }  // End of RXIPND0


      CAN_HWOBJ[0].uwMSGCTR = 0xfffd;        // reset INTPND

      // USER CODE BEGIN (SRN0_OBJ0,6)

      // USER CODE END

    }


    // message object 1 interrupt
 
    // USER CODE BEGIN (SRN0,3)

    // USER CODE END


  }  // End of while()

  // USER CODE BEGIN (SRN0,7)

  // USER CODE END

} //  End of function CAN_viSRN0

 

// USER CODE BEGIN (CAN_General,10)

// 发送数据后重新对CAN模块初始化,主要是仲裁寄存器和屏蔽寄存器
void CAN_vSetARMR(void)

   

  ///  General Configuration of the Node A:           
  ///  - set INIT and CCE

  CAN_ACR        =  0x0041;      // load global control register
 

  ///  General Configuration of the Node B:
  ///  - set INIT and CCE

  CAN_BCR        =  0x0041;      // load global control register 

  ///  -----------------------------------------------------------------------
  ///  Configuration of the CAN Message Objects 0 - 31:
  ///  ----------------------------------------------------------------------- 
   
  ///  - acceptance mask 11-bit: 0x7FF
  ///  - identifier 11-bit:      0x0B0

  CAN_MSGAMRL0   =  0x0000;      // load acceptance mask register low
  CAN_MSGAMRH0   =  0xFFFC;      // load acceptance mask register high
  CAN_MSGARL0    =  0x0000;      // load arbitration register low
  CAN_MSGARH0    =  0x02C0;      // load arbitration register high
  CAN_MSGDRL00   =  0x0000;      // load data register 0 low
  CAN_MSGDRH00   =  0x0000;      // load data register 0 high
  CAN_MSGDRL04   =  0x0000;      // load data register 4 low
  CAN_MSGDRH04   =  0x0000;      // load data register 4 high
  ///  - acceptance mask 11-bit: 0x7FF
  ///  - identifier 11-bit:      0x400

  CAN_MSGAMRL1   =  0x0000;      // load acceptance mask register low
  CAN_MSGAMRH1   =  0xFFFC;      // load acceptance mask register high
  CAN_MSGARL1    =  0x0000;      // load arbitration register low
  CAN_MSGARH1    =  0x1000;      // load arbitration register high
  CAN_MSGDRL10   =  0x0000;      // load data register 0 low
  CAN_MSGDRH10   =  0x0000;      // load data register 0 high
  CAN_MSGDRL14   =  0x0000;      // load data register 4 low
  CAN_MSGDRH14   =  0x0000;      // load data register 4 high 
  CAN_HWOBJ[1].uwMSGCFG &=  ~0x0008;   //定义报文对象为接收对象   
  //   -----------------------------------------------------------------------
  //   Start the CAN Nodes:
  //   -----------------------------------------------------------------------

  CAN_BCR       &= ~(uword)0x0041; // reset INIT and CCE 
}

//初始化接收数组对象
TCAN_SWObj Init_vSWObj(TCAN_SWObj pstObj){
 int i;
 pstObj.ulID = 0x0000;
 pstObj.ulMask = 0x0000;
 pstObj.uwCounter = 0;
 pstObj.uwMsgCfg = 0;
 for(i=0; i<8; i++)
 {
  pstObj.ubData[i] = 0x00;
 }
 return pstObj;
}
//CAN_vSendData(0,0x10,data,6);
//功  能:CAN发送1帧数据(数据长度<=8)                                       *
//参  数:ID---报文标识符                                                   *
//       DataBUF---报文数据区首址                                          *
//       LEN---报文数据长度                                                *
//   objNr---报文对象
//       XTD  ---标识符类型 0=标准标识符,1=扩展标识符
//返  回:INT8U CANsnd1DFrm --- 发送成功与否标志,                          *
//       =0,没有空闲发送缓冲区,发送不成功;=1,发送成功                  */
void CAN_vSend1Frame(unsigned char ObjNr,unsigned char XTD, unsigned long ID, unsigned char *DataBuf, unsigned char LEN)

 unsigned char i; 
 TCAN_SWObj pstObj;
 //初始化报文对象 
 pstObj = Init_vSWObj(pstObj);
 if(XTD == 0)
 {             
  pstObj.uwMsgCfg &= ~0x0004;    //11位标准标识符
 }
 else
 {         
  pstObj.uwMsgCfg |= 0x0004;    //29位扩展标识符
 }
 pstObj.ulID  = ID;
    pstObj.uwMsgCfg |= (1 <<3 ); //定义该报文对象为发送对象,请求发送,发送数据帧
 pstObj.uwMsgCfg |= LEN << 4;  //定义发送报文长度
 for(i=0; i {          
     pstObj.ubData[i] = *((unsigned char far *)(DataBuf++));
  data2[i] =  pstObj.ubData[i];
 }  
 if(CAN_ubRequestMsgObj(ObjNr))//判断节点空闲
 {  
  CAN_HWOBJ[ObjNr].uwMSGCFG |=  0x0008;   //定义报文对象为发送对象
  CAN_vConfigMsgObj(ObjNr, &pstObj);     
        CAN_HWOBJ[ObjNr].uwMSGCTR = 0xe7ff;  // 置位 TXRQ, 复位 CPUUPD,开始发送数据
  if(CAN_HWOBJ[ObjNr].uwMSGCFG & 0x0002) //该对象与B节点相连
  {       
   while(0 == (CAN_BSR & 0X008))  //等待发送完成
   {
    for(i=0;i<10;i++);
   }
   CAN_BSR &= 0XFFF7;      //清除TXOK标志
  }
  else   //该对象与A节点相连
  {     
   while(0 == (CAN_ASR & 0X008))  //等待发送完成
   {
    for(i=0;i<10;i++);
   }
   CAN_ASR &= 0XFFF7;      //清除TXOK标志
  }           
        CAN_HWOBJ[ObjNr].uwMSGCTR = 0xfdff;       // 复位 NEWDAT,使用完后释放该节点  
//  CAN_vSetARMR();     //重新设定仲裁和标识符屏蔽寄存器
 }       
}
//发送N个字节 
void CAN_vSendDataN( unsigned char ObjNr, unsigned char XTD,unsigned long ID, unsigned char *DataBuf, unsigned char LEN)
{
 unsigned int num1, num2, i;  
 if(XTD == 1)
 {          
  CAN_HWOBJ[ObjNr].uwMSGCFG |= 0x0004;  //扩展帧标识符
 } 
 num1 = LEN / 8;
 num2 = LEN % 8;
 for(i=0; i {
  CAN_vSend1Frame(ObjNr, XTD, ID, DataBuf+i*8, 8);
 } 

 CAN_vSend1Frame(ObjNr, XTD,ID, DataBuf+num1*8, num2);  
 if(XTD == 1)
 {          
  CAN_HWOBJ[ObjNr].uwMSGCFG &= ~0x0004;  //设置回标准帧标识符 
 } 
}
// CAN_vSendFarFrame(0,0, 0x0001b, data_send, 4);
// 发送远程帧,当接收到带有匹配标识符的数据帧时,报文数据保存到相关的数据寄存器MSGDRn0/ MSGDRn4
void CAN_vSendFarFrame(unsigned char ObjNr,unsigned char XTD, unsigned long ID, unsigned char *DataBuf, unsigned char LEN)
{  
  unsigned char i; 
 TCAN_SWObj pstObj;
 //初始化报文对象 
 pstObj = Init_vSWObj(pstObj);
 if(XTD == 0)
 {             
  pstObj.uwMsgCfg &= ~0x0004;    //11位标准标识符
 }
 else
 {         
  pstObj.uwMsgCfg |= 0x0004;    //29位扩展标识符
 }
 pstObj.ulID  = ID;
    pstObj.uwMsgCfg &= ~(1 <<3 ); //定义该报文对象为接受对象,请求发送,发送远程
 pstObj.uwMsgCfg |= LEN << 4;  //定义发送报文长度
 for(i=0; i {          
     pstObj.ubData[i] = *((unsigned char far *)(DataBuf++));
  data2[i] =  pstObj.ubData[i];
 }  
 if(CAN_ubRequestMsgObj(ObjNr))//判断节点空闲
 {  
  CAN_HWOBJ[ObjNr].uwMSGCFG |=  0x0008;   //定义报文对象为发送对象
  CAN_vConfigMsgObj(ObjNr, &pstObj);     
        CAN_HWOBJ[ObjNr].uwMSGCTR = 0xe7ff;  // 置位 TXRQ, 复位 CPUUPD,开始发送数据
  if(CAN_HWOBJ[ObjNr].uwMSGCFG & 0x0002) //该对象与B节点相连
  {      
   while(0 == (CAN_BSR & 0X008)); //等待发送完成
   CAN_BSR &= 0XFFF7;      //清除TXOK标志
  }
  else   //该对象与A节点相连
  {    
   while(0 == (CAN_ASR & 0X008)); //等待发送完成
   CAN_ASR &= 0XFFF7;      //清除TXOK标志
  } 
        CAN_HWOBJ[ObjNr].uwMSGCTR = 0xfdff;       // 复位 NEWDAT,使用完后释放该节点  
   CAN_HWOBJ[ObjNr].uwMSGCFG &=  ~0x0008;   //定义报文对象为接收对象   
  //   CAN_vSetARMR();     //重新设定仲裁和标识符屏蔽寄存器
 }    
}

//功能:接收报文函数
//参数:
//  ubObjNr:接收报文对象的编号 
// pstObj:接收参数 
//返回:空
void CAN_vReveiveMsgObj(ubyte ubObjNr, TCAN_SWObj pstObj)
{       
 int i;
 //初始化报文对象 
 pstObj = Init_vSWObj(pstObj);    
 for(i = 0; i < (CAN_HWOBJ[ubObjNr].uwMSGCFG & 0x00f0) >> 4; i++)//接收数据
 {
  pstObj.ubData[i] = CAN_HWOBJ[ubObjNr].ubData[i];
 }
 
 if(CAN_HWOBJ[ubObjNr].uwMSGCFG & 0x04)  // extended identifier
 {
  pstObj.ulID   = CAN_HWOBJ[ubObjNr].ulCANAR;
  pstObj.ulMask = CAN_HWOBJ[ubObjNr].ulCANAMR;
 }
 else                                    // standard identifier 
 {
  pstObj.ulID   = CAN_HWOBJ[ubObjNr].ulCANAR >> 18;
  pstObj.ulMask = CAN_HWOBJ[ubObjNr].ulCANAMR >> 18;
 }
 
 pstObj.uwCounter = CAN_HWOBJ[ubObjNr].uwCounter;
 pstObj.uwMsgCfg  = CAN_HWOBJ[ubObjNr].uwMSGCFG;    
  
 
 ccpCommand(pstObj.ubData); // CCP命令解析  
}

// USER CODE END


// USER CODE END

(3)     调用方法

 //使用节点0发送data_send中的12个字节

//11位标准标识符,标识符为0x0400,

 

 CAN_vSendDataN(0,0, 0x00400, data_send, 12);

 //使用节点1送data_send中的12个字节

//11位标准标识符,标识符为0x0400,

CAN_vSendDataN(1,0, 0x00400, data_send, 12);   



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
浅谈AVR中定时器几种工作模式