📄 can.cpp
字号:
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 + -