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

📄 protocolkw2000.c

📁 汽车电子解码器电缆测试。可以判断汽车故障在哪里
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************************
 *  目的:KWP2000 协议库函数
 *  功能:提供基本 KWP2000 协议操作接口
 *  模块依赖:SCI.h Timer.h
 *  注意:协议实现部分采用对外查询对内中断方式处理,因为难度太大没有实现对外中断方式的接口
          仅在发送和接收之间留下时间空隙,可在发送和接收之间插入代码,但请保证代码执行时间
          小于协议规定的桢回送时间 P2(0MS~1000MS),否则接收数据将丢失
          Note 2007.10.4. 隐藏BUG 在通讯链路数据回送状态下有数据发送请求将不等待上一次汽车
          的链路请求回送完毕直接发送,此时会导致通讯失败,室内实测时还未出现该情况
 ******************************************************************************************/
#include <stdio.h>
#include "compiler.h"
#include "SCI.h"
#include "Timer.h"
#include "ProtocolKw2000.h"
#include "Cable.h"
#ifdef DEBUGKW2000
#include "Display.h"
#include "Keyboard.h"
#endif

#define   T0TIME    5         //定时器初始化时间
static struct    KW2000       //模块数据结构
{
     unsigned int  HTime;               //触发高电瓶时间
     unsigned int  LTime;               //触发低电瓶时间
     unsigned char hold[20];            //存放保持链路发送数据
     unsigned char *Waitsend;           //待发送数据
     unsigned char *Waitread;           //待接收数据
     volatile unsigned char Flashset;   //发送数据就位标志
     volatile unsigned char Readset;    //接收数据就位标志
     unsigned char Count;               //发送计数器
     unsigned char Lenth;               //数据包长度
     unsigned char Chksum;              //校验
     volatile int  MScount;             //MS记数
     int           Btyetime;            //字节间距
     int           HoldT;               //链路保持间距
}    Tagkw;

/*
**-----------------------------------------------------------------------------------------
** 初始化 KWP2000 协议通讯模块
**-----------------------------------------------------------------------------------------
*/
void KW_Init( )
{
#ifdef DEBUGMODE
     DebugString( "KW_Init()" );
#endif
     Tagkw.Waitsend = NULL;
     Tagkw.Waitread = NULL;
     Tagkw.Flashset = 0;
     Tagkw.Readset = 1;
     Tagkw.Count = 0;
     Tagkw.Lenth = 0;
     Tagkw.Chksum = 0;
     Tagkw.MScount = 0;
     Tagkw.Btyetime = 0;
     Tagkw.HoldT = 1000;
     Tagkw.hold[0] = 0;
     Tagkw.HTime = 24;
     Tagkw.LTime = 25;
}
/*
**-----------------------------------------------------------------------------------------
** 插入 KWP2000 通讯链路
** KeepDig:协议请求方保持链路样本
** HoldTime: 通讯链路保持时间
** 返回: 1
**-----------------------------------------------------------------------------------------
*/
char KW_Maintain( unsigned char *KeepDig, int HoldTime )
{
#ifdef DEBUGMODE
     DebugString( "KW_Maintain()" );
#endif
     unsigned char Len;
     unsigned char i;
     Tagkw.HoldT = HoldTime;
     Len = KW_Getlen( KeepDig );
     if( Len >= 20 )
     {
          return FAIL;
     }
     else
     {
          //NULL
     }
     for( i=0; i<Len; i++ )
     {
          Tagkw.hold[i] = KeepDig[i];
     }
     return SUCCESS;
}
/*
**-----------------------------------------------------------------------------------------
** 0x55波特触发函数,addr1决定触发ID,PORT为选脚,有成功判定
**-----------------------------------------------------------------------------------------
*/
unsigned char KWIso_link( unsigned char addr1,unsigned char portK,unsigned char portL )
{
#ifdef DEBUGMODE
     DebugString( "iso_link()" );
#endif
     unsigned char kb2;
     unsigned char i=0;
     //初始化所需的硬件环境
     TimeDestroy( TIMER0 );
     TimeStop( TIMER0 );
     SCIdestroy();
     //选通 L 线
     ChanSet( portK,portL );
     //打开L线,与K线同步

     SCITXD( THIGH ); delay(500); //一段时间的高电平清总线

     //发送请求的系统ID号
     SCITXD( TLOW ); delay(200); //5波特起始位 //20ms
     //发送请求的系统ID号
     if( ( addr1&0x01 ) != 0 ) SCITXD( THIGH );
     else                      SCITXD( TLOW );
     delay( 200 );//20ms
     if( ( addr1&0x02 ) != 0 ) SCITXD( THIGH );
     else                      SCITXD( TLOW );
     delay( 200 );
     if( ( addr1&0x04 ) != 0 ) SCITXD( THIGH );
     else                      SCITXD( TLOW );
     delay( 200 );
     if( ( addr1&0x08 ) != 0 ) SCITXD( THIGH );
     else                      SCITXD( TLOW );
     delay( 200 );
     if( ( addr1&0x10 ) != 0 ) SCITXD( THIGH );
     else                      SCITXD( TLOW );
     delay( 200 );
     if( ( addr1&0x20 ) != 0 ) SCITXD( THIGH );
     else                      SCITXD( TLOW );
     delay( 200 );
     if( ( addr1&0x40 ) != 0 ) SCITXD( THIGH );
     else                      SCITXD( TLOW );
     delay( 200 );
     if( ( addr1&0x80 ) != 0 ) SCITXD( THIGH );
     else                      SCITXD( TLOW );
     delay( 200 );
     SCITXD( THIGH );
     delay( 200 );  //结束位 200ms
     ChanSet( portK,0 );
     //等待0X55回送 记算动态波特率
     if( !SCIDynamicBuad() )
     {
          return FAIL;
     }
     //接收ECU回应校验拨特率
     TimeInit( TIMER0,10 );    //初始化T0 1ms
     TimeStart( TIMER0 );
     SCIENcontrol( 1 );  //允许读
     for( i=0; i<2; i++ )     //等待汽车反还2个K(k1,k2)
     {
          TimeSet( TIMER0, 0 );
          while( !SCIRE() && !TimeBreak( TIMER0,100 ) )
          {
            //NULL
          }
          if( TimeBreak( TIMER0,100 ) )
          {
            return FAIL;
          }
          kb2 = SCIreadin();
     }
     //触发完后关闭选择L线

     //关闭L线
     delay( 30 );           //等待30毫秒
     kb2 = ~kb2;
     SCIsend(kb2);        //将后一个K取反回送给汽车校验当前设定拨特率是否正确
     delay( 30 );
     return SUCCESS;
}
/*
**-----------------------------------------------------------------------------------------
** KWP2000 快速触发延时设定
** Thigh:快速触发高电瓶延时
** Tlow :快速触发低电瓶延时
**-----------------------------------------------------------------------------------------
*/
void KW_SetLinkTime( unsigned int Thigh, unsigned int Tlow )
{
     Tagkw.HTime = Thigh;
     Tagkw.LTime = Tlow;
}
/*
**-----------------------------------------------------------------------------------------
** KWP2000 通讯连接
** portK:电缆 K 线
** portL:电缆 L 线
** Buadrate:通讯波特率
** LinkDig:协议请求方通讯连接样本
** SysId:待进入的系统对应触发ID
**-----------------------------------------------------------------------------------------
*/
char KW_Link( unsigned char portK, unsigned char portL, unsigned long Buadrate, unsigned char *LinkDig, unsigned char SysId )
{
#ifdef DEBUGMODE
     DebugString( "KW_Link()" );
     unsigned char Rig[50];
#endif
     unsigned char Temp[20] = { 0, 0, 0, 0, 0, 0 };
     int i;
     //KW2000快速触发
     SCIini( Buadrate );         //SCI 10.4K
     TimeInit( TIMER0,5 );    //初始化T0 10ms
     //电缆选通
     ChanSet( portK,portL );
     SCITXD(THIGH);      delay(50);
     SCITXD(TLOW);       delay(Tagkw.LTime);     //低电平
     SCITXD(THIGH);      delay(Tagkw.HTime);     //高电平
     //关闭 L 线
     ChanSet( portK,0 );
     //触发请求数据
     SCIload( Kw2000Scon );
     TimeLoad( TIMER0, Kw2000Time );
     TimeStart( TIMER0 );
     //发送触发数据
     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; //发送数据更新就绪
     if( KW_Read( Temp, 800, 20 ) == SUCCESS )    //快速触发成功
     {
          return SUCCESS;
     }
     else
     {
#ifdef DEBUGKW2000
          sprintf( Rig,"%x,%x,%x,%x,%x",Temp[0],Temp[1],Temp[2],Temp[3],Temp[4] );
          LcdStr86( 1, 0, Rig, BLACK );
          TimeRelease();
          SCIRelease();
          GetAKey( 0 );
#endif
          //NULL
     }
     TimeRelease();
     SCIRelease();
     delay( 5000 ); //等待ECU冷却

⌨️ 快捷键说明

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