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

📄 can.cpp

📁 Canbus驱动德一个源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	GlintCanLed(FALSE, TRUE);

	CellNow = CanCB[BlockAddr].UrgencyReceBuf[ CanCB[BlockAddr].URBufRPoint ];
	
	//链路复位标志
	if( (CellNow[0]&0x80) != 0 )
	{
		//对方请求复位链路
		if( (CellNow[0]&0x40) != 0 )
		{
			MyAddr = CanCB[BlockAddr].Addr + URGENCY_PRI;
			
			CellBuf[0] = (MyAddr>>3)&0xff;
			CellBuf[1] = (MyAddr<<5)&0xff;
	
			CellBuf[2] = 1;
			CellBuf[3] = 0x80;
			
			PutToUrgency(CellBuf, BlockAddr);
			
			BeginSendCell();
			
			ResetLink(URGENCY_CHANNEL, BlockAddr, 2);
		}
		//对方应答复位链路
		else
		{
			//链路复位成功,开始应答过程
			CanCB[BlockAddr].fStart[1] = TRUE;
			
			ResetLink(URGENCY_CHANNEL, BlockAddr, 3);
		}
		
		CanCB[BlockAddr].URBufRPoint ++;
		CanCB[BlockAddr].URBufRPoint %= MAX_URECE_BUF;
		return;
	}
	
	//当前序号
	OrderNow = CellNow[0] & 0x3f;
	
	//没有启动初始化
	if( CanCB[BlockAddr].fStart[1] == FALSE )
	{
		CanCB[BlockAddr].URBufRPoint ++;
		CanCB[BlockAddr].URBufRPoint %= MAX_URECE_BUF;
		return;
	}
	
	//计算跨度
	Span = (OrderNow - CanCB[BlockAddr].ROrder[1]) & 0x3f;
	
	//超过最大跨度
	if( Span > MAX_SPAN )
	{
		RequstResetLink(1, BlockAddr, 7);
		CanCB[BlockAddr].URBufRPoint ++;
		CanCB[BlockAddr].URBufRPoint %= MAX_URECE_BUF;
		return;
	}
	//有丢失单元,复要,当前单元不处理
	else if( Span != 1 )
	{
		//复要
		RequestCell( URGENCY_CHANNEL, (CanCB[BlockAddr].ROrder[1]+1)&0x3f, BlockAddr, 3);
		
		if( CanCB[BlockAddr].RequestCount[1] > MAX_WAIT_REAPET )
		{
			RequstResetLink(1, BlockAddr, 0);
		}
		CanCB[BlockAddr].RequestCount[1] ++;
		
		tm_wkafter(TICK2MS(20));
	}
	//处理数据单元
	else
	{
		ProcDataCell(1, CellNow, BlockAddr); 
		
		CanCB[BlockAddr].URBufRPoint ++;
		CanCB[BlockAddr].URBufRPoint %= MAX_URECE_BUF;
		
		CanCB[BlockAddr].ROrder[1] = OrderNow;
		
		CanCB[BlockAddr].RequestCount[1] = 0;
	}
}

//普通帧处理
void ProcNormal(DWORD BlockAddr)
{
	BYTE CellBuf[MAX_CELL_SIZE];
	BYTE * CellNow;
	BYTE OrderNow;
	
	WORD MyAddr;
	
	BYTE Span;
	
	GlintCanLed(FALSE, TRUE);

	CellNow = CanCB[BlockAddr].NormalReceBuf[ CanCB[BlockAddr].NRBufRPoint ];
	
	//丢失数据单元检测和复要,若复要则不进行组桢处理,直到收到此单元或超过最大限度或永远丢失信息
	
	//链路复位标志
	if( (CellNow[0]&0x80) != 0 )
	{
		//对方请求复位链路
		if( (CellNow[0]&0x40) != 0 )
		{
			MyAddr = CanCB[BlockAddr].Addr + NORMAL_PRI;
			
			CellBuf[0] = (MyAddr>>3)&0xff;
			CellBuf[1] = (MyAddr<<5)&0xff;
	
			CellBuf[2] = 1;
			CellBuf[3] = 0x80;
			
			PutToNormal(CellBuf, BlockAddr);
			
			BeginSendCell();
			
			ResetLink(NORMAL_CHANNEL, BlockAddr, 0);
		}
		//对方应答复位链路
		else
		{
			//链路复位成功,开始应答过程
			CanCB[BlockAddr].fStart[0] = TRUE;
			
			ResetLink(NORMAL_CHANNEL, BlockAddr, 1);
		}
		
		CanCB[BlockAddr].NRBufRPoint ++;
		CanCB[BlockAddr].NRBufRPoint %= MAX_NRECE_BUF;
		return;
	}
	
	//当前序号
	OrderNow = CellNow[0] & 0x3f;
	
	//链路启动状态,停止处理一切 
	if( CanCB[BlockAddr].fStart[0] == FALSE )
	{
		CanCB[BlockAddr].NRBufRPoint ++;
		CanCB[BlockAddr].NRBufRPoint %= MAX_NRECE_BUF;
		return;
	}
	
	//计算跨度
	Span = (OrderNow - CanCB[BlockAddr].ROrder[0]) & 0x3f;
	
	//超过最大跨度
	if( Span > MAX_SPAN )
	{
		RequstResetLink(0, BlockAddr, 9);
		CanCB[BlockAddr].NRBufRPoint ++;
		CanCB[BlockAddr].NRBufRPoint %= MAX_NRECE_BUF;
		return;
	}
	//有丢失单元,复要,要设置最大等待时间?
	else if( Span != 1 )
	{
		//复要
		RequestCell( NORMAL_CHANNEL, (CanCB[BlockAddr].ROrder[0]+1)&0x3f, BlockAddr, 4);
		
		if( CanCB[BlockAddr].RequestCount[0] > MAX_WAIT_REAPET )
		{
			RequstResetLink(0, BlockAddr, 0);
		}
		CanCB[BlockAddr].RequestCount[0] ++;
		
		//等待,防止重复进入,此时间与波特率有关系,要精确设定?
		tm_wkafter(TICK2MS(20));
	}
	//处理数据单元
	else
	{
		ProcDataCell(0, CellNow, BlockAddr);
		
		CanCB[BlockAddr].NRBufRPoint ++;
		CanCB[BlockAddr].NRBufRPoint %= MAX_NRECE_BUF;
		
		CanCB[BlockAddr].ROrder[0] = OrderNow;
		
		CanCB[BlockAddr].RequestCount[0] = 0;
	}
}

//接收处理,单板
void CanDaemonReceiver(void)
{
	DWORD i;
	
	BOOL fProcEnd;
	
	for(i=0; i<CanStationCount; i++)
	{
		while(1)
		{
			fProcEnd = TRUE;
			
			//控制单元,无编码
			if( CanCB[i].CRBufRPoint != CanCB[i].CRBufWPoint )
			{
				ProcCommand(i);
				fProcEnd = FALSE;
			}
			
			//紧急单元,有编码
			else if(CanCB[i].URBufRPoint != CanCB[i].URBufWPoint)
			{
				ProcUrgency(i);
				fProcEnd = FALSE;
			}
		
			//一般单元,有编码
			else if(CanCB[i].NRBufRPoint != CanCB[i].NRBufWPoint)
			{
				ProcNormal(i);
				fProcEnd = FALSE;
			}
			
			//所有缓冲都处理完成。
			else if( fProcEnd == TRUE )
			{
				break; 
			}
		}
	}
}

//单元组桢处理,到此步,单元应该都是连续的
void ProcDataCell( DWORD Index, BYTE * CellNow, DWORD Ba)
{	
	DWORD i;

	//启动单元
	if( (CellNow[0]&0x40) != 0 )
	{
		//出现错误,上一桢没有处理完,应该是组桢错误,只能将上桢丢弃
		if( CanCB[Ba].FrameLength[Index] != CanCB[Ba].FrameOrder[Index] )
		{
			//统计信息
			CanStatInfo.FrameError ++;
		}
		
		//此桢起始序号
		CanCB[Ba].StartCellOrder[Index] = CellNow[0]&0x3f;
		//桢长度,为单元数目,不包括启动发送的单元
		CanCB[Ba].FrameLength[Index] = CellNow[1];
		//清桢内单元序号
		CanCB[Ba].FrameOrder[Index] = 0;
	}
	//数据单元
	else
	{
		//必须分别组帧,因为有可能会紧急单元主动上传,插入
		if( Index == 0 )
		{
			//组桢,每组有7个字节
			for(i=0; i<(MAX_CELL_DATA-1); i++)
			{
				NSendUpBuffer[NSUBufWPoint][ CanCB[Ba].FrameOrder[Index] * (MAX_CELL_DATA-1) + i ] = CellNow[i+1];
			}
		}
		else
		{
			//组桢,每组有7个字节
			for(i=0; i<(MAX_CELL_DATA-1); i++)
			{
				USendUpBuffer[USUBufWPoint][ CanCB[Ba].FrameOrder[Index] * (MAX_CELL_DATA-1) + i ] = CellNow[i+1];
			}
		}
		
		CanCB[Ba].FrameOrder[Index] ++;
		
		//此桢已经接收结束
		if( CanCB[Ba].FrameOrder[Index] == CanCB[Ba].FrameLength[Index] )
		{
			if( Index == 0 )
			{
				//移动缓冲指针
				NSUBufWPoint ++;
				NSUBufWPoint %= MAX_SUP_BUF;
			}
			else
			{
				//移动缓冲指针
				USUBufWPoint ++;
				USUBufWPoint %= MAX_SUP_BUF;
			}

			//通知上层任务,接收数据准备好
			DF_PostMessage(CanUpTaskId,SM_READCOMM);
		}
	}
}

DWORD CanRead(DWORD Sid, BYTE * buf)
{
	if( NSUBufRPoint != NSUBufWPoint )
	{
		memcpy(buf, NSendUpBuffer[NSUBufRPoint], MAX_BUF_SIZE);
		
		NSUBufRPoint ++;
		NSUBufRPoint %= MAX_SUP_BUF;
		
		//若缓冲区没有空
		if( (NSUBufRPoint!=NSUBufWPoint) || (USUBufRPoint!=USUBufWPoint) )
		{
			//通知上层任务继续读
			DF_PostMessage(CanUpTaskId,SM_READCOMM);
		}
	
		return buf[0];
	}
	
	if( USUBufRPoint != USUBufWPoint )
	{
		memcpy(buf, USendUpBuffer[USUBufRPoint], MAX_BUF_SIZE);
		
		USUBufRPoint ++;
		USUBufRPoint %= MAX_SUP_BUF;
		
		//若缓冲区没有空
		if( (NSUBufRPoint!=NSUBufWPoint) || (USUBufRPoint!=USUBufWPoint) )
		{
			//通知上层任务继续读
			DF_PostMessage(CanUpTaskId, SM_READCOMM);
		}
	
		return buf[0];
	}
	return 0;
}

DWORD CanWrite(DWORD sid, void * buf, DWORD Length, DWORD mode)
{
	//拆桢成功
	if( MakeSendCell(mode&0xffff, (BYTE *)buf, Length, (mode>>31)) == SUCCEED )
	{
		//开始发送
		BeginSendCell();
		
		fReceFrameOk = TRUE;

		//当前桢已经被接受
		return Length;
	}
	//暂存
	else
	{
		//已经占用的空间
		WORD Temp;
		if( RUBufRPoint > RUBufWPoint )
		{
			Temp = RUBufRPoint - RUBufWPoint;
		}
		else
		{
			Temp = MAX_RUP_BUF + RUBufRPoint - RUBufWPoint;
		}
		
		//有足够空间
		if( Temp > 1 ) 
		{
			ReceLength[RUBufWPoint] = Length;
			ReceMode[RUBufWPoint] = mode;
			
			memcpy(ReceUpBuffer[RUBufWPoint], (BYTE *)buf, Length);
			
			RUBufWPoint ++;
			RUBufWPoint %= MAX_RUP_BUF;
			
			return Length;
		}
		
		return 0;
	}
}

DWORD MakeSendCell(DWORD sid, BYTE * buf, DWORD Length, DWORD Type)
{
	DWORD i, j;
	
	BYTE CellBuf[MAX_CELL_SIZE];
	
	WORD CellLength;
	
	WORD CellNumber;
	
	//控制块号码
	DWORD Ba = LookBlock(sid);
	
	DWORD MyAddr;
	
	//无此地址
	if( Ba == 0xffff )
	{
		return FAIL;
	}
	
	if( Type == WCF_NORMAL )
	{
		//判断链路状态
		if( CanCB[Ba].fStart[0] != TRUE )
		{
			return FAIL;
		}
	
		MyAddr = sid + NORMAL_PRI;
	}
	else
	{
		//判断链路状态
		if( CanCB[Ba].fStart[1] != TRUE )
		{
			return FAIL;
		}
	
		MyAddr = sid + URGENCY_PRI;
	}
	
	//此桢中要占用的单元数目
	CellNumber = Length / 7;
	
	//保证包括最后一个单元
	if( (Length%7) != 0 )
	{
		CellNumber ++;
	}
	
	WORD Temp;
	
	//考察发送缓冲所剩余的空间
	if( Type == WCF_URGENT )
	{
		if( CanCB[Ba].USBufRPoint > CanCB[Ba].USBufWPoint )
		{
			Temp = CanCB[Ba].USBufRPoint - CanCB[Ba].USBufWPoint;
		}
		else
		{
			Temp = MAX_USEND_BUF + CanCB[Ba].USBufRPoint - CanCB[Ba].USBufWPoint;
		}
	}
	else
	{
		if( CanCB[Ba].NSBufRPoint > CanCB[Ba].NSBufWPoint )
		{
			Temp = CanCB[Ba].NSBufRPoint - CanCB[Ba].NSBufWPoint;
		}
		else
		{
			Temp = MAX_NSEND_BUF + CanCB[Ba].NSBufRPoint - CanCB[Ba].NSBufWPoint;
		}
	}
	
		
	//空闲一帧。
	if( Temp > (CellNumber+1+2+1) )
	{
		CellBuf[0] = (MyAddr>>3)&0xff;
		CellBuf[1] = (MyAddr<<5)&0xff;
				
		CellBuf[2] = 2;
		//启动单元
		CellBuf[3] = 0x40;
		//此帧长度
		CellBuf[4] = CellNumber;
		
		if( Type == WCF_URGENT )
		{
			//放入缓冲
			PutToUrgency(CellBuf, Ba);
		}
		else
		{
			//放入缓冲
			PutToNormal(CellBuf, Ba);
		}
		
		//处理数据单元 
		for(i=0; i<CellNumber; i++)
		{
			//处理中间数据桢
			if( i != (CellNumber-1) )
			{
				CellLength = 7;
			}
			//最后一桢数据桢处理
			else
			{
				CellLength = Length % 7;
			}
			
			if( CellLength == 0 )
			{
				CellLength = 7;
			}
			
			CellBuf[0] = (MyAddr>>3)&0xff;
			CellBuf[1] = (MyAddr<<5)&0xff;
				
			//本单元长度
			CellBuf[2] = CellLength+1;
			//为序号准备
			CellBuf[3] = 0;
		
			//移动数据
			for(j=0; j<CellLength; j++)
			{
				CellBuf[4+j] = buf[j+i*7];
			}
			
			if( Type == WCF_URGENT )
			{
				//放入缓冲
				PutToUrgency(CellBuf, Ba);
			}
			else
			{
				//放入缓冲
				PutToNormal(CellBuf, Ba);
			}
		}
		
		return SUCCEED;
	}
		
	return FAIL;
}

void RequestCell(DWORD ChannelType, DWORD RequestOrder, DWORD BlockAddr, DWORD Where)
{
	BYTE CellBuf[MAX_CELL_SIZE];
	
	DWORD MyAddr = CanCB[BlockAddr].Addr + COMMAND_PRI;
	
	CellBuf[0] = (MyAddr>>3)&0xff;
	CellBuf[1] = (MyAddr<<5)&0xff;
				
	CellBuf[2] = 3;
	CellBuf[3] = REQUEST_REAPET_SEND;
	CellBuf[4] = ChannelType;
	CellBuf[5] = RequestOrder;
	
	PutToCommand(CellBuf, BlockAddr);
	
	//添入现在复要的号
	CanCB[BlockAddr].RequestCell[ChannelType] = RequestOrder;
	
	//统计信息
	CanStatInfo.RequestCell ++;
}

//发送请求复位链路的命令
void RequstResetLink(DWORD ChannelType, DWORD BlockAddr, DWORD Where)
{
	//本身链路置为正在复位的状态
	CanCB[BlockAddr].fStart[ChannelType] = FALSE;
	
	//统计信息
	CanStatInfo.RequstResetLink ++;
}

//管理任务
void CanDaemon(void)
{
	DWORD  tmid, events_r;
	static WORD CanTimer = 0;
			
	DWORD i, j;
	
	DWORD MyAddr;
	
	BYTE CellBuf[MAX_CELL_SIZE];
	
	t_ident("CAND", 0, &CanDaemonTaskId);
    
    //启动定时
    tm_evevery((TICK2MS(MIN_CAN_TIMER)), EV_CAN_TIMER, &tmid);



    while (1) 

⌨️ 快捷键说明

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