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

📄 candrv.c

📁 vxWorks下的can总线驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
/* CANDrv.c - MC523x Flexcan communication driver */

/*  Copyright 2005 ZHUHAI UNITECH POWER TECHNOLOGY CO.,LTD  */

/*
modification history
--------------------
*/

/*
DESCRIPTION
This is the driver for the Flexcan contained in the 523X.
*/
#include "vxWorks.h"
#include "iosLib.h"
#include "intLib.h"
#include "errno.h"
#include "CANDrv.h"
#include "string.h"

int Tx_count;
int Rx_count;

int CanDrvNum  = 0; 

Tx_count=0;
Rx_count=0;

Can_DEV can_chan_dev[NUM_CAN];

LOCAL STATUS InitCan(Can_DEV *);
LOCAL STATUS WriteByte(Can_DEV *,UCHAR ,int );
LOCAL STATUS CanBaudSet (Can_DEV *, UINT);
LOCAL STATUS CanTxIDSet (Can_DEV *,UINT);
LOCAL STATUS CanRxIDSet (Can_DEV *,UINT);
LOCAL STATUS CheckBusStatus(Can_DEV *);
LOCAL void CanTxInterrupt (Can_DEV *);
LOCAL void CanRxInterrupt (Can_DEV *);

/******************************************************************************
*CanDrv  --  CAN驱动安装程序
*返回 - 安装成功返回OK,否则返回ERROR
*参数:无
******************************************************************************/
STATUS CanDrv(void)
{
	if(CanDrvNum > 0)
	{
		printf("Can driver has been installed!\n");
		return OK;//已经安装驱动
	}

	if((CanDrvNum = iosDrvInstall(0,0,CanOpen,CanClose,CanRead,CanWrite,CanIoctl)) == ERROR)
	{
		printf("Can driver install ERROR!\n");
		return ERROR;
	}
#if NUM_CAN == 2
	intConnect(INUM_TO_IVEC(CAN0_MB0_INTVEC),Can0TxInterrupt,0);
	intConnect(INUM_TO_IVEC(CAN0_MB1_INTVEC),Can0RxInterrupt,0);
	intConnect(INUM_TO_IVEC(CAN1_MB0_INTVEC),Can1TxInterrupt,0);
	intConnect(INUM_TO_IVEC(CAN1_MB1_INTVEC),Can1RxInterrupt,0);
	
#else
	intConnect(INUM_TO_IVEC(CAN0_MB0_INTVEC),Can0TxInterrupt,0);
	intConnect(INUM_TO_IVEC(CAN0_MB1_INTVEC),Can0RxInterrupt,0);	
#endif

	printf("Can driver has been installed successfully !\n");
	return OK;
}

/******************************************************************************
*itos  --  将一个整数转换为字符
*返回 - 转换后的字符串指针
*参数:val -- 要转换的整数
******************************************************************************/

static char * itos (int val)
{
    static char str [20];
    char strtmp [20];
    str [0] = '\0';

    if (val == 0)
	return "0";

    while (val != 0)
	{
	strcpy (strtmp, str);
	str[0] = '0' + (val % 10);
	str[1] = '\0';
	strcat (str, strtmp);
	val = val - (val %= 10);
	}

    return str;
}

/******************************************************************************
*CanDevCreate  --  CAN设备创建函数
*返回 - 创建成功返回OK,否则返回ERROR
*参数:无
*
******************************************************************************/

STATUS CanDevCreate()
{
	char canName[20];
	int i;
	if(CanDrvNum == 0)
	{
		return ERROR;
	}

	for(i=0;i<NUM_CAN;i++)
	{
		canName[0] = '\0';
		strcat (canName, CAN_NAME_BASE);
	    strcat (canName, itos (i));
		if(iosDevAdd((DEV_HDR *)&can_chan_dev[i],canName,CanDrvNum) == ERROR)
		{
			printf("Can device add ERROR !\n");
			return ERROR;
		}
	}
	return OK;
}


/******************************************************************************
*CanOpen  --  打开CAN设备
*返回 - 返回设备ID号
*参数:pCan_Dev   --  要打开的CAN设备
       remainder  --  文件名,在这里为空
	   flags      --  设备的打开方式,对于can永远以读写方式打开
*
******************************************************************************/

int CanOpen(Can_DEV *pCan_Dev,UCHAR *remainder,int flags)
{
	if(flags != 2)
	{
		printf("Can device open ERROR !\n");
		return ERROR;/*只能以读写的方式打开*/
	}
	if(remainder[0] != 0)
	{
		printf("Can device open ERROR !\n");
		return ERROR;/*can设备没有文件名*/
	}
	pCan_Dev->Flag_canOpen = CAN_YES; /*打开CAN设备*/

	/*使MB0和MB1不参与仲裁与配匹*/
    CANDEV_WRITE(pCan_Dev->txcode,
		TX_NOTENABLE | DEFAULT_LENGTH);
	CANDEV_WRITE(pCan_Dev->rxcode,
		RX_NOTENABLE | DEFAULT_LENGTH);
	/*清除发送缓冲区数据*/
	CANDEV_WRITE(pCan_Dev->txdata0,0x00);
	CANDEV_WRITE(pCan_Dev->txdata1,0x00);
	CANDEV_WRITE(pCan_Dev->txdata2,0x00);
	CANDEV_WRITE(pCan_Dev->txdata3,0x00);
	CANDEV_WRITE(pCan_Dev->txdata4,0x00);
	CANDEV_WRITE(pCan_Dev->txdata5,0x00);
	CANDEV_WRITE(pCan_Dev->txdata6,0x00);
	CANDEV_WRITE(pCan_Dev->txdata7,0x00);

	/*清除接收缓冲区数据*/
	CANDEV_WRITE(pCan_Dev->rxdata0,0x00);
	CANDEV_WRITE(pCan_Dev->rxdata1,0x00);
	CANDEV_WRITE(pCan_Dev->rxdata2,0x00);
	CANDEV_WRITE(pCan_Dev->rxdata3,0x00);
	CANDEV_WRITE(pCan_Dev->rxdata4,0x00);
	CANDEV_WRITE(pCan_Dev->rxdata5,0x00);
	CANDEV_WRITE(pCan_Dev->rxdata6,0x00);
	CANDEV_WRITE(pCan_Dev->rxdata7,0x00);

	/*接收使能*/
	CANDEV_WRITE(pCan_Dev->rxcode,
		RX_ENABLE | DEFAULT_LENGTH);

	printf("Can device has been opened !\n");
	return((int)pCan_Dev);


}

/******************************************************************************
*CanOpen  --  关闭CAN设备
*返回 - 无
*参数:pCan_Dev   --  要关闭的CAN设备
*
******************************************************************************/

int CanClose(Can_DEV *pCan_Dev)
{
	if(pCan_Dev->Flag_canOpen == CAN_NO)
	{
		printf("Can device has been closed !\n");
		return OK;
	}
	
	pCan_Dev->Flag_canOpen = CAN_NO; /*关闭CAN设备*/

	CANDEV_WRITE(pCan_Dev->txcode,
		TX_NOTENABLE | DEFAULT_LENGTH);
	CANDEV_WRITE(pCan_Dev->rxcode,
		RX_NOTENABLE | DEFAULT_LENGTH);
	/*初始化发送缓冲区指针及发送计数器*/
	pCan_Dev->ptx = pCan_Dev->tx_Buff;
	pCan_Dev->tx_number = 0;
	pCan_Dev->tx_length =0;

		/*初始化接收缓冲区指针及接收计数器*/
	pCan_Dev->prx_write = pCan_Dev->rx_Buff;
	pCan_Dev->prx_read = pCan_Dev->rx_Buff;
	pCan_Dev->rx_number = 0;
	pCan_Dev->rx_length = 0;

		
	printf("Can device has been closed !\n");
	return OK;

}
/******************************************************************************
*
* CanWrite  --   CAN发送函数
* 返回: 成功返回已写入的字节数, 否则返回0
*参数说明:
         pChan    --   需要控制的设备
         buffer   --   写缓冲区
         someArg  --   写字节数
******************************************************************************/

int CanWrite(Can_DEV *pCan_Dev,UCHAR *buffer,UINT16 nBytes)
{
	int i;
	int j;
	UCHAR *txbuf;
	txbuf = buffer;
	if(pCan_Dev->Flag_canOpen == CAN_NO) 
	{
		printf("Can device hasn't been opened !\n");
		return 0;/*如果设备没有打开返回0*/
	}
	if(nBytes > MAX_TX_BUFFER)
	{
		printf("要发送的字节数大于发送缓冲区长度 !\n");
		return 0; /*要发送的字节数大于发送缓冲区*/
	}

	/*
	if( ERROR == semTake(pCan_Dev->tx_semSync, 50) )
	{
		printf("Cann't Take The TX Sem.\n\r");
		return 0;
	}
    */

	//semTake(pCan_Dev->tx_semSync,WAIT_FOREVER);/*等待发送中断释放信号量*/
	/*如果需发送的字节数小于或等于8,不用复制到设备的发送缓冲区中,直接发送
	否则将所有数据复制到设备缓冲区中,先发送前8个字节,剩余的在设备的缓冲区中用中断发送*/
	if(nBytes <= 8)
	{
		j = 0;
		while(CheckBusStatus(pCan_Dev) != OK) //检查CAN总线是否在空闲状态
		{
			j++;
			if(j >= 40000) break;
		}
		if(j >= 40000) 
		{

			printf("Can bus is always busy !\n");
			return 0;//总线一直忙
		}

		CANDEV_WRITE(pCan_Dev->txcode,   /*INACTIVE发送*/
			TX_NOTENABLE);
		for(i=0;i<nBytes;i++)
		{
			WriteByte(pCan_Dev,*txbuf,i);
			txbuf++;
		}
		pCan_Dev->tx_number = 0;
		pCan_Dev->tx_length = nBytes;
		pCan_Dev->ptx = pCan_Dev->tx_Buff;
		CANDEV_WRITE(pCan_Dev->txcode,   /*ACTIVE发送*/
			TX_ENABLE | pCan_Dev->tx_length);
		printf("Has been transmitted!\n");

	}
	else
	{
		/*复制数据到设备的发送缓冲区中*/
		for(i = 0;i < nBytes;i++,txbuf++)
		{
			pCan_Dev->tx_Buff[i] = *txbuf;
		}

		pCan_Dev->ptx = pCan_Dev->tx_Buff;
		pCan_Dev->ptx += 8;/*发送指针往后移8个字节*/
		pCan_Dev->tx_number = nBytes -8;
		pCan_Dev->tx_length = 8;

		j = 0;
		while(CheckBusStatus(pCan_Dev) != OK) //检查CAN总线是否在空闲状态
		{
			j++;
			if(j >= 40000) break;
		}
		if(j >= 40000)
		{
			pCan_Dev->ptx = pCan_Dev->tx_Buff;
			pCan_Dev->tx_number = 0;
			pCan_Dev->tx_length = 0;
			printf("Can bus is always busy !\n");
			return 0;//总线一直忙
		}

		CANDEV_WRITE(pCan_Dev->txcode,   /*INACTIVE发送*/
			TX_NOTENABLE);
		txbuf = buffer;
		for(i=0;i<8;i++)
		{
			WriteByte(pCan_Dev,*txbuf,i);
			txbuf++;
		}
		CANDEV_WRITE(pCan_Dev->txcode,   /*ACTIVE发送*/
			TX_ENABLE | pCan_Dev->tx_length);
		printf("Has been transmitted!\n");
	}
	return nBytes;


}
/******************************************************************************
*
* CanRead  --   CAN接收函数
* 返回: 成功返回已读的字节数, 否则返回0
*参数说明:
         pChan    --   需要控制的设备
         buffer   --   读缓冲区
         someArg  --   读字节数
******************************************************************************/
int CanRead(Can_DEV *pCan_Dev,UCHAR *buffer,UINT16 nBytes)
{
	UINT16 i;
	UCHAR *rx_buff;
	rx_buff = buffer;
	i = 0;
	if(pCan_Dev->Flag_canOpen == CAN_NO) 
	{
		printf("Can device is not been opened !\n");
		return 0;
	}
	if( ERROR == semTake(pCan_Dev->rx_semSync, 50) )
	{
		//printf("Cann't Take The RX Sem.\n");
		return 0;
	}

	//semTake(pCan_Dev->rx_semSync,WAIT_FOREVER);/*等待接收中断释放信号量*/

	while((pCan_Dev->prx_read != pCan_Dev->prx_write)&&(i < nBytes))
	{
	     *rx_buff = *pCan_Dev->prx_read;
		 rx_buff++;
		 pCan_Dev->prx_read++;
		 i++;
		 if((pCan_Dev->prx_read - pCan_Dev->rx_Buff) == MAX_RX_BUFFER )
		 {
			pCan_Dev->prx_read = pCan_Dev->rx_Buff;
		 }
	}

	return(i);

}
/******************************************************************************
*
* CAN控制函数
*
* 返回:
* 成功返回OK, 设备错误返回ERROR, 不支持返回ERROR
* 
*参数说明:
*  pChan    --   需要控制的设备
*  request  --   请求的功能
*  someArg  --   控制参数
******************************************************************************/

int CanIoctl
    (
    Can_DEV *	pChan,		/* device to control */
    int		request,		/* request code */
    void *	someArg			/* some argument */
    )
{
    STATUS result = OK;
    int     arg = (int)someArg;

	if(pChan->Flag_canOpen != CAN_YES) return ERROR;/*如果设备没有打开返回0*/

    switch (request)
	{
	case CAN_BAUD_SET:
	    if (CanBaudSet(pChan, arg) != OK)
		result = ERROR;
	    break;

	case CAN_BAUD_GET:
	    *(int *)arg = pChan->baudRate;
	    return (OK);

	case CAN_TXID_SET:
	    if (CanTxIDSet(pChan, arg) != OK)
			result = ERROR;
	    break;

	case CAN_TXID_GET:
	    *(int *)arg = pChan->TxID;
	    return (OK);

⌨️ 快捷键说明

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