📄 can1.c
字号:
* -2 no message 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
*/
int CAN1Read(unsigned int ch, void *p) {
unsigned char typ;
if (ch >= sizeof (id_typ)) return (-1); // channel not defined
typ = id_typ[ch];
if ((typ & DIR_MASK) != CanRX) return (-1); // channel is not a receiving channel
if (!(C1MOBJ[ch].msg_ctl & NEWDAT_)) return (-2); // no new data available
memcpy (p, C1MOBJ[ch].msg, (typ >> 4)); // copy new data to buffer
C1MOBJ[ch].msg_ctl = NEWDAT_CLR;
return 0;
}
/***** CAN I/O Routines for Remote Frame Handling **********************************/
/*
* CAN1ReqRemote: Request Remote Frame
* Input Parameter: ch := message object channel (1 .. 15)
*
* Return Value: 0 n bytes of message transferred to data buffer
* -1 message object not defined for receiving
*
* - check if CAN message object is defined for receiving
* - set message object for remote frame request
*
* Note: To read the data use the function CAN1Read
*/
int CAN1ReqRemote (unsigned int ch) {
unsigned char typ;
if (ch >= sizeof (id_typ)) return (-1); // channel not defined
typ = id_typ[ch];
if ((typ & DIR_MASK) != CanRX) return (-1); // channel is not a receiving channel
C1MOBJ[ch].msg_ctl = TXRQ_SET & NEWDAT_CLR;
return 0;
}
/*
* CanSetRemote:
* Input Parameter: ch := message object channel (1 .. 15)
* p := pointer to data buffer
*
* - check if CAN message object is defined for transmission
* - Fill data buffer with data
*/
int CAN1SetRemote(unsigned int ch, void *p) {
unsigned char typ;
if (ch >= sizeof (id_typ)) return (-1); // channel not defined
typ = id_typ[ch];
if (!(typ & DIR_MASK)) return (-1); // channel is not a transmission channel
C1MOBJ[ch].msg_ctl = NEWDAT_CLR & MSGVAL_CLR;
memcpy (C1MOBJ[ch].msg, p, (typ >> 4));
C1MOBJ[ch].msg_ctl = NEWDAT_SET & MSGVAL_SET;
return 0;
}
/***** 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 outbuf[OLEN][8]; // transmission buffer
// 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 inbuf[ILEN][8]; // receive buffer
/*
* CanInterrupt:
* - called by hardware when a CAN message is send or received
* - checks if Channel 3 interrupt (transmission) occured
* - if new transmit data, copy new data to Channel 3 object buffers
* - checks if Channel 4 interrupt (receiving) occured
* - copy received data, copy data from Channel 4 object buffers
*/
void CAN1Interrupt (void) interrupt 0x40 using CAN_INTREGS {
unsigned char IntID;
unsigned int Status;
while (IntID = C1IR) {
switch (IntID) {
case 1: // Status Change Interrupt
// The CAN controller has updated (not necessarily changed)
// the status in the Control Register.
Status = C1CSR;
if (Status & 0x8000) // if BOFF
{
// Indicates when the CAN controller is in busoff state.
}
if (Status & 0x4000) // if EWRN
{
}
if (Status & 0x0800) // if TXOK
{
Status &= 0xf7ff;
C1CSR = Status; // reset TXOK
}
if (Status & 0x1000) // if RXOK
{
// Indicates that a message has been received successfully.
Status &= 0xefff;
C1CSR = Status; // reset RXOK
}
if (Status & 0x0700) // if LEC
{
}
break;
case 2: // Message Object 15 Interrupt
if ((C1MOBJ[15].msg_ctl & 0x0c00) == 0x0800) // if MSGLST set
{
// Indicates that the CAN controller has stored a new
// message into object 15, while NEWDAT was still set,
// ie. the previously stored message is lost.
C1MOBJ[15].msg_ctl = 0xf7ff; // reset MSGLST
}
C1MOBJ[15].msg_ctl = 0x7dfd; // release buffer
break;
case 2+3: // Handle Interrupt for Transmit Channel 3
C1MOBJ[3].msg_ctl = INTPND_CLR; // Clear Interrupt Pending flag
if (ostart != oend) {
if (CAN1Send (3, outbuf[oend & (OLEN-1)]) == 0) {
oend++;
}
}
break;
case 2+4: // Handle Interrupt for Receive Channel 4
if (CAN1Read (4, inbuf[istart & (ILEN-1)]) == 0) {
istart++;
}
C1MOBJ[4].msg_ctl = INTPND_CLR; // Clear Interrupt Pending flag
break;
default: // Clear any unexpected interrupt pending flag
C1MOBJ[IntID-2].msg_ctl = INTPND_CLR;
break;
}
}
}
/*
* Can1SendIsr:
* 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
*
* - 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
*/
int CAN1SendIsr (unsigned int ch, void *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];
i = (typ >>4); // message length
C1CSR &= ~CAN_IE_; // disable CAN interupt
_nop_ (); // avoid pipeline effects
_nop_ ();
if ((oend != ostart) ||
(C1MOBJ[ch].msg_ctl & TXRQ_)) { // CAN channel busy?
// yes copy to interrupt buffer
memcpy (outbuf[ostart & (OLEN-1)], p, sizeof(outbuf[0]));
ostart++;
}
else { // not,
CAN1Send (3, p); // transfer directly to message object
}
C1CSR |= CAN_IE_; // enable CAN interupt
return (0);
}
/*
* Can1ReadIsr:
* 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
*/
int CAN1ReadIsr (unsigned int ch, void *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];
i = (typ >>4); // 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 + -