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