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

📄 drv_can.c

📁 CAN开发例子
💻 C
📖 第 1 页 / 共 2 页
字号:
 *	Enqueue a client packet object into the RS task queue.
 *
 *	Once placed in queue, client must not modify the data
 *	otherwise unpredictable results. To safely change the object,
 *	dequeue, modify, re-enqueue.
 *
 *  The code in mainly executed in critical region [SuspendAllInterrupt]
 *  because many tasks can call this function at the same time and break
 *  the FIFO list.
 *
 *	Returns 1 if successfull, 0 if message could not be enqueued
 **********************************************************************/
StatusType CAN_enqMsg(CAN_message_tRef toEnqueue)
{
  CAN_message_tRef CAN_list_itor;

  if (toEnqueue != NULL)
  {
    SuspendAllInterrupts();
    if (CAN_list_head == NULL)
      CAN_list_head = toEnqueue;
    else
    {
      CAN_list_itor = CAN_list_head;
      while (CAN_list_itor->next != NULL)
        CAN_list_itor = CAN_list_itor->next;
      CAN_list_itor->next = toEnqueue;
    }
    toEnqueue->next     = NULL;
    toEnqueue->CallerID = id_tsk_run;
    toEnqueue->state    = CAN_FULL;
    CAN_list_count++;
    ResumeAllInterrupts();
    return E_OK;
  }
  else
    return E_OS_STATE;
}

/**********************************************************************
 *	Dequeue a client message from the RS task queue.
 *
 *
 *********************************************************************/
CAN_message_tRef CAN_deqMsg(void)
{
  CAN_message_tRef CAN_list_itor;

  SuspendAllInterrupts();
  CAN_list_itor = NULL;
  if (CAN_list_head != NULL)
  {
    CAN_list_itor = CAN_list_head;
    CAN_list_head = CAN_list_head->next;
    CAN_list_count--;
  }
  ResumeAllInterrupts();
  return CAN_list_itor;
} 

/**********************************************************************
 * Called by the CAN driver task.
 * Check the RXFUL bit of the both RX CAN hardware buffers.
 * If at least one message is store in hardware then this function
 * tries to tranfer the data from hardware to dedicated structure
 * (structure created by other tasks).
 *
 * @param void        
 * @return Status    Always return E_OK
 **********************************************************************/
StatusType ReadCANBuffer(void)
{
  if (PIR3bits.RXB0IF == 1)
  {
    CANCONbits.WIN2 = 1; 
    CANCONbits.WIN1 = 1; 
    CANCONbits.WIN0 = 0;
    if (CopyHard2FrameBuffer() == E_OK)
    {
      RXB0CONbits.RXFUL = 0;
      PIR3bits.RXB0IF    = 0;
      PIE3bits.RXB0IE   = 1;
    }
  }
  if (PIR3bits.RXB1IF == 1)
  {
    CANCONbits.WIN2 = 1; 
    CANCONbits.WIN1 = 0; 
    CANCONbits.WIN0 = 1;
    if (CopyHard2FrameBuffer() == E_OK)
    {
      RXB0CONbits.RXFUL = 0;
      PIR3bits.RXB1IF    = 0;
      PIE3bits.RXB1IE   = 1;
    }
  }
  
  return(E_OK);
}

/**********************************************************************
 *	Enqueue a client packet object into the RS task queue.
 *
 *	Once placed in queue, client must not modify the data
 *	otherwise unpredictable results. To safely change the object,
 *	dequeue, modify, re-enqueue.
 *
 *  The code in mainly executed in critical region [SuspendAllInterrupt]
 *  because many tasks can call this function at the same time and break
 *  the FIFO list.
 *
 *	Returns 1 if successfull, 0 if message could not be enqueued
 **********************************************************************/
StatusType CAN_RCV_Register(CAN_message_tRef toEnqueue)
{
  CAN_message_tRef CAN_list_itor;

  if (toEnqueue != NULL)
  {
    SuspendAllInterrupts();
    if (CAN_list_head_rcv == NULL)
      CAN_list_head_rcv = toEnqueue;
    else
    {
      CAN_list_itor = CAN_list_head_rcv;
      while (CAN_list_itor->next != NULL)
        CAN_list_itor = CAN_list_itor->next;
      CAN_list_itor->next = toEnqueue;
    }
    toEnqueue->next     = NULL;
    toEnqueue->CallerID = id_tsk_run;
    CAN_list_count_rcv++;
    ResumeAllInterrupts();
    return E_OK;
  }
  else
    return E_OS_STATE;
}

/**********************************************************************
 * Parse the entier RX message list to find any task waiting for the 
 * received message ID.
 * Once a such taks is found we post an event to the waiting task
 * to tell its software buffer is full and we break.
 * The event is used if the task want to wait for a particular message
 * ID without overloading the CPU by a pooling method.
 *
 * @param  type    IN Number of the hardware buffer      
 * @return Status     E_OK if tranfer initiated
 *                    E_OS_STATE otherwise
 **********************************************************************/
StatusType CopyHard2FrameBuffer(void)
{
  StatusType returned_type;
  CAN_message_tRef CAN_list_itor;

  returned_type = E_OK;

  if (CAN_list_head_rcv != NULL)
  {
    CAN_list_itor = CAN_list_head_rcv;
    do
    {
      #ifdef __NOFILTER__
      if (1)
      #else
      if (CAN_list_itor->SIDH == RXB0SIDH)
      #endif
      {
        if (CAN_list_itor->state == CAN_FREE)
        {
          CAN_list_itor->SIDH    = RXB0SIDH;
          CAN_list_itor->data[0] = RXB0D0;
          CAN_list_itor->data[1] = RXB0D1;
          CAN_list_itor->data[2] = RXB0D2;
          CAN_list_itor->data[3] = RXB0D3;
          CAN_list_itor->data[4] = RXB0D4;
          CAN_list_itor->data[5] = RXB0D5;
          CAN_list_itor->data[6] = RXB0D6;
          CAN_list_itor->data[7] = RXB0D7;
          CAN_list_itor->length  = RXB0DLC & 0x0F;
          CAN_list_itor->state   = CAN_FULL;
          SetEvent(CAN_list_itor->CallerID, CAN_QUEUE_FULL);  
        }
        else
          returned_type = E_OS_STATE; 
      }
      CAN_list_itor = CAN_list_itor->next;
    }
    while (CAN_list_itor != NULL);
  }

  return(returned_type);
}

/**********************************************************************
 * ISR of the CAN driver.
 * 
 * For each interrupt we disable the IE first to avoid any infinite loop
 * and we clear the IF in the dedicated function (Read or Write CAN mess).
 * Indeed we have to clear the IT when the message has been properly 
 * accessed and is no more used. The IF lets the peripheral accept a new 
 * message.  
 * If 3 frames arrive at the same time, the two first are stored in the 
 * RCV buffers and the third is discarded (temporary overload bus).
 *
 * @return void 
 **********************************************************************/
void CAN_INT(void)
{
  if (PIR3 & 0x03)
  { 
    if (PIR3bits.RXB0IF)
      PIE3bits.RXB0IE = 0;
    if (PIR3bits.RXB1IF)
      PIE3bits.RXB1IE = 0;
    SetEvent(CAN_DRV_ID, CAN_RCV_MSG);
  };
  
  if (PIR3 & 0x1C)
  {
    if (PIR3bits.TXB0IF)
      PIE3bits.TXB0IE = 0;
    if (PIR3bits.TXB1IF)
      PIE3bits.TXB1IE = 0;
    if (PIR3bits.TXB2IF)
      PIE3bits.TXB2IE = 0;
    SetEvent(CAN_DRV_ID, CAN_NEW_MSG);
  }
    
  if (PIR3 & 0xE0)
  {
    if (PIR3bits.WAKIF)
      PIR3bits.WAKIF = 0;
    if (PIR3bits.ERRIF)
    {
      COMSTATbits.RXB0OVFL = 0;
      COMSTATbits.RXB1OVFL = 0;
      PIR3bits.ERRIF = 0;
    }
    if (PIR3bits.IRXIF)
      PIR3bits.IRXIF = 0;
    SetEvent(CAN_DRV_ID, CAN_ERR_MSG);
  }
}

/* End of File : drv_can.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -