CAN轉COM或CAN-1

    前段時間在做了一個使用CAN接收數據,然後通過KEY選擇是另一個CAN或者COM發送處理的數據。

    我會通過連載的方式發佈整個過程。

    部分文件著作權歸所屬個人!(在註釋中有)

    首先,我們準備環境:

    MDK3.5 + AK100(ZLG的ARM牛X仿真器)

    其次,我整理思緒... ...

    最基本,需要三個主要模塊:CAN、UART、KEY。

    CAN code:

   

/****************************************Copyright (c)**************************************************
**                                    廣州致遠電子有限公司
**                                     工業通信網絡事業部
**                                http://www.embedcontrol.com
**-------------------------------------文件信息--------------------------------------------------------
**	文   件  	名:	LPC2300CAN.c
** 	當  前  版  本:	v1.0
** 	日		    期:	2007年5月06日
**	描		    述:	
**-------------------------------------歷史創建--------------------------------------------------------
**	文   件  	名:	LPC2300CAN.c
** 	版  		本:	v1.0
** 	日		    期:	2007年4月27日
**	創    建    人:	滕欣欣
**	描		    述:	LPC2300開發板實驗教程實例代碼
**-------------------------------------歷史修改--------------------------------------------------------
**	文   件  	名:	
** 	版  		本:	
** 	日		    期:	
**	修   改     人:	
**	描		    述:	
********************************************************************************************************/
#include "../can/LPC2300CAN.h"
#include "LPC2300CANReg.h"
#include "lpc23xx.h"
#include "../common/type.h"
static struct _MessageDetail MessageDetailT,MessageDetailR;

unsigned char dataAB[8];
unsigned long dataRID;

extern CAN_FIFOMailBox_TypeDef sFIFOMailBox;

/*
*********************************************************************************************************
**函數原型		:  	unsigned char Enter_SWRst(unsigned char Ch);
**參數說明		:  	Ch:CAN控制器號,0表示第一路CAN
**返回值		:	0:失敗
**				:	1: 成功	
**說	明		:	CAN控制器進入軟件復位模式
*********************************************************************************************************/
unsigned char Enter_SWRst(unsigned char Ch)
{
	unsigned long regaddr;
	REG_CANMOD regmod;
	regaddr = (unsigned long)(&CAN1MOD)+Ch*CANOFFSET;			
	regmod.DWord = RGE(regaddr);		//讀取CAN1MOD寄存器
	regmod.Bits.RM = 1;					//RM位置“1”
	RGE(regaddr) = regmod.DWord;		//回寫CAN1MOD寄存器
	regmod.DWord = RGE(regaddr);		//驗證寫入值	
	return (0 != regmod.Bits.RM)? 1:0; 
}
/*
*********************************************************************************************************
**函數原型		:  	unsigned char Quit_SWRst(unsigned char Ch);
**參數說明		:  	Ch:CAN控制器號,0表示第一路CAN
**返回值		:	0:失敗
**				:	1: 成功	
**說	明		:	CAN控制器退出軟件復位模式
*********************************************************************************************************/
unsigned char Quit_SWRst(unsigned char Ch)
{
	unsigned long regaddr;
	REG_CANMOD regmod;
	regaddr = (unsigned long)(&CAN1MOD)+Ch*CANOFFSET;			
	regmod.DWord = RGE(regaddr);		//讀取CAN1MOD寄存器
	regmod.Bits.RM = 0;					//RM位置“0”
	RGE(regaddr) = regmod.DWord;		//回寫CAN1MOD寄存器
	regmod.DWord = RGE(regaddr);		//驗證寫入值	
	return (0 != regmod.Bits.RM)? 0:1; 
}
/*
*********************************************************************************************************
**函數原型		:  	unsigned char CAN_Init(unsigned char Ch, unsigned long Baud);
**參數說明		:  	Ch:CAN控制器號,0表示第一路CAN
**				:	Baud:CAN波特率值
**返回值		:	無
**說	明		:	CAN控制器退出軟件復位模式
*********************************************************************************************************/
void CAN_Init(unsigned char Ch, unsigned long Baud)
{
	unsigned long regaddr;
	PCONP |= 0x01L<<13;				//打開CAN控制器電源
	switch(Ch)						//配置CAN控制器引腳
	{
		case 0:
			PINSEL0 &= ~(0x03L<<0);/*RD1*/
			PINSEL0 |= (0x01L<<0);
			PINSEL0 &= ~(0x03L<<2);/*TD1*/
			PINSEL0 |= (0x01L<<2);
			break;
		case 1:
			PINSEL1 &= ~(0x03L<<10);/*RD1*/
			PINSEL1 |= (0x03L<<10);
			PINSEL1 &= ~(0x03L<<12);/*TD1*/
			PINSEL1 |= (0x03L<<12);
			break;
		default:
			break;
	}
	Enter_SWRst(Ch);
	regaddr = (unsigned long)(&CAN1BTR)+Ch*CANOFFSET;
	RGE(regaddr) = Baud;
	CAN_AFMR &= ~0x07;	//設置爲旁路模式
	CAN_AFMR|=(1<<1);
	Quit_SWRst(Ch);
}
/*
*********************************************************************************************************
**函數原型		:  	unsigned char CANRCVANDSEND(unsigned char Ch, unsigned char BUFNum);
**參數說明		:  	Ch:CAN控制器號,0表示第一路CAN
**				:	BUFNum 選擇緩衝區
**返回值		:	無
**說	明		:	CAN將收到的信息再發送出去 
*********************************************************************************************************/
unsigned char CANRCVANDSEND(unsigned char Ch, unsigned char BUFNum)
{
	unsigned long mes, CAN32reg;
	unsigned long regaddr;
	unsigned char i=5;
	unsigned char i2 = 0;
	BUFNum-=1;		// 計算地址方便。
	
	
	regaddr = (unsigned long)(&CAN1RFS)+Ch*CANOFFSET;				//處理DLC、RTR、FF
	mes = RGE(regaddr);
	mes &= 0Xffff0000;
	regaddr = (unsigned long)(&CAN1TFI1)+Ch*CANOFFSET+0X10*BUFNum;
	RGE(regaddr)=mes;
	
	
	regaddr = (unsigned long)(&CAN1RID)+Ch*CANOFFSET;				//處理ID
	mes = RGE(regaddr);
	regaddr = (unsigned long)(&CAN1TID1)+Ch*CANOFFSET+0X10*BUFNum;
	RGE(regaddr)=mes;
	dataRID = mes;
	
	regaddr = (unsigned long)(&CAN1RDA)+Ch*CANOFFSET;				//處理 數據A
	mes = RGE(regaddr);
	regaddr = (unsigned long)(&CAN1TDA1)+Ch*CANOFFSET+0X10*BUFNum;
	RGE(regaddr)=mes;
	// MessageDetailR.DATAA = mes;
	for (i2 = 0; i2 < 4; i2++) {
		dataAB[i2] = mes >> 8 * i2;
	} 

	regaddr = (unsigned long)(&CAN1RDB)+Ch*CANOFFSET;				//處理 數據B
	mes = RGE(regaddr);
	regaddr = (unsigned long)(&CAN1TDB1)+Ch*CANOFFSET+0X10*BUFNum;
	RGE(regaddr)=mes;
	// MessageDetailR.DATAB = mes;
	for (i2 = 0; i2 < 4; i2++) {
		dataAB[4 + i2] = mes >> 8 * i2;
	} 
		
	regaddr = (unsigned long)(&CAN1GSR)+Ch*CANOFFSET;				//查 接收緩衝區狀態
	mes = RGE(regaddr);
	while(mes&(1<<0))												// RBS爲1 接收緩衝區滿
	{
		regaddr = (unsigned long)(&CAN1CMR)+Ch*CANOFFSET;				
		mes=RGE(regaddr);
		mes |= (1<<2);												//釋放接收緩衝區
		RGE(regaddr)=mes;
		if(!(i--))
		{
			return(0);
		}
	}
	
	// regaddr = (unsigned long)(&CAN1CMR)+Ch*CANOFFSET;				
	// mes=RGE(regaddr);
	// mes &= (~(1<<2));												
	// RGE(regaddr)=mes;
	
	return(1);
}
/*
*********************************************************************************************************
**函數原型		:  	unsigned char writedetail(unsigned char LEN,unsigned char FF, unsigned int ID,unsigned char *data);
**參數說明		:  	LEN:數據長度
**				:	*data 發送數據所在的數組 
				:   
**返回值		:	操作成功返回 1 失敗返回 0
**說	明		:	 用戶填寫發送 幀信息
*********************************************************************************************************/
 unsigned char writedetail(unsigned char LEN,unsigned char FF, unsigned int ID,unsigned char *data)
{
	unsigned char i;
	if(LEN>8)
	{
		return(0);
	}
	else
	{
		MessageDetailT.LEN=LEN;
		MessageDetailT.FF=FF;
		MessageDetailT.CANID=ID;
		MessageDetailT.DATAA=0;			//先清零
		MessageDetailT.DATAB=0;
	
		for(i=0;i<LEN;i++)
		{
			if(i<4)
			{
				MessageDetailT.DATAA |= (*(data+i)<<(i*8)); 
			}
			else
			{
				MessageDetailT.DATAB |= (*(data+i)<<((i-4)*8));
			}
		}
	//MessageDetailT.DATAB = ID;	
	return(1);
	}
}
/*
*********************************************************************************************************
**函數原型		:  	unsigned char CANSend(unsigned char Ch, unsigned char BUFNum);
**參數說明		:  	Ch:CAN控制器號,0表示第一路CAN
**				:	BUFNum 選擇緩衝區
				:   MessageDetailT 報文的特徵信息及數據
**返回值		:	無
**說	明		:	CAN控制器退出軟件復位模式
*********************************************************************************************************/
unsigned char CANSend(unsigned char Ch, unsigned char BUFNum)
{
	unsigned long CAN32reg;
	unsigned long regaddr;
	unsigned char FFflag;
	
	BUFNum-=1;		// 計算地址方便。
	
	
	regaddr = (unsigned long)(&CAN1TFI1)+Ch*CANOFFSET+0X10*BUFNum;	// 3緩衝區間地址差 0x10
	CAN32reg = RGE(regaddr);
	CAN32reg &= ~((0x0fL<<16) | (0x01L<<30) | (0x80000000));        //清 DLC,RTR.FF位?
	CAN32reg |= ((unsigned long)MessageDetailT.LEN<<16) | ((unsigned long)MessageDetailT.FF<<31);
	RGE(regaddr)=CAN32reg;
	
	FFflag = MessageDetailT.FF;
	
	regaddr = (unsigned long)(&CAN1TID1)+Ch*CANOFFSET+0X10*BUFNum;	//寫幀ID
	CAN32reg = RGE(regaddr);
	if(FFflag)														//FF爲1,ID爲29位
	{
		CAN32reg &=0x70000000;
		CAN32reg |= (MessageDetailT.CANID & 0x1fffffff);
	}
	else
	{
		CAN32reg &= 0xfffff800;										//FF爲0 ,ID爲11位
		CAN32reg |= (MessageDetailT.CANID & 0x000007ff);
	}
	RGE(regaddr)=CAN32reg;
	
	regaddr = (unsigned long)(&CAN1TDA1)+Ch*CANOFFSET+0X10*BUFNum;	// 寫幀數據A
	RGE(regaddr) = MessageDetailT.DATAA;
	
	regaddr = (unsigned long)(&CAN1TDB1)+Ch*CANOFFSET+0X10*BUFNum;	// 寫幀數據B
	RGE(regaddr) = MessageDetailT.DATAB;
	
	regaddr = (unsigned long)(&CAN1CMR)+Ch*CANOFFSET;				//寫控制寄存器,發送
	CAN32reg = RGE(regaddr);
	CAN32reg &= ~0x03;
	CAN32reg |= 0x03;
	CAN32reg &= ~((1<<5)|(1<<6)|(1<<7));
	switch(BUFNum)
	{
		case 0: CAN32reg |= 01<<5;break;
		case 1: CAN32reg |= 01<<6;break;
		case 2: CAN32reg |= 01<<7;break;
		default: break;
	}
	RGE(regaddr)=CAN32reg;
	
	
	regaddr = (unsigned long)(&CAN1GSR)+Ch*CANOFFSET;				//查詢發送狀態
	CAN32reg = RGE(regaddr);
	/*/if(CAN32reg&(1<<5))											//等待所有請求的發送已經完成
	{
		;
	}	*/	
	if(CAN32reg&(1<<3))			//所有的請求已成功完成
	{
		
		return(1);				//發送成功返回 1
	}	
	else { return (0);}			//發送失敗返回 0 
	
}

/*----------------------------------------------------------------------------
  read a message from CAN peripheral and release it
 *----------------------------------------------------------------------------*/
void CAN_rdMsg (CAN_msg *msg)  {
                                                  // Read identifier information
  if ((CAN1->sFIFOMailBox[0].RIR & CAN_ID_EXT) == 0) { // Standard ID
    msg->format = STANDARD_FORMAT;
    msg->id     = (DWORD)0x000007FF & (CAN1->sFIFOMailBox[0].RIR >> 21);
  }  else  {                                          // Extended ID
    msg->format = EXTENDED_FORMAT;
    msg->id     = (DWORD)0x0003FFFF & (CAN1->sFIFOMailBox[0].RIR >> 3);
  }
                                                  // Read type information
  if ((CAN1->sFIFOMailBox[0].RIR & CAN_RTR_REMOTE) == 0) {
    msg->type =   DATA_FRAME;                     // DATA   FRAME
  }  else  {
    msg->type = REMOTE_FRAME;                     // REMOTE FRAME
  }
                                                  // Read length (number of received bytes)
  msg->len = (unsigned char)0x0000000F & CAN1->sFIFOMailBox[0].RDTR;
                                                  // Read data bytes
  msg->data[0] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDLR);
  msg->data[1] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDLR >> 8);
  msg->data[2] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDLR >> 16);
  msg->data[3] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDLR >> 24);

  msg->data[4] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDHR);
  msg->data[5] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDHR >> 8);
  msg->data[6] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDHR >> 16);
  msg->data[7] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDHR >> 24);

  CAN1->RF0R |= CAN_RF0R_RFOM0;                    // Release FIFO 0 output mailbox
}


此模塊主要用到的函數爲:CANRCVANDSEND()提供接收CAN總線的數據,在原例中爲接收發送一體。我們需要稍微改造一下,

 

    // MessageDetailR.DATAA = mes;
    for (i2 = 0; i2 < 4; i2++) {
        dataAB[i2] = mes >> 8 * i2;
    }
 

我們知道CAN分數據A部分與數據B部分,每部分各爲4個Byte數組。

上面即數據A部分的分離數組。

同理,我們只需要增加4,即可取到數據B部分的每個數組值。

    // MessageDetailR.DATAB = mes;
    for (i2 = 0; i2 < 4; i2++) {
        dataAB[4 + i2] = mes >> 8 * i2;
    }

 

至此,CAN模塊處理完。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章