📄 protocolkw2000.c
字号:
// 5波特触发
if( !KWIso_link( SysId, portK, portL ) )
{
TimeRelease();
SCIRelease();
return FAIL;
}
TimeInit( TIMER0,5 ); //初始化T0 10ms
SCIload( Kw2000Scon );
TimeLoad( TIMER0, Kw2000Time );
//发送触发数据
Tagkw.MScount = 0;
Tagkw.Waitsend = LinkDig;
Tagkw.Btyetime = 10;
Tagkw.Lenth = KW_Getlen( LinkDig );
Tagkw.Chksum = 0;
for( i=0; i<Tagkw.Lenth-1; i++ )
{
Tagkw.Chksum += Tagkw.Waitsend[i];
}
Tagkw.Waitsend[i] = Tagkw.Chksum;
Tagkw.Count = 0;
SCIsendin( Tagkw.Waitsend[Tagkw.Count++] ); //发送第一字节
Tagkw.Flashset = 1; //发送数据更新就绪
Tagkw.Readset = 0;
if( KW_Read( Temp, 800, 20 ) )
{
return SUCCESS;
}
else
{
//NULL
}
TimeRelease();
SCIRelease();
return FAIL;
}
/*
**-----------------------------------------------------------------------------------------
** KWP2000 发送协议包刷新函数
** Dig:待发送数据包
** BtyeDst:发送字节间隔( MS )
**-----------------------------------------------------------------------------------------
*/
char KW_Send( unsigned char *Dig, int BtyeDst )
{
int i;
while( Tagkw.MScount < ( 20/T0TIME ) ); //桢间距 20MS
Tagkw.MScount = 0;
while( Tagkw.Flashset && ( Tagkw.MScount < ( Tagkw.HoldT/T0TIME-1 ) ) ) //正在发送,等待一个链路时间单位
{
//NULL
}
Tagkw.MScount = 0;
while( !Tagkw.Readset && ( Tagkw.MScount < ( Tagkw.HoldT/T0TIME-1 ) ) ) //正在接收,等待一个链路时间单位
{
//NULL
}
if( !Tagkw.Readset )
{
return 0; //上一次收发接收失败
}
else
{
//NULL
}
// 装载发送数据 初始化发送状态
Tagkw.MScount = 0;
Tagkw.Waitsend = Dig;
Tagkw.Btyetime = BtyeDst;
Tagkw.Lenth = KW_Getlen( Dig );
Tagkw.Chksum = 0;
for( i=0; i<Tagkw.Lenth-1; i++ )
{
Tagkw.Chksum += Tagkw.Waitsend[i];
}
Tagkw.Waitsend[i] = Tagkw.Chksum;
Tagkw.Count = 0;
Tagkw.Flashset = 1; //发送数据更新就绪
while( Tagkw.Flashset && ( Tagkw.MScount < ( Tagkw.HoldT/T0TIME-1 ) ) ) //正在发送,等待1个链路保持时间时间单位
{
//NULL
}
return SUCCESS;
}
/*
**-----------------------------------------------------------------------------------------
** KWP2000 回送协议包接收函数
** Dig:数据包接收位置
** Wtime:接收等待最大时间(MS)
** MaxLen:最大接收长度
**-----------------------------------------------------------------------------------------
*/
char KW_Read( unsigned char *Dig, int Wtime, unsigned char MaxLen )
{
unsigned int WaitTime;
if( Wtime >= Tagkw.HoldT ) Wtime = Tagkw.HoldT;
Tagkw.MScount = 0;
while( !Tagkw.Readset && ( Tagkw.MScount < ( Tagkw.HoldT/T0TIME-1 ) ) ) //正在接收,等待一个链路时间单位
{
//NULL
}
Tagkw.MScount = 0;
while( Tagkw.Flashset && ( Tagkw.MScount < ( Tagkw.HoldT/T0TIME-1 ) ) ) //正在发送,等待一个链路时间单位
{
//NULL
}
WaitTime = Wtime/T0TIME;
Tagkw.MScount = 0;
Tagkw.Waitread = Dig;
Tagkw.Lenth = 4;
Tagkw.Readset = 0;
SCIENcontrol( 1 );
while( Tagkw.MScount < WaitTime && !Tagkw.Readset ) //指定时间等待接收完毕
{
if( Tagkw.Count >= MaxLen ) //NULL
{
Tagkw.Count = 0;
SCIENcontrol( 0 );
return FAIL;
}
}
if( Tagkw.Readset ) return SUCCESS;
return FAIL;
}
/*
**-----------------------------------------------------------------------------------------
** 提取 KWP2000 回送协议包长度信息(KW2000专有函数)
** Dig:数据包
**-----------------------------------------------------------------------------------------
*/
unsigned char KW_Getlen( unsigned char *Dig )
{
if( Dig[0]>0x80 )
{
return( ( Dig[0]&0x3f )+4 );
}
else if( Dig[0]==0x80 )
{
return( Dig[3]+5 );
}
else
{
return( Dig[0]+1 );
}
}
/*
**-----------------------------------------------------------------------------------------
** 协议定时器中断函数
**-----------------------------------------------------------------------------------------
*/
void Kw2000Time()
{
static char i;
Tagkw.MScount++;
//字节间距满发送下一字节
if( Tagkw.Flashset && ( Tagkw.MScount >= (int)( Tagkw.Btyetime/T0TIME )) )
{
if( !Tagkw.Waitsend )
{
return;
}
SCIsendin( Tagkw.Waitsend[Tagkw.Count] );
Tagkw.Count++;
if( Tagkw.Count >= Tagkw.Lenth ) //发送完毕
{
Tagkw.Count = 0;
Tagkw.Lenth = 0;
Tagkw.Waitsend = NULL;
}
else
{
//NULL
}
}
//请求链路时间满发送保持链路
else if( Tagkw.MScount > (int)( Tagkw.HoldT/T0TIME ) && Tagkw.hold[0] )
{
Tagkw.MScount = 0;
Tagkw.Count = 0;
Tagkw.Lenth = KW_Getlen( Tagkw.hold );
Tagkw.Waitread = NULL;
Tagkw.Waitsend = Tagkw.hold;
Tagkw.Chksum = 0;
for( i=0; i<Tagkw.Lenth-1; i++ )
{
Tagkw.Chksum += Tagkw.Waitsend[i];
}
Tagkw.Waitsend[i] = Tagkw.Chksum;
Tagkw.Count = 0;
SCIsendin( Tagkw.Waitsend[Tagkw.Count++] ); //发送第一字节
Tagkw.Flashset = 1; //发送数据更新就绪
}
else
{
//NULL
}
}
/*
**-----------------------------------------------------------------------------------------
** 协议串口中断函数
**-----------------------------------------------------------------------------------------
*/
void Kw2000Scon()
{
Tagkw.MScount = 0;
//串口接收中断
if( SCIRE() )
{
if( !Tagkw.Waitread ) return;
Tagkw.Waitread[Tagkw.Count] = SCIreadin();
if( Tagkw.Waitread[0] ==0x80 )
{
if( Tagkw.Count == 3 ) Tagkw.Lenth = KW_Getlen( Tagkw.Waitread );
}
else if( Tagkw.Count == 0 )
{
Tagkw.Lenth = KW_Getlen( Tagkw.Waitread );
}
Tagkw.Count++;
if( Tagkw.Count >= Tagkw.Lenth ) //接收完毕
{
Tagkw.Count = 0;
// Kw2000 协议 ECU 忙标志
if( Tagkw.Waitread[0] >0x80 && Tagkw.Waitread[3] == 0x7f ) return;
if( Tagkw.Waitread[0] ==0x80 && Tagkw.Waitread[4] == 0x7f ) return;
// Kw2000 协议 ECU 忙标志
Tagkw.Lenth = 0;
Tagkw.Readset = 1;
Tagkw.Waitread = NULL;
}
}
//串口发送
else if( SCISE() )
{
if( !Tagkw.Waitsend ) //发送完毕
{ //注意: 程序经典错误 <时间性的控制错误> 逻辑上没有问题的中断代码在模拟运行时
//必须考虑中断响应存在响应时间,以下发送流程解晰
//向串口发送数据由定时器引发
//定时器发送数据0 | 中断响应时间 | 定时器发送数据1 | 中断响应时间 |
// -串口中断0 -串口中断1
//可以看到实际的发送 2 个字节数据 完毕是在 串口中断1 而并不是在 定时器发送数据1 的定时中断内
//所以若以定时中断为基准判断收发标记
//理论上已经下达 了 2次发送请求,但实际在串口中断1响应前只完成发送一次数据
//这时误以为已经发送完毕而打开接收的话,如果程序执行时间 小于 中断响应时间 就会
//在 串口中断1 产生之前允许接收,在单工总线情况下就会误收到乱数
Tagkw.Flashset = 0;
}
}
}
//----------------------------------------------------------------- End Of File -----------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -