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

📄 protocol686a.c

📁 汽车电子解码器电缆测试。可以判断汽车故障在哪里
💻 C
字号:
/*****************************************************************************************
 *  目的:686A 68 6A 协议库函数
 *  功能:提供基本 686A 68 6A 协议通讯接口
 *  模块依赖:SCI.h Timer.h
 *  注意:
 ******************************************************************************************/
#include <stdio.h>
#include "compiler.h"
#include "SCI.h"
#include "Timer.h"
#include "Cable.h"
#include "Protocol686A.h"
//#define DEBUG686A
#ifdef DEBUG686A
#include "Display.h"
#endif

#define T0TIME   5                  //定时器初始化时间
//Define Of 686A.State
#define WAITING  0                 //等待状态
#define SENDING  1                 //发送状态
#define READING  2                 //接收状态
static struct ISO686A              //模块数据结构
{
     unsigned char hold[20];       //存放保持链路数据
     unsigned char *Waitsend;      //待发送数据
     unsigned char *Waitread;      //待接收数据
     volatile unsigned char State;          //当前通讯状态
     unsigned char Count;          //发送计数器
     unsigned char Lenth;          //数据包长度
     unsigned char Chksum;         //校验
     volatile int  MScount;        //MS记数
     int           Btyetime;       //字节间距
     int           HoldT;          //链路保持间距
}    Tag686A;

/*
**-----------------------------------------------------------------------------------------
** 初始化 686A 协议通讯模块
**-----------------------------------------------------------------------------------------
*/
void ISO686A_Init( )
{
#ifdef DEBUGMODE
     DebugString( "ISO686A_Init()" );
#endif
     Tag686A.Waitsend = NULL;
     Tag686A.Waitread = NULL;
     Tag686A.State = WAITING;
     Tag686A.Count = 0;
     Tag686A.Lenth = 0;
     Tag686A.Chksum = 0;
     Tag686A.MScount = 0;
     Tag686A.Btyetime = 0;
     Tag686A.HoldT = 1000;
     Tag686A.hold[0] = 0;
}

/*
**-----------------------------------------------------------------------------------------
** 插入 686A 通讯链路
** KeepDig:协议请求方保持链路样本
** HoldTime: 通讯链路保持时间
** 返回: 1
**-----------------------------------------------------------------------------------------
*/
char ISO686A_Maintain( unsigned char *KeepDig, int HoldTime )
{
#ifdef DEBUGMODE
     DebugString( "ISO686A_Maintain()" );
#endif
     unsigned char Len;
     unsigned char i;
     Tag686A.HoldT = HoldTime;
     Len = KeepDig[0];
     if( Len >= 20 )
     {
          return FAIL;
     }
     else
     {
          //NULL
     }
     for( i=0; i<=Len; i++ )
     {
          Tag686A.hold[i] = KeepDig[i];
     }
     return SUCCESS;
}
/*
**-----------------------------------------------------------------------------------------
** 0x55波特触发函数,addr1决定触发ID,PORT为选脚,有成功判定
**-----------------------------------------------------------------------------------------
*/
unsigned char	Iso686A_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();
     }
#ifdef DEBUG686A
unsigned char TempBuf[20];
sprintf( TempBuf, " %2x " , kb2 );
LcdStr86( 1, 1, TempBuf, BLACK );
while( 1 );
#endif
     //触发完后关闭选择L线
     //关闭L线
     delay( 30 );           //等待30毫秒
     kb2 = ~kb2;
     SCIsend( kb2 );        //将后一个K取反回送给汽车校验当前设定拨特率是否正确
     delay( 30 );           //等待ECU将最初5波特发送的ID取反回送
     return SUCCESS;
}
/*
**-----------------------------------------------------------------------------------------
** 686A 通讯连接
** portK:电缆 K 线
** portL:电缆 L 线
** LinkDig:协议请求方通讯连接样本
** SysId:待进入的系统对应ID
**-----------------------------------------------------------------------------------------
*/
char  ISO686A_Link( unsigned char portK,unsigned char portL,unsigned char *LinkDig, unsigned char SysId )
{
     unsigned char Temp[20];
     if( !Iso686A_link( SysId, portK, portL ) )
     {
          TimeRelease();
          SCIRelease();
          return FAIL;
     }
     TimeInit( TIMER0,5 ); //初始化T0 5ms
     SCIload( ISO686AScon );
     TimeLoad( TIMER0, ISO686ATime );
     TimeStart( TIMER0 );
     if( LinkDig )
     {
          ISO686A_Send( LinkDig , 10 );
          if( !ISO686A_Recive( Temp, 800, 20 ) )
          {
               TimeRelease();
               SCIRelease();
               return FAIL;
          }
          else
          {
#ifdef DEBUG686A
unsigned char TempBuf[20];
sprintf( TempBuf, " %2x,%2x,%2x,%2x,%2x" , Temp[0], Temp[1], Temp[2], Temp[3], Temp[4] );
LcdStr86( 1, 1, TempBuf, BLACK );
#endif
          }
     }
     return SUCCESS;
}
/*
**-----------------------------------------------------------------------------------------
** 686A 发送协议包刷新函数
** Dig:待发送数据包
** Lenth:待发送数据长度
** BtyeDst:发送字节间隔( MS )
**-----------------------------------------------------------------------------------------
*/
char  ISO686A_Send( unsigned char *Dig, int BtyeDst )
{
     unsigned char i;
#ifdef DEBUG686A
unsigned char TempBuf[20];
LcdClr();
sprintf( TempBuf, " %2x,%2x,%2x,%2x,%2x" , Dig[0], Dig[1], Dig[2], Dig[3], Dig[4] );
LcdStr86( 1, 16, TempBuf, BLACK );
#endif
     if( !Dig )  return 0;
     Tag686A.MScount = 0;
     while( ( SENDING == Tag686A.State ) && ( Tag686A.MScount < ( Tag686A.HoldT/T0TIME-1 ) ) )  //正在发送,等待一个链路时间单位
     {
          //NULL
     }
     Tag686A.MScount = 0;
     while( ( READING == Tag686A.State ) && ( Tag686A.MScount < ( Tag686A.HoldT/T0TIME-1 ) ) )   //正在接收,等待一个链路时间单位
     {
          //NULL
     }
     if( READING == Tag686A.State )
     {
          return 0; //上一次收发接收失败
     }
     else
     {
          //NULL
     }
     //获取参数
     Tag686A.Waitsend = Dig;
     Tag686A.Btyetime = BtyeDst;
     Tag686A.Lenth = Dig[0];
     //计算校验
     Tag686A.Chksum = 0;
     for( i=1; i<Tag686A.Lenth; i++ )
     {
          Tag686A.Chksum += Tag686A.Waitsend[i];
     }
     Tag686A.Waitsend[i] = Tag686A.Chksum;
     //发送开始
     Tag686A.Count = 1;
     SCIsendin( Tag686A.Waitsend[Tag686A.Count++] ); //发送第一字节
     Tag686A.State = SENDING;
     Tag686A.MScount = 0;
     while( ( SENDING == Tag686A.State ) && ( Tag686A.MScount < ( Tag686A.HoldT/T0TIME-1 ) ) ); //正在发送,等待
     return 1;
}
/*
**-----------------------------------------------------------------------------------------
** 686A 回送协议包接收函数
** Dig:数据包接收位置
** Wtime:接收等待最大时间(MS)
** MaxLen:最大接收长度
**-----------------------------------------------------------------------------------------
*/
char  ISO686A_Recive( unsigned char *Dig, int Wtime, unsigned char MaxLen )
{
     unsigned int WaitTime;
     if( !Dig )  return 0;
     if( Wtime >= Tag686A.HoldT )    Wtime = Tag686A.HoldT;
     while( ( READING == Tag686A.State ) && ( Tag686A.MScount < ( Tag686A.HoldT/T0TIME-1 ) ) )    //正在接收,等待一个链路时间单位
     {
          //NULL
     }
     Tag686A.MScount = 0;
     while( ( SENDING == Tag686A.State ) && ( Tag686A.MScount < ( Tag686A.HoldT/T0TIME-1 ) ) )    //正在发送,等待一个链路时间单位
     {
          //NULL
     }
     WaitTime = Wtime/T0TIME;
     //获取参数
     Tag686A.Waitread = Dig;
     Tag686A.Lenth = 0;
     Tag686A.Count = 1;
     //等待接收完毕
     Tag686A.MScount = 0;
     SCIENcontrol( 1 );
     Tag686A.State = READING;
     while( ( Tag686A.MScount < WaitTime ) && ( Tag686A.State == READING ) )    //指定时间等待接收完毕
     {
          if( Tag686A.Count >= MaxLen )
          {
               Tag686A.Count = 0;
               SCIENcontrol( 0 );
               return FAIL;
          }
     }
     if( READING == Tag686A.State ) return FAIL;
     return SUCCESS;
}
/*
**-----------------------------------------------------------------------------------------
** 协议定时器中断函数
**-----------------------------------------------------------------------------------------
*/
void  ISO686ATime()
{
     static unsigned char i;
     Tag686A.MScount++;
     if( SENDING == Tag686A.State )  //发送状态
     {
          if( Tag686A.MScount >= ( Tag686A.Btyetime/T0TIME ) )  //字节间距满
          {
               if( !Tag686A.Waitsend ) return ;
               SCIsendin( Tag686A.Waitsend[Tag686A.Count] );
               Tag686A.Count++;
               if( Tag686A.Count > Tag686A.Lenth )
               {
                    Tag686A.Count = 1;
                    Tag686A.Lenth = 0;
                    Tag686A.Waitsend = NULL;
               }
          }
     }
     else  if( READING == Tag686A.State )  //接收状态
     {
          if( ( Tag686A.MScount > 10 ) && ( Tag686A.Count != 1 ) ) //5*10MS桢间距无回应代表结束
          {
               Tag686A.Waitread[0] = Tag686A.Count-1;
               Tag686A.Count = 1;
               Tag686A.Lenth = 0;
               Tag686A.Waitread = NULL;
               Tag686A.State = WAITING;
               Tag686A.MScount = 0;
          }
     }
     else  if( WAITING == Tag686A.State )  //等待状态
     {
          if( ( Tag686A.MScount > (int)( Tag686A.HoldT/T0TIME ) ) && Tag686A.hold[0] ) // 握手等待时间满
          {
               Tag686A.MScount = 0;
               Tag686A.Count = 0;
               Tag686A.Lenth = Tag686A.hold[ 0 ];
               Tag686A.Waitread = NULL;
               Tag686A.Waitsend = Tag686A.hold;
               Tag686A.Chksum = 0;
               for( i=1; i<Tag686A.Lenth; i++ )
               {
                    Tag686A.Chksum += Tag686A.Waitsend[i];
               }
               Tag686A.Waitsend[i] = Tag686A.Chksum;
               Tag686A.Count = 1;
               SCIsendin( Tag686A.Waitsend[Tag686A.Count++] ); //发送第一字节
               Tag686A.State = SENDING; //发送数据更新就绪
          }
     }
}
/*
**-----------------------------------------------------------------------------------------
** 协议串口中断函数
**-----------------------------------------------------------------------------------------
*/
void  ISO686AScon()
{
     Tag686A.MScount = 0;
     //串口接收中断
     if( SCIRE() )
     {
          if( Tag686A.Waitread )
          {
               Tag686A.Waitread[Tag686A.Count] = SCIreadin();
          }
          Tag686A.Count++;
     }
     //串口发送中断
     else  if( SCISE() )
     {
          // Sending Last Byte
          if( NULL == Tag686A.Waitsend )     //发送完毕
          {
               if( Tag686A.Waitread )
               {
                    Tag686A.State = READING;
               }
               else
               {
                    Tag686A.State = WAITING;
               }
          }
     }
}

//----------------------------------------------------------------- End Of File -----------

⌨️ 快捷键说明

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