amoBBS 阿莫电子论坛

 找回密码
 注册
搜索
bottom↓
查看: 31526|回复: 182

有没有搞过汽车电子K-Line编程的?上传些OBD诊断仪的资料,抛砖引玉~

  [复制链接]
发表于 2009-12-2 11:10:27 | 显示全部楼层 |阅读模式
最近在调试基于K-Line 的KWP2000协议,遇到些问题,主要在于协议对定时的要求较高,有很多错误处理,有没有这方面的高手交流下?
下面是我找到的一些资料,包括数据链路层协议,使用AVR实现的代码,等等。
这个是标准的协议:
点击此处下载 ourdev_509815.rar(文件大小:928K) (原文件名:ISO14230.rar)
这个是好像是使用AVRmega8实现的,老外做的,但是我没下到原理图,。。。有下到这个原理图资料的能不能分享下? 这个代码有很好的参考作用。
点击此处下载 ourdev_509816.rar(文件大小:17K) (原文件名:AVRISO_SourceCode.rar)
这个貌似是国内的人改的,用mega128做的现在看得还不是很明白;
点击此处下载 ourdev_509817.rar(文件大小:3K) (原文件名:ATmega128&K.rar)
希望有做过这方面高手出来分享点资料和demo 代码,偶现在对这个协议每帧之间的定时,如何判断总线状态,监视总线有些疑问。。
 楼主| 发表于 2009-12-2 11:18:46 | 显示全部楼层
K-Line的硬件电路一般比较简单,串口的收发信号通过电压比较器转成单线12V或者24V电平来传输。也有汽车级的专用芯片。
上传个直接用FT232做的例子:

(原文件名:kwp2k_flasher_clon_schema.png)
这个是老外的电路,上位机直接使用串口API可以实现协议。
下位机使用单片机或者ARM做协议转换和数据处理更有好处,这样定时更精确,同时可以减轻上位机的负担,上位机专门从串口取数据在GUI上显示就可以了。
下位机还可以实现更多的协议,比如VPW,PWM,CANBUS等等。
 楼主| 发表于 2009-12-2 11:23:16 | 显示全部楼层
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3363429&bbs_page_no=1&search_mode=1&search_text=VPW&bbs_id=1000
这个是我以前上传的。。VPW转232。。。
发表于 2009-12-2 11:28:17 | 显示全部楼层
MARK一下,LZ做汽车诊断仪?
发表于 2009-12-2 11:35:26 | 显示全部楼层
如果不上操作系统,汽车诊断有什么难的,就是烦而已。
KWP2000,15765,协议都挺烦的,我个人觉得做诊断仪的人,都是性子特别好,
有耐心的人,烦在哪里呢?一个诊断仪要诊断几个系列的车型,而且一个车型上的电器协议也有的不兼容,这个是联电搞的,那个是博士搞得,这个是自己搞的,真是超级烦,标准的代码工人,像堆积木一样。
 楼主| 发表于 2009-12-2 11:38:45 | 显示全部楼层
正在做相关的研究呢。。。
发表于 2009-12-2 13:05:13 | 显示全部楼层
mark
 楼主| 发表于 2009-12-2 14:09:26 | 显示全部楼层
干脆上传老外做的USB—K线诊断仪的全套资料吧

(原文件名:kwp2k_flasher_clon_partplace.png)


(原文件名:kwp_clon_permited.png)

点击此处下载 ourdev_509901.rar(文件大小:1.86M) (原文件名:How To Build your KWP2000 Clone.rar)
 楼主| 发表于 2009-12-2 14:11:40 | 显示全部楼层
继续上传~国外著名的上位机软件Scantool的源代码,C语言写的。。。
点击此处下载 ourdev_509903.rar(文件大小:153K) (原文件名:source.rar)
 楼主| 发表于 2009-12-2 14:14:46 | 显示全部楼层
继续上传,一些国外相关的论文与制造资料~
这个也是AVR做的,主芯片是AT90CAN128,我这里也整理下上传上来~
这是有关这个诊断仪的论文:
点击此处下载 ourdev_509907.rar(文件大小:138K) (原文件名:AVR OBDII Documentation 2.rar)
下面是包括原理图,全部源代码:
点击此处下载 ourdev_509911.rar(文件大小:599K) (原文件名:obd-ii.rar)

(原文件名:obdii_avr_pcb.jpg)


(原文件名:obdii_avr_rpm.jpg)
 楼主| 发表于 2009-12-2 14:29:57 | 显示全部楼层
再上传,SAEJ1939培训教程,这个是基于CANBUS的,应用很广泛,这个教程也非常清晰明了,比看枯燥的协议好多了~
点击此处下载 ourdev_509914.pdf(文件大小:2.10M) (原文件名:SAE J1939协议培训教程.pdf)
 楼主| 发表于 2009-12-2 14:35:24 | 显示全部楼层
还有一些讲的很详细的论文,国内的论文太粗略了,,这些花了我不少时间在网上找呢。希望有做过汽车诊断开发的出来一起讨论,借助阿莫的网站平台共享资料,一起提高~
点击此处下载 ourdev_509915.pdf(文件大小:230K) (原文件名:14230物理层数据链路层设计.pdf)
点击此处下载 ourdev_509916.pdf(文件大小:176K) (原文件名:232转K线设计.pdf)
点击此处下载 ourdev_509917.pdf(文件大小:200K) (原文件名:OBD2接口适配器设计.pdf)
点击此处下载 ourdev_509918.pdf(文件大小:144K) (原文件名:OBDII.pdf)
发表于 2009-12-2 14:41:53 | 显示全部楼层
强烈支持LZ,,,
发表于 2009-12-2 17:11:54 | 显示全部楼层
是用K线还是CAN线?
发表于 2009-12-2 17:19:23 | 显示全部楼层
学习了,谢谢LZ
 楼主| 发表于 2009-12-2 18:29:19 | 显示全部楼层
【13楼】 huangqi412
积分:171
派别:
等级:------
来自:湖南 湘潭
是用K线还是CAN线?  
------------------------------------------------------
我现在正在研究的是基于K线的KWP2000协议,CAN总线的最近刚刚调通,基于J1939协议的,不过还没拿ECU试呢。
目前K线的遇到些麻烦,就是每帧之间的时隙,错误处理等等。
 楼主| 发表于 2009-12-2 18:32:10 | 显示全部楼层
【4楼】 USB_Study

积分:63
派别:
等级:------
来自:
如果不上操作系统,汽车诊断有什么难的,就是烦而已。
KWP2000,15765,协议都挺烦的,我个人觉得做诊断仪的人,都是性子特别好,
有耐心的人,烦在哪里呢?一个诊断仪要诊断几个系列的车型,而且一个车型上的电器协议也有的不兼容,这个是联电搞的,那个是博士搞得,这个是自己搞的,真是超级烦,标准的代码工人,像堆积木一样。
---------------------------------------------------------------------------------
协议枯燥而繁杂,但是这是工作与责任,设计可靠与稳定的诊断仪是要花很多心思的。
发表于 2009-12-2 19:44:58 | 显示全部楼层
jh
发表于 2009-12-2 19:52:03 | 显示全部楼层
这个帖子比较有分量的.国内的应该是金德与另外一家做得最好.其中金德号召已经被BOSCH收购了。
发表于 2009-12-2 19:54:58 | 显示全部楼层
顶下~~~
发表于 2009-12-2 19:59:30 | 显示全部楼层
mark
发表于 2009-12-2 20:48:29 | 显示全部楼层
mark
发表于 2009-12-2 21:43:39 | 显示全部楼层
使用状态机,KWP2k协议栈每10ms调用一次,用软定时器来控制P2,P2*,以及P3.

:) 另外你们的诊断仪是给那些车型开发的?
发表于 2009-12-2 21:52:08 | 显示全部楼层
KWP2K属于过气的协议,现在的趋势是UDS:-)
VW的新的ECU中协议也多是UDS啦
 楼主| 发表于 2009-12-2 22:18:03 | 显示全部楼层
【22楼】 modelfly
使用状态机,KWP2k协议栈每10ms调用一次,用软定时器来控制P2,P2*,以及P3.  

:) 另外你们的诊断仪是给那些车型开发的?
---------------------------------------------------------------------------------------
KWP2K协议栈.。。请教下是指写好的程序包么。。。有参考Demo么。
关于车型,,,这个和老板签了保密协议。。哎。
发表于 2009-12-3 15:43:03 | 显示全部楼层
【24楼】 powerSTM 农夫山拳

KWP2K协议栈.。。请教下是指写好的程序包么。。。有参考Demo么。

这个就不好意思,是不能释放的:-(,不过关于编程的思路可以在论坛中搜索状态机相关的讨论。

欢迎进一步讨论
发表于 2009-12-3 16:01:18 | 显示全部楼层
MARK 强
发表于 2009-12-3 16:12:58 | 显示全部楼层
mark~学习~
发表于 2009-12-3 18:23:24 | 显示全部楼层
不错,学习.
发表于 2009-12-3 18:40:39 | 显示全部楼层
mark,牛人啊
发表于 2009-12-3 19:35:21 | 显示全部楼层
K 线主要就是前面的5 波特率同步吧,同步后就是状态机的处理 以及对数据帧的间歇时间已经每个byte 的间歇时间 等差错处理的时间控制了,。,前几个月接触过这个东西,了解了下,后面项目停了就没看了。。
发表于 2009-12-4 15:48:43 | 显示全部楼层
mark一下,顶上去
发表于 2009-12-4 15:58:53 | 显示全部楼层
搞OBD协议是用什么做测试的,买个ECU,还是直接上车做测试?
发表于 2009-12-4 16:04:27 | 显示全部楼层
貌似现在都用CAN
 楼主| 发表于 2009-12-4 19:40:30 | 显示全部楼层
32楼】 ep1c3
积分:50
派别:
等级:------
来自:
搞OBD协议是用什么做测试的,买个ECU,还是直接上车做测试?  
------------------------------------------------------------------
开发阶段还是直接在ECU接上去测试的,当然,一般还会接上去些外设,比如用滑动变阻器来代替模拟量传感器,按钮开关代替开关量,LED显示开关量输出之类的。
 楼主| 发表于 2009-12-4 19:42:17 | 显示全部楼层
【33楼】 snail0204 瓜牛

积分:531
派别:
等级:------
来自:江苏
貌似现在都用CAN  
----------------------------------------------------------------
CAN是趋势,不过目前还有很多车是基于K线的。未来FlexRay是发展方向,基于CAN的也有很多协议呢~
 楼主| 发表于 2009-12-4 19:43:39 | 显示全部楼层
【25楼】 modelfly
积分:82
派别:
等级:------
来自:
【24楼】 powerSTM 农夫山拳

KWP2K协议栈.。。请教下是指写好的程序包么。。。有参考Demo么。

这个就不好意思,是不能释放的:-(,不过关于编程的思路可以在论坛中搜索状态机相关的讨论。

欢迎进一步讨论

__________________________

没关系~我自己再多啃啃协议,码点代码做做实验。
发表于 2009-12-4 22:47:00 | 显示全部楼层
不懂,标记一下。
发表于 2009-12-5 11:37:13 | 显示全部楼层
去年在一家公司里也做这方面的,是针对大众的车型,K线、和CAN方面的。不过可惜的是我没参与。
发表于 2009-12-5 11:44:29 | 显示全部楼层
汽车诊断仪会火
 楼主| 发表于 2009-12-7 15:39:23 | 显示全部楼层
【22楼】 modelfly
积分:82
派别:
等级:------
来自:
使用状态机,KWP2k协议栈每10ms调用一次,用软定时器来控制P2,P2*,以及P3
-------------------------------------------------------------------------------------------
请教下modelfly  协议栈为什么每10ms 要调用一次?
发表于 2009-12-7 15:45:50 | 显示全部楼层
mark
发表于 2009-12-7 18:58:23 | 显示全部楼层
好东东,建议莫哥给LZ一条裤子穿穿。
 楼主| 发表于 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
 楼主| 发表于 2009-12-7 21:28:15 | 显示全部楼层
驱动电路和原理图和通讯时隙图不太刷得不出来了。。。
啥时候才俺才能申请个裤子呢,,,
发表于 2009-12-10 14:12:38 | 显示全部楼层
LZ能不能再贴下图片,感兴趣.
发表于 2009-12-10 15:50:41 | 显示全部楼层
很好阿,支持楼主
发表于 2009-12-10 16:35:17 | 显示全部楼层
你的图片没了啊? 在发一次咯! 想在看看!
发表于 2009-12-10 19:05:40 | 显示全部楼层
没弄过KWP2000,做过基于ISO15765诊断代码的测试
发表于 2009-12-10 19:47:40 | 显示全部楼层
MARK下
这个跟ODB 是不是一个概念呀
发表于 2009-12-10 23:24:16 | 显示全部楼层
支持楼主~~~
发表于 2009-12-11 11:03:40 | 显示全部楼层
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位  


UBRR0H = 0x0a;            //初始化串口0,200baud
UBRR0L = 0x3a;


UBRR0H = 0x00;
UBRR0L = 0x30;           /* baud rate 10400 */


老兄,这个咋回事, 波特14400 倍频, UCSR1推出来晶振是2M, 200或者10400,不倍频, UCSR2推出来晶震是8M
发表于 2009-12-11 11:05:03 | 显示全部楼层
#pragma ctask wakeup                //150ms
void wakeup(void)


这里注释150MS  但6*50000=300MS 后面也注释300MS,,,
发表于 2009-12-26 16:42:34 | 显示全部楼层
回复【4楼】USB_Study
-----------------------------------------------------------------------

还与个人脾气有关啊!呵呵!看来我不行了。
发表于 2009-12-26 16:45:53 | 显示全部楼层
对了,大家知不知道,K-LINE现在都用什么芯片啊?能不能推荐一下芯片型号啊?

谢谢!
发表于 2009-12-26 18:20:56 | 显示全部楼层
mark
发表于 2010-1-5 21:55:39 | 显示全部楼层
【54楼】 I silence
积分:2
派别:
等级:------
来自:
对了,大家知不知道,K-LINE现在都用什么芯片啊?能不能推荐一下芯片型号啊?

谢谢!  

比较便宜的有ST的L6937
 楼主| 发表于 2010-1-5 22:42:03 | 显示全部楼层
上面的测试程序有点小问题,但是思路已经很清楚,硬搬意义不在,偶正在把这个朝ARM上移植。
发表于 2010-1-6 12:50:05 | 显示全部楼层
Good title.Mark
发表于 2010-1-6 13:41:46 | 显示全部楼层
试过J1939故障诊断  我也想搞搞can诊断工具呢
发表于 2010-1-6 13:56:06 | 显示全部楼层
Mark
发表于 2010-2-2 23:20:01 | 显示全部楼层
关注一下
貌似现在的小车 很多都是can总线吧?

很好的资料 谢谢
发表于 2010-2-3 02:55:00 | 显示全部楼层
关注一下
发表于 2010-4-5 22:03:28 | 显示全部楼层
to  powerSTM 农夫山拳:
自己最近用L6937D搭了个电路,还利用TJA1021搭了个LIN的电路,还不知道对不对??
可以把你的电路发给我参考下?或者您 留个联系方法,对我的图给点意见,谢谢!
nichunhua1981@sohu.com
发表于 2010-4-15 14:20:29 | 显示全部楼层
我这里用一根串口转K的线进行初始化,单片机是飞思卡尔的,程序如下,但是无法收到回复,请各位大侠看看有没有什么问题

  back0=AS1_SendChar(0xf0);/*波特率200情况下发送0xf0,原波特率为200*/
  Cpu_Delay100US(500);/*延时50ms*/
  
  
  SCI0BD = 96;                         /* 设置波特率10400 */
  
  back1=AS1_SendChar(0x81);     /*发送请求command,每个发送字节之间延时5ms*/

  Cpu_Delay100US(50);
  
   back2=AS1_SendChar(0x11);

  Cpu_Delay100US(50);
  
   back3=AS1_SendChar(0xf1);

  Cpu_Delay100US(50);
  
  back4=AS1_SendChar(0x81);

  Cpu_Delay100US(50);
  
  back5=AS1_SendChar(0x04);
发表于 2010-4-15 14:36:55 | 显示全部楼层
新奇!mark!标记!
 楼主| 发表于 2010-4-15 18:39:06 | 显示全部楼层
回复【63楼】chunnynee
-----------------------------------------------------------------------

我是用LM339/LM393的。用在一个产品上了,另外一个新产品已经测试了几个月了,没问题。
发表于 2010-4-15 20:25:59 | 显示全部楼层
mark
 楼主| 发表于 2010-4-17 22:37:30 | 显示全部楼层
回复【64楼】call03
我这里用一根串口转K的线进行初始化,单片机是飞思卡尔的,程序如下,但是无法收到回复,请各位大侠看看有没有什么问题
  back0=AS1_SendChar(0xf0);/*波特率200情况下发送0xf0,原波特率为200*/
  Cpu_Delay100US(500);/*延时50ms*/
   
   
  SCI0BD = 96;                         /* 设置波特率10400 */
   
  back1=AS1_SendChar(0x81);     /*发送请求command,每个发送字节之间延时5ms*/
  Cpu_Delay100US(50);
   
   back2=AS1_SendChar(0x11);
  Cpu_Delay100US(50);
   
   back3=AS1_SendChar(0xf1);
  Cpu......
-----------------------------------------------------------------------

可以用示波器看看时序,Cpu_Delay100US(500);/*延时50ms*/ 这个好像有点长了,我用LPC ARM做发完0xF0延时只需要3ms即可。
发表于 2010-4-17 23:42:32 | 显示全部楼层
PowerSTM 有接触过 ELM327 这颗芯片吗?

这个不是集成了很多种总线和协议了吗?直接使用这样的芯片行不行?
发表于 2010-4-18 00:06:04 | 显示全部楼层
mark
 楼主| 发表于 2010-4-19 11:34:27 | 显示全部楼层
回复【69楼】STM32_Study
PowerSTM 有接触过 ELM327 这颗芯片吗?
这个不是集成了很多种总线和协议了吗?直接使用这样的芯片行不行?
-----------------------------------------------------------------------

知道,我还买了一套,但是其实这个片子是对北美车型的协议开发,我们上车进行了实际测试,很多车子测不出来。甚至包括VPW,15765.
ELM327其实就是PIC带CAN的单片机开发的。
发表于 2010-4-19 16:12:33 | 显示全部楼层
回复【71楼】powerSTM 农夫山拳

知道,我还买了一套,但是其实这个片子是对北美车型的协议开发,我们上车进行了实际测试,很多车子测不出来。甚至包括VPW,15765.
ELM327其实就是PIC带CAN的单片机开发的。
-----------------------------------------------------------------------

哦?是为什么呢?国内的车子不符合标准协议吗?还是elm327 不符合协议?

测不出来,是指整个没法通信?还是说有部分参数无法读取?
 楼主| 发表于 2010-4-19 18:18:09 | 显示全部楼层
回复【72楼】STM32_Study
回复【71楼】powerSTM 农夫山拳
知道,我还买了一套,但是其实这个片子是对北美车型的协议开发,我们上车进行了实际测试,很多车子测不出来。甚至包括VPW,15765.  
ELM327其实就是PIC带CAN的单片机开发的。
-----------------------------------------------------------------------
哦?是为什么呢?国内的车子不符合标准协议吗?还是elm327 不符合协议?
测不出来,是指整个没法通信?还是说有部分参数无法读取?
-----------------------------------------------------------------------

某些厂商修改了协议,ELM327无法获得正确的信息,无法识别出协议,自然无法通讯
发表于 2010-4-22 15:40:37 | 显示全部楼层
回复【68楼】powerSTM 农夫山拳
-----------------------------------------------------------------------

谢谢,这个问题已经解决,一方面用示波器看了一下时序,还是不严谨,改了个别数字之后可以了。
但是我现在只能从示波器处看到数据(K线端的发送和回复都看得到),K转RS232上并未收到数据(串口端只看得到发送,没有看到回复),请问是否还需要对串口进行其他操作,比如置高或置低某脚的电平。
发表于 2010-4-28 12:10:24 | 显示全部楼层
LS,81 11 f1 81 04 是开始通信对吧.
如何获取故障码?该发什么数据?
发表于 2010-5-10 19:11:34 | 显示全部楼层
powerSTM 农夫山拳:
我现在用Fast initialization方式已经和ECU建立通信了,但5 Baud initialization还没实现??单片机好像也没法到这么低的波特率呢?请问您是如何实现的呢??
发表于 2010-5-10 20:01:36 | 显示全部楼层
逻辑高低模拟一下5pbs
发表于 2010-5-10 20:16:10 | 显示全部楼层
我也正在尝试。
假设当前串口工作在5 baud,那应该发送的数据时什么? 是0x33吗?
发表于 2010-5-10 20:35:21 | 显示全部楼层
汗,我们也是做汽车电子,不过只是做空调的,学习。。。。。。。。。。
发表于 2010-5-10 21:33:58 | 显示全部楼层
好东东,直得研究
发表于 2010-5-10 21:39:50 | 显示全部楼层
mark
发表于 2010-5-24 21:02:51 | 显示全部楼层
回复【楼主位】powerSTM 农夫山拳
-----------------------------------------------------------------------

我利用Fast initialization初始化ECU后,发送Start Communication命令后,ECU有正确的积极响应。
但随后发送任何命令,譬如Access Timing Parameter,ECU没有任何响应,请问为什么呢?发送的命令波形是正确的,通信速率是10400,我现在是没辙了??请问有什么建议能让我前进呢。

已经搞定,还是定时的问题。
发表于 2010-5-28 15:08:53 | 显示全部楼层
哈哈 我去年底也做了一个行车显示器 也是用K线通讯的 现在一直工作的很OK 配BOSH M7 ECU的
发表于 2010-5-28 19:29:55 | 显示全部楼层
回复【83楼】Melin 秀秀
-----------------------------------------------------------------------

请问秀秀利用5 Baud 方式对ECU进行初始化的时候,Address Byte应该是什么??
发表于 2010-6-12 13:31:55 | 显示全部楼层
关注
发表于 2010-6-13 13:42:41 | 显示全部楼层
建议给LZ一条裤子穿穿
发表于 2010-6-13 16:27:31 | 显示全部楼层
非常的哭
发表于 2010-6-13 17:08:12 | 显示全部楼层
.
发表于 2010-6-13 17:09:19 | 显示全部楼层
MARK KWP2000
MARK 汽车诊断仪
MARK K-LINE
发表于 2010-6-13 17:28:19 | 显示全部楼层
搞个开源的,呵呵
发表于 2010-7-8 15:23:20 | 显示全部楼层
谢谢楼主分享
发表于 2010-7-8 15:39:28 | 显示全部楼层
我做过K线工装,用232与单片机连接,单片机控制TJA1020即可,主要是那个5波特率比较复杂些,其他也不困难
发表于 2010-9-14 14:39:44 | 显示全部楼层
http://code.google.com/p/opengauge/wiki/OBDuinoInterface
这儿比较详细,直白些

还有个芯片:
MC33290
ISO K Line Serial Link Interface
发表于 2010-9-14 17:45:16 | 显示全部楼层
liuxiahenji
发表于 2010-9-15 12:56:37 | 显示全部楼层
记号
发表于 2010-9-15 14:18:04 | 显示全部楼层
做这个要注意那个93LC46,有不同封装的,且管脚的顺序不一样!!
曾经在这个上面吃过小亏。
发表于 2010-11-12 14:41:56 | 显示全部楼层
mark! 好资料,学习
发表于 2010-11-12 15:21:25 | 显示全部楼层
留着以后用吧。
发表于 2010-11-12 17:38:06 | 显示全部楼层
积分:30
派别:
等级:------
来自:苹果
mark! 好资料
友情提示:标题不合格、重复发帖,将会被封锁ID。详情请参考:论坛通告:封锁ID、获得注册邀请码、恢复被封ID、投诉必读
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|阿莫电子论坛(原ourAVR/ourDEV) ( 公安备案:44190002001997(交互式论坛) 工信部备案:粤ICP备09047143号 )

GMT+8, 2020-2-24 19:12

阿莫电子论坛, 原"中国电子开发网"

© 2004-2018 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表