|
楼主 |
发表于 2009-12-7 21:20:06
|
显示全部楼层
为了争取下裤子。。。发点正在测试中的源代码吧,全部详细注释好的主芯片mega128,串口1用于与上位机相连,串口0用于与K线相连,电压比较器与K线的接法如下图:
电路很简单,那个2.5V基准也是用单片机电源电阻分压分出来的 (原文件名:Kline.jpg)
下面是时序:
时隙:每帧之间时隙是固定的 (原文件名:time.jpg)
程序对定时很有要求,无论是初始化,发送与接收,在标准协议里都有定义~
下面是详细注释工作过程的代码:
#define RX_BEGIN_BYTE 0XAA
void sendchar1(unsigned char c) //串口1发送与计算机相连
{
UDR1 = c;
while(!(UCSR1A & 0x40));
}
void sendchar0(unsigned char c) //串口0发送与KWP2000相连
{
UDR0 = c;
while(!(UCSR0A & 0x40));
}
#pragma ctask delay /*delay dt+1 us */
void delay(unsigned int dt)
{
while(dt)
{
WDR(); //ICC编译器 复位看门狗 喂狗
NOP();
NOP();
NOP();
dt--;
}
}
#pragma ctask wakeup //150ms
void wakeup(void)
{
delay(50000);
delay(50000);
delay(50000);
delay(50000);
delay(50000);
delay(50000);
}
void watchdog_init(void)
{
WDR();
WDTCR = 0x0f;
}
/*******************************************************
MAIN PROGRAM
********************************************************/
unsigned char rev[256],send[100],revhead,revtail,send_byte,hostbuf[20]; //接收数据包的长短,发送头尾,
unsigned char csc,cp,tempcsc; //CRC校验 CP指针
unsigned char combyte23[6]= {0x82,0x11,0xf1,0x1a,0x80,0x1e}; /* read ECU ID */
struct data
{
unsigned bit0:1; /* receive period or send period, 0: send ; 1: receives收发状态控制*/
unsigned bit1:1; /* receiving or waiting , 0: waiting, 1: receive the first byte */
unsigned bit2:1; /* receive end, 0: not ,1: receive end,may send data to host K线帧已经收到*/
unsigned bit3:1; /* receiving the host command 0: waiting,1: receiving */
unsigned bit4:1; /* indication the host com buffer have data 来自主机的帧已经收到*/
unsigned bit5:1; /* 600 ms send tester present保持在线? command to ECU */
unsigned bit6:1; /* */
unsigned bit7:1;
}mfig;
/**************************************************************
MAIN FUNCTION START
***************************************************************/
void main( void ) /* */
{
unsigned char c_char,i;
DDRA = 0x00;
PORTA = 0xff;
DDRB = 0x00;
PORTB = 0xff;
DDRC = 0x07;
PORTC = 0xff;
DDRD = 0x00;
PORTD = 0xff;
DDRE = 0x00;
PORTE = 0xff;
mfig.bit0 = 0;
mfig.bit1 = 0;
mfig.bit2 = 0;
mfig.bit3 = 0;
mfig.bit4 = 0;
mfig.bit5 = 0;
mfig.bit6 = 0;
for(i=0;i<27;i++)
{
wakeup(); /* Wait for Initial finish 7800ms */
}
/******************************************/
watchdog_init();
OCR0 = 0x4e; /* 78 * 1024/8 = 10ms 10ms 定时,用于检测ECU是否已经结束应答帧*/
TCCR0 = 0x0f; /*ctc模式,1024分频*/
TCNT0 = 0x00;
TIMSK &= ~0x02; /* disable T/C0 cmp 输出比较中断int*/
TCCR3B = 0x05; /* 1024 prescale 128*(ffff-edb0)=600ms*/
TCNT3H = 0xed;
TCNT3L = 0xb0;
ETIMSK |= 0x04; //T/C3溢出中断使能
UCSR1A |= 0x02; /* UART1 init 分频因子8 倍速*/
UCSR1B = 0x98; /* RXCIE1,RXEN1,TXEN1接收中断使能 使能收发*/
UCSR1C = 0b00110110; //8位,奇校验
UBRR1H = 0x00;
UBRR1L = 0x10; /*14400 70us/bit */ //与上位机的通讯使用14400波特率
UCSR0A &= ~0x02; /* UART0 init 分频因子 16 */
UCSR0B = 0x98; //接收中断使能,使能收发
UCSR0C = 0x06; //8位
for(i=0;i<100;i++)
rev=0;
revhead=revtail=0; /* buffer pointer init*/
delay(5000);
sendchar1(0xaa); //TEST *******1发送AA 56 00 间隔1us
delay(1000);
sendchar1(0x56);
delay(1000);
sendchar1(0x00);
asm("sei"); //开中断 等待HOST发来的数据
hostbuf[3] = 0x00; //先初始化host缓冲3为00
while(!mfig.bit4) //host缓冲未接收完,一直等待不断喂狗?
{
NOP();
NOP();
NOP();
WDR();
};
while(hostbuf[3]!=0x55) /* Wait for Kline Start command 没收到开始K线的通讯 一直等待*/
{
mfig.bit4 = 0; //清host缓冲标志位
while(!mfig.bit4)
{
NOP();
NOP();
NOP();
WDR();
};
}
mfig.bit4 = 0x00; //清HOST缓冲标志
asm("cli"); //关中断
wakeup();
WDR();
wakeup(); /* delay 300 ms */
asm("sei"); /* ENABLE INTERRUPT*/
delay(1000);
sendchar1(0x56); //TEST *******3 Kline Start Flag告知主机k 线开始初始化
delay(1000);
sendchar1(0xaa);
delay(1000);
sendchar1(0x00);
/*************************************************/
UBRR0H = 0x0a; //初始化串口0,200baud
UBRR0L = 0x3a;
WDR();
send_byte = 0xf0;
sendchar0(send_byte); /* wake up pulse */
delay(5000); /* delay 5 ms */
UBRR0H = 0x00;
UBRR0L = 0x30; /* baud rate 10400 */
/*************************************************/
WDR();
send_byte = 0x81;
sendchar0(send_byte); /* send start communication commmand */
sendchar1(send_byte); //把初始化帧头发给HOST
delay(5000);
send_byte = 0x11;
sendchar0(send_byte);
delay(5000);
send_byte = 0xf1;
WDR(); //喂狗
sendchar0(send_byte);
delay(5000);
send_byte = 0x81;
sendchar0(send_byte);
delay(5000);
send_byte = 0x04;
sendchar0(send_byte);
delay(5000); /* start communication end */
mfig.bit0 = 1; /* send data over, enter receive period 进入收状态*/
mfig.bit2 = 0; //状态位初始化K线帧未收完
mfig.bit5 = 0; //暂时不需要发送保持在线信息
WDR(); //喂狗,这时其实是开始对ECU回应时间的计数,2s无回应说明连接不上,单片机复位
while(!mfig.bit1) //等待接收K线上的数据,没收到则一直等待
NOP(); //超时会导致看门狗复位
sendchar1(0x52); //******2 发送现在的工作状态,已经开始接收
TIMSK |= 0x02; //开T0比较中断
while (!mfig.bit2) //等待10ms
NOP();
sendchar1(0xff); //通知主机已经接到响应帧,原版程序未分确认帧和消极帧
delay(1000);
while((revhead)!=revtail) /* if buffer is not empty then send to host */
{
sendchar1(rev[revtail++]); //这里也可以不向主机发送
//revtail++;
if(revtail==0x100) revtail=0;
delay(1000);
}
/******************************进入kwp2000收发主循环************************************/
WDR();
while(1)
{
if(mfig.bit4 ==1 && hostbuf[3]==0x55) //;Kline Reset Command 主机帧已近收到,并且是一个复位帧
{
mfig.bit4 = 0x00; //清标志
asm("cli"); //关中断
wakeup();
WDR();
wakeup(); /* delay 300 ms */
asm("sei"); /* ENABLE INTERRUPT*/
delay(1000);
sendchar1(0x56); //TEST *******3 Kline Start Flag
delay(1000);
sendchar1(0xaa);
delay(1000);
sendchar1(0x00);
/***************************************************/
UBRR0H = 0x0a; //初始化串口1,200baud
UBRR0L = 0x3a;
send_byte = 0xf0;
sendchar0(send_byte); /* wake up pulse */
delay(5000); /* delay 5 ms */
UBRR0H = 0x00;
UBRR0L = 0x30; /* baud rate 10400 */
/*************************************************/
send_byte = 0x81;
sendchar0(send_byte); /* send start communication commmand */
delay(5000);
send_byte = 0x11;
sendchar0(send_byte);
delay(5000);
send_byte = 0xf1;
sendchar0(send_byte);
delay(5000);
send_byte = 0x81;
sendchar0(send_byte);
delay(5000);
send_byte = 0x04;
sendchar0(send_byte);
delay(5000); /* start communication end */
mfig.bit0 = 1; /* send data over, enter receive period */
mfig.bit2 = 0;
mfig.bit5 = 0;
WDR();
while(!mfig.bit1)
NOP();
TIMSK |= 0x02; //开T0中断
while (!mfig.bit2)
NOP();
delay(1000);
while((revhead)!=revtail) /* if buffer is not empty then send to host */
{
sendchar1(rev[revtail++]); //
// revtail++; //
if(revtail==0x100) revtail=0; //接收缓冲的大小为256
delay(1000);
}
mfig.bit4 = 0x00;
}
if(mfig.bit4 ==1 && hostbuf[3]!=0x55) /*host buffer have command*/
{
delay(55000); //P3
mfig.bit0 = 0; //进入发状态
mfig.bit1=mfig.bit2=0; //清0与K线收相关的标志位
TIMSK &=~0x02; //关10ms接收中断
WDR();
mfig.bit0 = 0; //进入发中断
switch(hostbuf[1])
{
case 0x55: //hostbuf[4]=Command NO. 长帧代表是一个OBD命令
tempcsc = 0;
for(i=0;i<hostbuf[2]-1;i++) //hostbuf[2]=Command Length
{
switch(i)
{
case 0:
{
send_byte = hostbuf[3]; //Command Mode FMT?
tempcsc += send_byte;
}
break;
case 1:
{
send_byte = 0x11; //Ecu Address
tempcsc += send_byte;
}
break;
case 2:
{
send_byte = 0xf1; //Tester Address
tempcsc += send_byte;
}
break;
case 3:
{ //Command NO. SID
send_byte = hostbuf[1+i];
tempcsc += send_byte;
}
break;
default: //Command type
{
send_byte = hostbuf[1+i];
tempcsc += send_byte;
}
}
sendchar0(send_byte); //Send to Ecu
delay(5000);
}
sendchar0(tempcsc); /* Send Check Sum */
delay(5000);
break;
default:
{
sendchar1(0x55); //if error then send 0x55 to host不是OBD命令
}
}
mfig.bit0 = 1; //收状态
mfig.bit2 = 0;
while(!mfig.bit1) /* Start receive data等待接收*/
{
NOP();
}
TIMSK |= 0x02; /* Start T0 */
while (!mfig.bit2) /* Receive data over */
NOP(); //这里不在喂狗,连接不上,等待死亡
delay(1000);
while((revhead)!=revtail) /* if buffer is not empty then send to host */
{
sendchar1(rev[revtail++]);
if(revtail==0x100) revtail=0;
delay(1000);
}
mfig.bit4 = 0;
WDR();
} /* host buffer have command END*/
if(mfig.bit5) /* send test present to ECU*/
{
delay(50000);
WDR();
mfig.bit0 = 0;
mfig.bit1=mfig.bit2=0;
TIMSK &=~0x02;
mfig.bit0 = 0;
send_byte = 0x81;
sendchar0(send_byte); //send tester present commmand
delay(5000);
send_byte = 0x11;
sendchar0(send_byte);
delay(5000);
send_byte = 0xf1;
sendchar0(send_byte);
delay(5000);
send_byte = 0x3e;
sendchar0(send_byte);
delay(5000);
send_byte = 0xc1;
sendchar0(send_byte);
delay(5000); //tester present end
mfig.bit0 = 1;
mfig.bit2 = 0;
while(!mfig.bit1)
NOP();
TIMSK |= 0x02;
while (!mfig.bit2 )
NOP();
delay(1000);
while((revhead)!=revtail) //if buffer is not empty then send to host
{ sendchar1(rev[revtail++]);//
//revtail++;
if(revtail==0x100) revtail=0;
delay(1000);
}
mfig.bit5 =0;
WDR();
} /* send test present to ECU ****END******/
} /* MAIN LOOP END */
} /* MAIN END */
/********************************************************************
UART0 RX INT 串口0接收中断
*********************************************************************/
#pragma interrupt_handler uart0_rx_isr:19
void uart0_rx_isr(void)
{
unsigned char c_rev;
c_rev = UDR0;
if(mfig.bit0==0) //处于发送状态
{
if(c_rev!=send_byte) /* if send data and data error then repeat send */
{
sendchar0(send_byte);
}
}
else //处于接收状态
{ /* receive data and write to buffer */
rev[revhead++] = c_rev;
if(revhead==0x100) revhead=0;
mfig.bit1 = 1; //接收到Byte,置位标志位
TCNT0 = 0; //
}
}
/*********************************************************************
Timer 0 cmp int 定时器0
**********************************************************************/
#pragma interrupt_handler t0_cmp_isr:16
void t0_cmp_isr(void)
{
if(mfig.bit1) //已经开始接收 10ms中断
mfig.bit2 = 1; //不再有字节的数据再发送,接收完毕 /* set receive over flag */
}
/*********************************************************************
Timer 3 ovf int 用于定时给总线发送数据保持在线
**********************************************************************/
#pragma interrupt_handler t3_ovf_isr:30
void t3_ovf_isr(void)
{
mfig.bit5 = 1; /* send tester present flag 600ms*/
TCNT3H = 0xed;
TCNT3L = 0xb0;
}
/*********************************************************************
UART1 INT(RECEIVE HOST COMMAND) 串口1来自主机的中断 接收中断
***********************************************************************/
#pragma interrupt_handler revhostcom:31
void revhostcom(void)
{
unsigned char c1_rev;
c1_rev = UDR1;
sendchar1(c1_rev); //回复主机主机发送的数据
if((mfig.bit3==0) && (c1_rev == RX_BEGIN_BYTE)) //Search Package Head 正在等待主机命令并且收到帧头AA
{
mfig.bit3 =1; //接收主机命令,为0时为等待命令
cp=0; //cp初始化为0
hostbuf[cp++]= c1_rev; //Store Head Byte hostbuf[0]为帧头
csc = c1_rev; //csc 为循环校验码
}
else //U2
{
if(mfig.bit3 == 1) //non Head Byte
{
if(cp<3) //common command Length=7 byte
{
hostbuf[cp++]= c1_rev;
csc+=c1_rev;
}
else //U3
{
if(hostbuf[1] == 0x55) //long package hostbuf[1]=0x55
{
if(cp < hostbuf[2]) //package length = hostbuf[2]+1
{
hostbuf[cp++]= c1_rev;
csc+=c1_rev;
}
else
{
if(csc == c1_rev) //校验成功
{
mfig.bit4 = 1; //host缓冲有命令
mfig.bit3 = 0; //接收完毕,继续等待主机命令
}
}
}
else if(csc==c1_rev)
{
mfig.bit4 =1; /* flag the package is receive over,buffer have data */
mfig.bit3 =0; /* receive end */
}
}
} //U3
} //U2
} //viod |
|