📄 protocol686a.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 + -