单片机TwinCAN调试心得
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 CCECAN_ACR = 0x0041; // load global control register
/// -----------------------------------------------------------------------
/// Configuration of CAN Node B: /// -----------------------------------------------------------------------/// General Configuration of the Node B:
/// - set INIT and CCECAN_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 96CAN_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 quantaCAN_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: 0x0000CAN_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 0CAN_MSGCFGL0 = 0x0002; // load message configuration register low
CAN_MSGCFGH0 = 0x0000; // load message configuration register high/// - acceptance mask 11-bit: 0x7FF
/// - identifier 11-bit: 0x0B0CAN_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 highCAN_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 disabledCAN_MSGCFGL1 = 0x0082; // load message configuration register low
CAN_MSGCFGH1 = 0x0000; // load message configuration register high/// - acceptance mask 11-bit: 0x7FF
/// - identifier 11-bit: 0x002CAN_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 highCAN_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) = 0CAN_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 disabledPECC4 = 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 ENDwhile((( ((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 CCECAN_ACR = 0x0041; // load global control register
/// General Configuration of the Node B:
/// - set INIT and CCECAN_BCR = 0x0041; // load global control register
/// -----------------------------------------------------------------------
/// Configuration of the CAN Message Objects 0 - 31: /// ----------------------------------------------------------------------- /// - acceptance mask 11-bit: 0x7FF /// - identifier 11-bit: 0x0B0CAN_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: 0x400CAN_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<LEN; 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<num1; 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/ MSGDRn4void 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<LEN; 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);