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

📄 can.cpp

📁 Canbus驱动德一个源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include "system.h"
#include "func.h"

#if( INSTALL_CANBUS == YES )

#include "canchip.h"

#if( CHIP_TYPE == MCP2510 )

	#include "cansta.h"
	#include "mcp2510.h"
	#include "qspi.h"
#elif( CHIP_TYPE == SJA1000 )
	#include "canmas.h"
	#include "sja1000.h"
#endif

#include "can.h"
#include "StatInfo.h"
#include "canstatic.h"


extern WORD SetTpuIoStatus(WORD IoNum, WORD Status);


//驱动CAN灯闪烁
void GlintCanLed(DWORD Type, DWORD Status)
{
	//发送
	if( Type == TRUE )
	{
		//点亮
		if( Status == FALSE )
		{
		}
		else
		{
			//
			fSendLed = TRUE;
		}
	}
	else
	{
		if( Status == FALSE )
		{
		}
		else
		{
			
			fReceLed = TRUE;
		}
	}
}

DWORD MakeStaAddr(BYTE c1, BYTE c2)
{
	DWORD StaAddr;
	
	StaAddr = c1 << 3;
	StaAddr += c2 >> 5;
	StaAddr &= 0xff;
	
	return StaAddr;
}

//由站号查询控制块地址
WORD LookBlock(WORD StaAddr)
{
	DWORD i;
		
	for(i=0; i<CanStationCount; i++)
	{
		if( CanCB[i].Addr == StaAddr )
		{
			return i;
		}
	}
	
	//没有找到合适的控制块
	return 0xffff;
}



//普通
//CellBuf的格式定义,主从一致:
//CellBuf[0]    -- 站号低位
//CellBuf[1]    -- 站号高位
//CellBuf[2]    -- 长度,数据长度
//CellBuf[3-10] -- 数据
void PutToNormal(BYTE * CellBuf, DWORD BlockAddr)
{
	BYTE * SendBuf;
	
	GlintCanLed(TRUE, TRUE);
	
	SendBuf = CanCB[BlockAddr].NormalSendBuf[ CanCB[BlockAddr].NSBufWPoint ];
	
	//若不为链路启动
	if( (CellBuf[3]&0x80) == 0 )
	{
		//处理序号,最大为64
		CellBuf[3] |= CanCB[BlockAddr].SOrder[0];
		CanCB[BlockAddr].SOrder[0] ++;
		CanCB[BlockAddr].SOrder[0] &= 0x3f;
	}

	//写入缓冲
	memcpy( SendBuf, CellBuf, (CellBuf[2]+3) );
	
	DWORD imask = splx(MAX_ILEV);
	CanCB[BlockAddr].NSBufWPoint ++;
	CanCB[BlockAddr].NSBufWPoint %= MAX_NSEND_BUF;
	splx(imask);
}

//主动上传
//CellBuf的格式定义,主从一致:
//CellBuf[0]    -- 站号低位
//CellBuf[1]    -- 站号高位
//CellBuf[2]    -- 长度,数据长度
//CellBuf[3-10] -- 数据
void PutToUrgency(BYTE * CellBuf, DWORD BlockAddr)
{
	BYTE * SendBuf;
	
	GlintCanLed(TRUE, TRUE);
	
	SendBuf = CanCB[BlockAddr].UrgencySendBuf[ CanCB[BlockAddr].USBufWPoint ];
	
	if( (CellBuf[3]&0x80) == 0 )
	{
		//处理序号,最大为64
		CellBuf[3] |= CanCB[BlockAddr].SOrder[1];
		CanCB[BlockAddr].SOrder[1] ++; 
		CanCB[BlockAddr].SOrder[1] &= 0x3f; 
	}


	//写入缓冲
	memcpy( SendBuf, CellBuf, (CellBuf[2]+3) );
	
	DWORD imask = splx(MAX_ILEV);
	CanCB[BlockAddr].USBufWPoint ++;
	CanCB[BlockAddr].USBufWPoint %= MAX_USEND_BUF;
	splx(imask);
}

//命令和丢失桢
//CellBuf的格式定义,主从一致:
//CellBuf[0]    -- 站号低位
//CellBuf[1]    -- 站号高位
//CellBuf[2]    -- 长度,数据长度
//CellBuf[3-10] -- 数据
void PutToCommand(BYTE * CellBuf, DWORD BlockAddr)
{
	DWORD imask;
	
	BYTE * SendBuf;

	GlintCanLed(TRUE, TRUE);

	SendBuf = CanCB[BlockAddr].CommandSendBuf[ CanCB[BlockAddr].CSBufWPoint ];
	
	//写入缓冲
	memcpy( SendBuf, CellBuf, (CellBuf[2]+3) );
	
	imask = splx(MAX_ILEV);
	CanCB[BlockAddr].CSBufWPoint ++;
	CanCB[BlockAddr].CSBufWPoint %= MAX_CSEND_BUF;
	splx(imask);

	BeginSendCell();
}

//************************************************************
//发送操作
//************************************************************
void DoSendProc(void)
{
	DWORD i;
	BYTE * CellNow;
	
	//查询所有的模块
	for(i=0; i<CanStationCount; i++)
	{ 
		TCanCBlock * p = &(CanCB[i]);

		//首先处理命令返回缓冲
		if( p->CSBufRPoint != p->CSBufWPoint )
		{
			CellNow = p->CommandSendBuf[ p->CSBufRPoint ];
			
			WriteBytes(CellNow, CellNow[2]+3);
			
			p->CSBufRPoint ++;
			p->CSBufRPoint %= MAX_CSEND_BUF; 
			
			p->CommandSendAll++;
	
			BeginSend();
			
			return;
		}
		//处理紧急事件缓冲
		else if( p->USBufRPoint != p->USBufWPoint )
		{
			CellNow = p->UrgencySendBuf[ p->USBufRPoint ];
			
			//for debug
			//if( ((CellNow[3]&0x80)!=0) || ((CellNow[3]&0x3f)%10 != 0) ) 
			{
				WriteBytes(CellNow, CellNow[2]+3);
			}
			
			if( (CellNow[3]&0x80) == 0 )
			{
				//清除发送等待计数
				p->StopSendCount[1] = 0;
				//取最后的计数
				p->SendEnd[1] = CellNow[3] & 0x3f;
			}
			
			//记录历史单元
			for(i=0; i<MAX_CELL_SIZE; i++)
			{
				HistoryBuf[1][ HBufWPoint[1] ][i] = CellNow[i];
			}
			
			HBufWPoint[1] ++;
			HBufWPoint[1] %= MAX_HIS_BUF;
			
			p->USBufRPoint ++;
			p->USBufRPoint %= MAX_USEND_BUF;
			
			p->UrgencySendAll ++; 
	
			//for debug
			//if( ((CellNow[3]&0x80)!=0) || ((CellNow[3]&0x3f)%10 != 0) ) 
			{
				BeginSend();
			}      
			
			return;
		}
		//其次处理一般事件缓冲
		else if( p->NSBufRPoint != p->NSBufWPoint )
		{
			CellNow = p->NormalSendBuf[ p->NSBufRPoint ];
			
			WriteBytes(CellNow, CellNow[2]+3);
			
			if( (CellNow[3]&0x80) == 0 )
			{
				p->StopSendCount[0] = 0;
				p->SendEnd[0] = CellNow[3] & 0x3f;
			}
	
			//记录历史单元
			for(i=0; i<MAX_CELL_SIZE; i++)
			{
				HistoryBuf[0][ HBufWPoint[0] ][i] = CellNow[i];
			}
			
			HBufWPoint[0] ++;
			HBufWPoint[0] %= MAX_HIS_BUF;
			
			p->NSBufRPoint ++;
			p->NSBufRPoint %= MAX_NSEND_BUF;
			
			p->NormalSendAll++;
	
			BeginSend();
			
			return;
		}
	}
}

void BeginSendCell()
{
	BYTE Status;

	//查询状态
	ReadCanStatus(&Status);
	
	//发送缓冲空
	if( IsTxdBufEmpty(Status) == TRUE )
	{
		DoSendProc();
	}
	
	//若出现错误,则复位硬件
	if( (Status&CAN_HARD_ERROR) != 0 )
	{
		InitCanHard();
	}
}


//************************************************************
//查找丢失单元,且发送
//************************************************************
void FindAndSendLost(DWORD Order, DWORD RequestOrder, DWORD BlockAddr)
{
	DWORD i;
	BYTE CellBuf[MAX_CELL_SIZE];
	WORD PointNow;
	BOOL fFind;
	
	DWORD Temp;
		
	DWORD Address = CanCB[BlockAddr].Addr;
	
	//????????????????????//
	if( Order > 1 )
	{
		
	}
	
	//区分为何种通道
	if( Order == NORMAL_CHANNEL )
	{
		Temp = Address + NREAPTE_PTR;
	}
	else
	{
		Temp = Address + UREAPTE_PTR;
	}
		
	//当前指针
	PointNow = HBufWPoint[Order];
	
	//指向最新的记录
	PointNow --;
	if( PointNow > MAX_HIS_BUF )
	{
		PointNow = MAX_HIS_BUF - 1;
	}
	
	fFind = FALSE;
	
	//搜索所有的历史记录单元
	for(i=0; i<MAX_HIS_BUF; i++)
	{
		if( (HistoryBuf[Order][PointNow][3]&0x3f) == RequestOrder )
		{
			fFind = TRUE;
			break;
		}
		PointNow --;
		if( PointNow > MAX_HIS_BUF )
		{
			PointNow = MAX_HIS_BUF - 1;
		}
	}
	
	//找到了需要的桢
	if( fFind == TRUE )
	{
		CellBuf[2] = HistoryBuf[Order][PointNow][2];
		
		//拷贝数据和长度
		for(i=3; i<(CellBuf[2]+3); i++)
		{
			CellBuf[i] = HistoryBuf[Order][PointNow][i];
		}
		
		//替换优先级
		CellBuf[0] = (Temp>>3)&0xff;
		CellBuf[1] = (Temp<<5)&0xff;
		
		//放入紧急缓冲,没有考虑是否有空间
		PutToCommand(CellBuf, BlockAddr);
	}
	//永远丢失
	else
	{
		Temp = Address + COMMAND_PRI;
		
		CellBuf[0] = (Temp>>3)&0xff;
		CellBuf[1] = (Temp<<5)&0xff;
		
		CellBuf[2] = 3;
		
		//永远丢失的单元
		CellBuf[3] = RESPOND_CELL_LOST;
		//通道类型
		CellBuf[4] = Order;
		//单元序号
		CellBuf[5] = RequestOrder;
		
		PutToCommand(CellBuf, BlockAddr);
	}
	
	//统计信息
	CanStatInfo.FindAndSendLost++;
}

//*****************************************************
//收到复位链路请求后,复位链路
//*****************************************************
void ResetLink(DWORD Index, DWORD BlockAddr, DWORD Where)
{
	CanCB[BlockAddr].SOrder[Index]         = 1;
	CanCB[BlockAddr].ROrder[Index]         = 0;
	CanCB[BlockAddr].StartCellOrder[Index] = 0;
	CanCB[BlockAddr].FrameLength[Index]    = 0;
	CanCB[BlockAddr].FrameOrder[Index]     = 0;
	CanCB[BlockAddr].StopSendCount[Index]  = 0xffff;
	
	CanCB[BlockAddr].fStart[Index]		   = TRUE;
	
	CanCB[BlockAddr].RequestCount[Index]   = 0;
	
	//统计信息
	CanStatInfo.ResetLink ++;
}

//*******************************************
//命令帧处理
//*******************************************
void ProcCommand(DWORD BlockAddr)
{
	BYTE CellBuf[MAX_CELL_SIZE];
	
	BYTE * CellNow;
	
	DWORD MyAddr;
	
	DWORD k;
	
	DWORD Index;

	//闪烁CAN灯
	GlintCanLed(FALSE, TRUE);
	
	CellNow = CanCB[BlockAddr].CommandReceBuf[ CanCB[BlockAddr].CRBufRPoint ];
	
	MyAddr = CanCB[BlockAddr].Addr + COMMAND_PRI;
		
	//???????????????????????????
	if( CellNow[8]==RESPOND_NREAPET )
	{
		Index = 0;
	}
	else if( CellNow[8]==RESPOND_UREAPET )
	{
		Index = 1;
	}
	else
	{
		if( (CellNow[1]==NORMAL_CHANNEL) )
		{
			Index = 0;
		}
		else
		{
			Index = 1;
		}
	}
	
	//处于复位状态
	if( CanCB[BlockAddr].fStart[Index] != TRUE )
	{
		CanCB[BlockAddr].CRBufRPoint ++;
		CanCB[BlockAddr].CRBufRPoint %= MAX_CRECE_BUF;
		return;
	}

	//控制报文分类处理
	switch( CellNow[8] )
	{
		//对方请求重发某单元数据
		case REQUEST_REAPET_SEND:
		
			//传送通道类型、需要的编码
			FindAndSendLost(CellNow[1], CellNow[2], BlockAddr);
			break;

		//对方发送的数据链路结束请求,对方想确认是否已经收到了最后一个单元
		//因为只有在相应通道空的情况下才发送,所以应该已经收到了最后一个单元
		case REQUEST_LINK_END:
		
			CellNow[2] &= 0x3f;
			
			//跨度
			k = ( CellNow[2] - CanCB[BlockAddr].ROrder[Index]) & 0x3f;
			
			if( k > MAX_SPAN )
			{
				RequstResetLink(Index, BlockAddr, 2);
				
				CanCB[BlockAddr].CRBufRPoint ++;
				CanCB[BlockAddr].CRBufRPoint %= MAX_CRECE_BUF;
				return;
			}
			
			if( k != 0 )
			{
				//从最后一个接收到的序号到最后的期望序号复要,
				//如何后续??????????????????
				RequestCell( Index, (CanCB[BlockAddr].ROrder[Index]+1)&0x3f, BlockAddr, 1);
				
				tm_wkafter(TICK2MS(20));
			}
			else
			{
				//发送确认结束链路回答
				CellBuf[0] = (MyAddr>>3)&0xff;
				CellBuf[1] = (MyAddr<<5)&0xff;
				
				CellBuf[2] = 2;
				CellBuf[3] = RESPOND_LINK_END;
				//通道类型
				CellBuf[4] = Index;
				
				PutToCommand(CellBuf, BlockAddr);
			}
			break;
			
		//对方响应的数据链路结束请求
		case RESPOND_LINK_END:
		
			//停止发送数据链路结束请求
			CanCB[BlockAddr].StopSendCount[Index] = 0xffff;
			break;
			
		//完全丢失桢的处理
		case RESPOND_CELL_LOST:
		
			//要求对方复位链路
			RequstResetLink(Index, BlockAddr, 5);
			
			CanCB[BlockAddr].CRBufRPoint ++;
			CanCB[BlockAddr].CRBufRPoint %= MAX_CRECE_BUF;
			return;
			
		//复要
		case RESPOND_NREAPET:
		case RESPOND_UREAPET:
			
			//判断是否为当前需要的序号
			if( (CellNow[0]&0x3f) == CanCB[BlockAddr].RequestCell[Index] )
			{
				ProcDataCell(Index, CellNow, BlockAddr); 
				
				CanCB[BlockAddr].ROrder[Index] = CellNow[0]&0x3f;
				
				CanCB[BlockAddr].RequestCell[Index] = 0xffff;
			}
			break;
	
		//主板要求分板静默
		case REQUEST_SILENCE:
		
			//暂时定为初始化链路,也能使分板静默
			ResetLink(NORMAL_CHANNEL, BlockAddr, 5);
			ResetLink(URGENCY_CHANNEL, BlockAddr, 6);
			
			//系统状态
			CanStatInfo.CanStatus |= 0x00000001;
			
			//不再操作计数器
			//return;
			
		default:
			break;
	}
	
	CanCB[BlockAddr].CRBufRPoint ++;
	CanCB[BlockAddr].CRBufRPoint %= MAX_CRECE_BUF;
}

//********************************************
//紧急帧处理
//********************************************
void ProcUrgency(DWORD BlockAddr)
{
	BYTE CellBuf[MAX_CELL_SIZE];
	BYTE * CellNow;
	
	BYTE OrderNow;
	
	WORD MyAddr;
	
	BYTE Span;

⌨️ 快捷键说明

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