⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can1.c

📁 this application program demonstrate programming and simulation of the on-chip CAN (controller area
💻 C
📖 第 1 页 / 共 2 页
字号:
 *                     -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 + -