📄 can_drv.c
字号:
CANPAGE = CanChannel(ch); // select CAN message object
if (!(CANSTCH & CanRXOK)) {
return (-2); // no message available
}
if (CANSTCH & CanDLCW) {
return (-2); // incoming message does not have expected length
}
CANCONCH = 0; // reset previous status
CANSTCH = 0;
while (i) { // copy information to message buffer
*p++ = CANMSG;
i--;
}
CANCONCH = typ; // set channel for new receiving
return (0); // message object copied to buffer
}
/***** CAN I/O Routines for Remote Frame Handling **********************************/
/*
* CanReqRemote: Request Remote Frame
* Input Parameter: ch := message object channel (0 .. 14)
*
* Return Value: 0 n bytes of message transferred to data buffer
* -1 message object not defined for transmission
*
* - check if CAN message object is defined for transmission
* - set message object for remote frame request
*/
char CanReqRemote (unsigned char ch) {
unsigned char typ;
// check if CAN message object is defined for transmission
if (ch >= sizeof (id_typ)) return (-1);
typ = id_typ[ch];
if ((typ & CanCONCH) != CanTX) return (-1);
CANPAGE = CanChannel(ch); // select CAN message object
CANCONCH = 0; // reset previous status
CANSTCH = 0;
CANIDT4 |= CanRTRMSK; // Set Remote transmission request value
CANCONCH = typ; // set channel for transmission
return (0);
}
/*
* CanGetRemote: Get Data from Remote Frame Request
* Input Parameter: ch := message object channel (0 .. 14)
* p := pointer to data buffer
*
* Return Value: 0 n bytes of message transferred to data buffer
* -1 message object not defined for transmission
* -2 incoming message does not have expected length
* -3 no remote message received
*
* - check if CAN message object is defined for transmission
* - check if a message is received
* - copy received message to data buffer
*/
char CanGetRemote (unsigned char ch, unsigned char *p) {
unsigned char i, typ;
// check if CAN message object is defined for transmission
if (ch >= sizeof (id_typ)) return (-1);
typ = id_typ[ch];
if ((typ & CanCONCH) != CanTX) return (-1);
i = typ & 0xF; // message length
CANPAGE = CanChannel(ch); // select CAN message object
if (!(CANSTCH & CanRXOK)) {
return (-3); // no CAN message received
}
if (CANSTCH & CanDLCW) {
return (-2); // incoming message does not have expected length
}
CANCONCH = 0; // reset previous status
CANSTCH = 0;
while (i) { // copy information to message buffer
*p++ = CANMSG;
i--;
}
return (0); // message object copied to buffer
}
#pragma NOAREGS // function called from interrupt, no ARx symbols!
/*
* CanSetRemote:
* Input Parameter: ch := message object channel (0 .. 14)
* p := pointer to data buffer
*
* - check if CAN message object is defined for remote reply
* - Fil data buffer with data
*/
char CanSetRemote (unsigned char ch, unsigned char *p) {
unsigned char i, typ;
unsigned char save_canpage;
// check if CAN message object is defined for reception
if (ch >= sizeof (id_typ)) return (-1);
typ = id_typ[ch];
if ((typ & CanCONCH) != CanRX) return (-1);
i = typ & 0xF; // message length
save_canpage = CANPAGE; // Save the current CANPAGE (to work in parallel with polling mode)
CANPAGE = CanChannel(ch); // select CAN message object
CANCONCH &= ~CanRPLV; // reset information valid
while (i) { // copy information to message buffer
CANMSG = *p++;
i--;
}
CANCONCH |= CanRPLV; // set information valid
CANPAGE = save_canpage; // restore the old CAN page (required for polling mode)
return (0); // message object copied to buffer
}
#pragma AREGS
/***** Interrupt Driven CAN I/O Routines *************************************/
// definitions for transmit (output) buffer (CAN Message Object 2)
#define OLEN 16 // number of buffers in outbuf
unsigned char ostart = 0; // transmission buffer start index
unsigned char oend = 0; // transmission buffer end index
unsigned char xdata outbuf[OLEN][8]; // transmission buffer
bit tx_error; // set when transmit error occur
// definitions for receive (input) buffer (CAN Message Object 3)
#define ILEN 16 // number of buffers in inbuf
unsigned char istart = 0; // receive buffer start index
unsigned char iend = 0; // receive buffer end index
unsigned char xdata inbuf[ILEN][8]; // receive buffer
bit rx_error; // set when receive error occur
#pragma REGISTERBANK (1) // function called from Register Bank 1
/*
* Read Data into inbuf (for CAN channels handled by Interrupt
*/
static void ReadToInBuf (void) {
unsigned char i;
unsigned char xdata *p;
if (!(CANSTCH & CanRXOK)) {
rx_error = 1; // not a receive OK interrupt
}
CANCONCH = 0; // reset previous status
CANSTCH = 0;
p = inbuf[istart & (ILEN-1)];
istart++;
for (i = sizeof (inbuf[0]); i != 0; i--) { // copy information to message buffer
*p = CANMSG;
p++;
}
CANCONCH = ID3TYP; // set channel for new receiving
}
/*
* CanInterrupt:
* - called by hardware when a CAN message is send or received
* - checks if Channel 2 interrupt (transmission) occured
* - if new transmit data, copy new data to Channel 2 object buffers
* - checks if Channel 3 interrupt (receiving) occured
* - copy received data, copy data from Channel 3 object buffers
*/
void CanInterrupt (void) interrupt 7 using 1 {
unsigned char i;
unsigned char typ;
unsigned char save_canpage;
unsigned char xdata *p;
save_canpage = CANPAGE; // Save the current CANPAGE (to work in parallel with polling mode)
// Handle Interrupt for Transmit Channel 2
if (ID2IntChk) { // Check Channel 2 Interrupt (transmit buffer)
CANPAGE = CanChannel(2);
if (!(CANSTCH & CanTXOK)) {
tx_error = 1; // not a transmit OK interrupt
}
CANCONCH = 0; // reset previous status
CANSTCH = 0;
if (ostart != oend) {
p = outbuf[oend & (OLEN-1)];
oend++;
typ = id_typ[2];
i = typ & 0xF; // message length
while (i) { // copy information to message buffer
CANMSG = *p;
p++;
i--;
}
CANCONCH = typ; // send information
}
}
// Handle Interrupt for Receive Channel 3/4
if (ID4IntChk) { // Check if data are available in Channel 4
CANPAGE = CanChannel (4);
ReadToInBuf (); // Read Data into inbuf
}
if (ID3IntChk) { // Check if data are available in Channel 4
CANPAGE = CanChannel (3);
ReadToInBuf (); // Read Data into inbuf
}
CANPAGE = save_canpage; // restore the old CAN page (required for polling mode)
}
#pragma REGISTERBANK (0) // use Register Bank 0 for following code
/*
* CanSendIsr:
* Input Parameter: ch := message object channel (0 .. 14)
* p := pointer to data buffer
*
* Return Value: 0 n bytes of message transferred to data buffer
* -1 message object not defined for transmission
* -2 no message available
* -3 messsage data length differs from definition
*
* - check if CAN message object is defined for receiving
* - check if a message is received
* - copy received message to data buffer
* - set message object for receiving
*/
char CanSendIsr (unsigned char ch, unsigned char *p) {
unsigned char i, typ;
// check if CAN message object is defined for transmit
if (ch >= sizeof (id_typ)) return (-1);
typ = id_typ[ch];
if ((typ & CanCONCH) != CanTX) return (-1);
i = typ & 0xF; // message length
ECAN = 0; // disable CAN interupt
CANPAGE = CanChannel(ch); // select CAN message object
if ((CANCONCH & CanCONCH)) { // CAN channel busy?
// yes copy to interrupt buffer
memcpy (outbuf[ostart & (OLEN-1)], p, sizeof(outbuf[0]));
ostart++;
}
else { // not, transfer to message object
CANCONCH = 0; // reset previous status
CANSTCH = 0;
while (i) { // copy information to message buffer
CANMSG = *p++;
i--;
}
CANCONCH = typ; // send information
}
ECAN = 1; // enable CAN interupt
return (0);
}
/*
* CanReadIsr:
* Input Parameter: ch := message object channel (0 .. 14)
* p := pointer to data buffer
*
* Return Value: 0 n bytes of message transferred to data buffer
* -1 message object not defined for receiving
* -2 no data available
*
* - check if CAN message object is defined for receiving
* - check if a message is received
* - copy received message to data buffer
* - set message object for receiving
*/
char CanReadIsr (unsigned char ch, unsigned char *p) {
unsigned char i, typ;
// check if CAN message object is defined for transmit
if (ch >= sizeof (id_typ)) return (-1);
typ = id_typ[ch];
if ((typ & CanCONCH) != CanTX) return (-1);
i = typ & 0xF; // message length
if (istart == iend) return (-2);
memcpy (p, inbuf[iend & (ILEN-1)], i);
iend++;
return (0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -