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

📄 drv_can.c

📁 picos18的can驱动样例程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/**********************************************************************/
/*                                                                    */
/* File name: drv_can.c                                               */
/*                                                                    */
/* Since:     2005-Jan-19                                             */
/*                                                                    */
/* Version:   PICos18 v2.05                                           */
/*            Copyright (C) 2003, 2004, 2005 Pragmatec.               */
/*            CAN driver v1.05                                        */
/*                                                                    */
/* Author:    Designed by Pragmatec S.A.R.L.        www.pragmatec.net */
/*            MONTAGNE Xavier [XM]      xavier.montagne@pragmatec.net */
/*            ROZIER Bertrand [RZR]     bertrand.rozier@pragmatec.net */
/*                                                                    */
/* Purpose:   PIC18 CAN peripheral management.                        */
/*            It allows task tosend data at the send time through a   */
/*            dedicated FIFO, and to wait for a certain CAN frame.    */ 
/*                                                                    */
/* Distribution: This file is part of PICos18.                        */
/*            PICos18 is free software; you can redistribute it       */
/*            and/or modify it under the terms of the GNU General     */
/*            Public License as published by the Free Software        */
/*            Foundation; either version 2, or (at your option)       */
/*            any later version.                                      */
/*                                                                    */
/*            PICos18 is distributed in the hope that it will be      */
/*            useful, but WITHOUT ANY WARRANTY; without even the      */
/*            implied warranty of MERCHANTABILITY or FITNESS FOR A    */
/*            PARTICULAR PURPOSE.  See the GNU General Public         */
/*            License for more details.                               */
/*                                                                    */
/*            You should have received a copy of the GNU General      */
/*            Public License along with gpsim; see the file           */
/*            COPYING.txt. If not, write to the Free Software         */
/*            Foundation, 59 Temple Place - Suite 330,                */
/*            Boston, MA 02111-1307, USA.                             */
/*                                                                    */
/*          > A special exception to the GPL can be applied should    */
/*            you wish to distribute a combined work that includes    */
/*            PICos18, without being obliged to provide the source    */
/*            code for any proprietary components.                    */
/*                                                                    */
/* History:                                                           */
/* 2005/01/19 [XM]  Create this file.                                 */
/* 2005/01/31 [XM]  Added reception buffer overflow management.       */
/*                  If an overflow occurs, new messages are discarded.*/
/* 2006/03/03 [RZR] Add Pre-defined BaudRate selection                */
/*                  Correct TX buffer allocation bug                  */
/* 2006/04/17 [RZR] Fixed bug ln 335 in CopyFrameBuffer2Hard (29 bits)*/
/*                                                                    */
/**********************************************************************/

#include "define.h"
#include "drv_can.h"

///////////////////////////////////////////////////////////////////////////////
//
//	OSCILLATOR	SPEED
//
#define	DEFAULT_CANSPEED		5
#define	OSCILATOR_FREQ			40

/*******************************************************************************
   CAN Baud rate setup table.
   Thanks Janez :-)
*******************************************************************************/

rom struct{    
   unsigned char  BRP;			//(1...64) Baud Rate Prescaler 
   unsigned char  SJW;			//(1...4) SJW time
   unsigned char  PROP;			//(1...8) PROP time
   unsigned char  PhSeg1;		//(1...8) Phase Segment 1 time
   unsigned char  PhSeg2;		//(1...8) Phase Segment 2 time
//   BRP,SJW,PROP,PH1,PH1
}

CO_BitRateData[8] = 
#if OSCILATOR_FREQ == 16
//   BRP,SJW,PROP,PH1,PH1
   {50,  1, 4, 8, 3, 			//CAN=10kbps
    25,  1, 4, 8, 3, 			//CAN=20kbps
    10,  1, 4, 8, 3, 			//CAN=50kbps
    4,   1, 4, 8, 3, 			//CAN=125kbps
    2,   1, 4, 8, 3, 			//CAN=250kbps
    1,   1, 4, 8, 3, 			//CAN=500kbps
    1,   1, 2, 4, 3, 			//CAN=800kbps
    1,   1, 2, 3, 2};			//CAN=1000kbps
#elif OSCILATOR_FREQ == 20
//   BRP,SJW,PROP,PH1,PH1
   {50,  1, 6, 8, 5, 			//CAN=10kbps
    25,  1, 6, 8, 5, 			//CAN=20kbps
    10,  1, 6, 8, 5, 			//CAN=50kbps
    5,   1, 4, 8, 3, 			//CAN=125kbps
    2,   1, 6, 8, 5, 			//CAN=250kbps
    1,   1, 6, 8, 5, 			//CAN=500kbps
    1,   1, 3, 5, 3, 			//CAN=800kbps     //combination does not work
    1,   1, 2, 4, 3};			//CAN=1000kbps
#elif OSCILATOR_FREQ == 32
//   BRP,SJW,PROP,PH1,PH1
   {64,  1, 8, 8, 8, 			//CAN=10kbps
    50,  1, 4, 8, 3, 			//CAN=20kbps
    20,  1, 4, 8, 3, 			//CAN=50kbps
    8,   1, 4, 8, 3, 			//CAN=125kbps
    4,   1, 4, 8, 3, 			//CAN=250kbps
    2,   1, 4, 8, 3, 			//CAN=500kbps
    2,   1, 2, 4, 3, 			//CAN=800kbps
    2,   1, 2, 3, 2};			//CAN=1000kbps
#elif OSCILATOR_FREQ == 40
//   BRP,	SJW,	PROP,	PH1,	PH1
   {64,  4, 8, 8, 8, 			//CAN=10kbps      //combination does not work
    50,  1, 6, 8, 5, 			//CAN=20kbps
    25,  1, 4, 8, 3, 			//CAN=50kbps
    8,   2, 6, 8, 8, 			//CAN=125kbps	//	DD
    4,   2, 7, 8, 4, 			//CAN=250kbps	//	DD
    2,   2, 7, 8, 4, 			//CAN=500kbps	//	DD
    0,   0, 0, 0, 0, 			//CAN=800kbps
    0,   0, 0, 0, 0};			//CAN=1000kbps
#else
   #error define_OSCILATOR_FREQ OSCILATOR_FREQ not supported
#endif

/**********************************************************************
 * Definition dedicated to the local functions.
 **********************************************************************/
EventMaskType   	CAN_event;

CAN_message_tRef	CAN_list_head;			//	Start of message queue
CAN_message_tRef	CAN_current_message;	//	Current message
unsigned char		CAN_list_count = 0;		//	Number of items currently in queue

CAN_message_tRef	CAN_list_head_rcv;		//	Start of message queue
CAN_message_tRef	CAN_current_message_rcv;//	Current message
unsigned char		CAN_list_count_rcv = 0;	//	Number of items currently in queue

unsigned char BaudRate;

/**********************************************************************
 * Task of the CAN driver, waiting for any of these 4 events :
 *  CAN_NEW_MSG   : A message has been sent then a hardware transmitter
 *                  is free. The driver will tranfer a software buffer
 *                  into a free TX[0,1,2] hardware buffer.
 *  CAN_RCV_MSG   : A message is arrived in the RX[0,1] buffer.
 *                  the driver transfer the content of the message into
 *                  a software buffer waiting for this message ID or
 *                  discard the message to free the hardware.
 *  CAN_ERR_MSG   : Something wrong appended and the driver must clean
 *                  the hardware before being disconnected. To be
 *                  completed...
 *
 * @param  void     
 * @return void   
 **********************************************************************/
TASK(CAN_Drv)
{
  // Determine CAN bus Speed
  CAN_FindSpeed(&BaudRate);
  CAN_config();

  while(1)
  {
    WaitEvent(CAN_NEW_MSG | CAN_RCV_MSG | CAN_ERR_MSG);
    GetEvent(CAN_DRV_ID, &CAN_event);        

    if (CAN_event & CAN_NEW_MSG)
    {
      ClearEvent(CAN_NEW_MSG);
      WriteCANBuffer();      
    }
    
    if (CAN_event & CAN_RCV_MSG)
    {
      ClearEvent(CAN_RCV_MSG);
      ReadCANBuffer();      
    }
    
    if (CAN_event & CAN_ERR_MSG)
    {
      ClearEvent(CAN_ERR_MSG);
    }
  }
}
 
/**********************************************************************
 * Hardware settings of the CAN port.
 *
 * @param  void     
 * @return void   
 **********************************************************************/
void CAN_config(void)
{
  CANCON   = 0x80;
  TRISBbits.TRISB2 = 0;
  TRISBbits.TRISB3 = 1;
  
  CAN_SetSpeed(BaudRate);

  CIOCON   = 0x20;
  PIE3     = 0xE3;/* All RX and Err without TX enabled */
  IPR3     = 0x00;
  RXM0SIDL = 0;
  RXM0SIDH = 0;
  RXM0EIDL = 0x00;
  RXM0EIDH = 0x00;
  RXF0SIDL = 0x00;
  RXF0SIDH = 0x00;
  RXF0EIDL = 0x00;
  RXF0EIDH = 0x00;
  RXB0CON  = 0x64; /* 0x24 for STD ID, 0x64 for EXT ID */
  TXB0CON  = 0x00;
  #ifdef __LOOPBACK__
  CANCON   = 0x40;
  #else
  CANCON   = 0x00;
  #endif

  /* Settings for the first frame to send */
  PIE3bits.TXB0IE = 0;

  /* Init the different FIFO */
  CAN_current_message = NULL;
  CAN_list_head       = NULL;
  CAN_list_head_rcv   = NULL;
}


/**********************************************************************
 * Called by the CAN driver task.
 * Function is incomplete now, finish later.
 * For now, just return OK and continue...
 *
 * @param  void        
 * @return Status    Always return E_OK
 **********************************************************************/
StatusType CAN_FindSpeed(unsigned char * speed)
{
	*speed = DEFAULT_CANSPEED;		//	Set to default
	return E_OK;
}


/**********************************************************************
 * Sets the various baud rate registers based upon the CO_BitRateData table..
 *
 * @param  void        
 * @return Status    Always return E_OK
 **********************************************************************/
StatusType CAN_SetSpeed(char speed)
{
	
	if ((speed > 7) || (speed < 0))
		return E_OS_STATE ;
		
	//	Prescaler in lower 6 bits; bits 5:0.  BRP as coded, begins at 1, so
	//	you must subtract 1 to convert	
	BRGCON1 = CO_BitRateData[speed].BRP -1;	
	
	//	Set the syncronizaiton jump width
	BRGCON1 += (CO_BitRateData[speed].SJW -1)<< 6;
	
	//	Propigation in lower 3 bits, 2:0
	BRGCON2 = CO_BitRateData[speed].PROP - 1;
	
	//	Located bits 5:3		
	BRGCON2 += (CO_BitRateData[speed].PhSeg1 -1) << 3;
	
	BRGCON2bits.SEG2PHTS = 1;	
	
	//	Set phase 2 segment time
	BRGCON3 = CO_BitRateData[speed].PhSeg2 -1;
	
	return E_OK;
}


/**********************************************************************
 * Called by the CAN driver task.
 * Call the CopyFrmaeBuffer2Hard 3 times, one for each TX buffer.
 * Indeed the 3 buffers could be free then we have to take our chance 
 * to send 3 waiting frames at the same time.
 *
 * @param  void        
 * @return Status    Always return E_OK
 **********************************************************************/
StatusType WriteCANBuffer(void)
{
	pTXBUF_t	txBuf;

	while (CAN_list_count)
	{
		// Find an empty buffer
			txBuf = TXBUF_START;
			while (((txBuf->TXCON & TXCON_EMPTY) != 0) &&
			(txBuf >=TXBUF_END)){
				txBuf--;
			}

	//	If we reached the end before finding an empty, return immed.	
	if (txBuf < TXBUF_END)
		return E_OS_STATE;

	CopyFrameBuffer2Hard(txBuf);
    }

  return(E_OK);
}

/**********************************************************************
 * Parse the entier TX message list to find any message to transfer.
 * Once a such message is found we post an event to the sending task
 * to tell the transfer is started and we break.
 * The event is used if the task want to send as fast as possible a 
 * set of message. Doing so the task will be able to send a new message
 * every time a TASK_CAN_TX_EVENT event is received.
 *
 * @param  type    IN Number of the hardware buffer      

⌨️ 快捷键说明

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