XC164单片机TwinCAN模块调试心得 (转)
单片机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 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<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/ 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<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);