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

📄 obdc.c

📁 在单片机上实现OBD协议的调制和解调,应用于车载OBD检测设备.
💻 C
字号:
#include <io51.h>
#include "def.h"
/*   #include "var.h" */
 /*   --VAR.H--    */
#define portmc    ((char xdata *)0xef00) /*  8255 */
#define port80    ((char xdata *)0xf400) /* 8254 port.0  */
#define port81    ((char xdata *)0xf500) /* 8254 port.1  */
#define port82    ((char xdata *)0xf600) /* 8254 port.2  */
#define port83    ((char xdata *)0xf700) /* 8254 port.3  */
data unsigned int ms10count;
data bit setpwm;    /* 0: VPW  1: PWM  */
data bit starfrm;
data bit sfflg;     /* 0: 接收  1: 发送  */
data bit recflg;    /* 0: 不接收  1: 接收帧  */
data bit pwmsflg;
data bit pwmsfack;  /* 1: 接收"发送帧"内响应  0: 不接收 */
data unsigned char cht2,recsj,rcount,timh0,timl0;
data unsigned char sendsj,scount,pwmd0;
data bit flag;
data bit rbflg;
data bit bflg;
data bit pwmsdf;
data bit pwmssf;
data char i;
data unsigned char ch1,ch2,ch3,ch4;
data unsigned char sett0h,sett0l,sett0md;

void time10ms(void);
void exint0(void);
void vpwc();
void pwmc();
void pwmsend();
void fout1();
void fout2();

void main()  /* CPU: 24MHz */
{ ch4=0;
  TMOD=1; IP=1; TCON=0X10;  /* T0 定时方式1(16bit),INT0 级别高于 T0,INT0,
			       T0中断允许  INT0 电平方式*/
  enable_ET0;               /* T0 中断控制允许  */
  EX0=0;EX1=0;ES=0;EA=1;T1=1;TXD=1;RXD=1;
  P13=0; P12=0;P16=1;
  P15=1; /* REC STA */
  P17=1; /* SEND STA */
  TH0=0XBE; TL0=0XE6;ms10count=0;
  while(ms10count<10);
  ch1= *portmc;
  T1=0; while(ms10count<20); T1=1;
  ch1=0;ch2=0;setpwm=0;pwmd0=0;
  while(1)
  {if(TXD==0)
   {T1=0;
    ch1=ch2;
    ch2=*portmc;
    T1=1;
    while(RXD==1);
    switch(ch2)
    {case 0xa0:  *portmc=0x10;break;  /* OBD-II 调制硬件号 V1.0 */
     case 0xa1:  *portmc=0x20;break;  /* OBD-II 调制软件号 V2.0 */
     default:    *portmc=~ch2;
    }
    if(ch2==0xf0)  /* start */
    {switch(ch1)
     {case 0x10:   /* VPW */
	 P14=0;setpwm=0;
	 ms10count=0;while(ms10count<3);vpwc();
	 break;
      case 0x11:   /* PWM */
      case 0x12:
	 pwmsfack=1;
	 P14=1;setpwm=1;
	 ms10count=0;while(ms10count<3);pwmc();
	 break;
      case 0x13:  /* PWM */
	 pwmsfack=0;
	 P14=1;setpwm=1;
	 ms10count=0;while(ms10count<3);pwmc();
	 break;
      case 0x20:  /* 方波 */
	 while(TXD==1);
	 sett0md=*portmc;
	 while(TXD==1);
	 sett0h=*portmc;
	 while(TXD==1);
	 sett0l=*portmc;
	 ms10count=0;while(ms10count<2);
	 if(sett0md==0) fout1();
	 else fout2();
	 break;
     }
    }
   }
  }
}

void vpwc()
{
 P13=0; P12=0;P16=1;P17=1;
 TL0=0;TH0=0;TR0=1;
 ET0=0;EX0=0;EA=1;
 flag=1;INT0=1;
  *port83=0x32; /* T0: 方式1; RD/WR 2Byte  */
  *port80=0; *port80=0;
  *port83=0x72; /* T1: 方式1; RD/WR 2Byte  */
  *port81=0; *port81=0;
  *port83=0xb0; /* T2: 方式0; RD/WR 2Byte  */
  *port82=0; *port82=0;

 sfflg=0;   /* 0: 接收  1: 发送  */
 recflg=0;  /* 0: 不接收  1: 接收帧  */
 *port83=0x12; /* T0: 方式1; RD/WR 1Byte  */
 *port83=0x52; /* T1: 方式1; RD/WR 1Byte  */
 *port83=0x90; /* T2: 方式0; RD/WR 1Byte  */
 P10=0;P11=1;  /* 初始化 D触发器 */
 P12=1;
 while(INT0==1);
 *port82=0xff;
 while(flag)
 {if(sfflg) /* 发送 */
  {if(P16==1)
    {
     if(scount==0) /* 转接收帧 */
     {
       while(P16==1);
       sfflg=0;
       P12=1; P10=0;P11=1;
       *port82=0xff;
       TL0=0;TH0=0;TR0=1;EX0=0;
     }
     else
     {if((sendsj&scount)==0) /* 位为0 */
	{*port83=0x72;*port81=32;*port81=0;}
      else {*port83=0x72;*port81=64;*port81=0;}
      scount=scount>>1;
     }
     while(P16==1);
    }
    else
    {if((sendsj&scount)==0) /* 位为0 */
	{*port83=0x32;*port80=64;*port80=0;}
     else {*port83=0x32;*port80=32;*port80=0;}
     scount=scount>>1;
     if(scount==0)
     {if(TXD==0)   /* 发送下一字节 */
      {sendsj=*portmc;
       scount=0x80;
      }
      else P17=1; /* 置发送结束标记 */
     }
     while(P16==0);
    }
  }
  else      /* 接收 */
  {if(INT0==1)
   {EX0=1;    /* 160 */
    TR0=0;
    timl0=TL0;
    if((TH0==0)&&(timl0<205)) rcount=rcount>>1;  /* 137 */
    else
    {if((TH0!=0)&&(timl0>86)) recflg=0;
     else {recsj=recsj+rcount;rcount=rcount>>1;}  /* 274 */
    }
    while(INT0==1);
   }
   else
   {/*  *port83=0x90;  方式0; RD/WR 1Byte  */
     *port82=0xff;
     if(TH0>1)
     {P15=1;     /* 置接收结束标记 */
      if(TXD==0)  /* 转发送帧 */
      {
       sendsj=*portmc;
       sfflg=1;
       EX0=0;
       while((TH0<3)||(INT0==1)) {if(INT0==1) TH0=0;} /* 检测空闲 */
       P10=0;P11=1;  /* 初始化 D触发器 */
       *port83=0x32;*port80=96;*port80=0;
       P10=1;P11=0;P11=0;P11=1;P12=1;  /* 发送启动位 */
       P17=0;       /* 置发送开始标记 */
       scount=0x80;
      }
      TH0=3;
     }
   }
  }
 }
}
void pwmc()
{rbflg=0;pwmssf=0;
 P13=1; P12=0;P16=1;P17=1;
 TMOD=0x19;
 TL0=0;TH0=0;TR0=1; ET0=0;
 TL1=0;TH1=0;TR1=0; ET1=0;
 EX0=0;EA=0;
 flag=1;INT0=1;
  *port83=0x32; /* T0: 方式1; RD/WR 2Byte  */
  *port80=0; *port80=0;
  *port83=0x72; /* T1: 方式1; RD/WR 2Byte  */
  *port81=0; *port81=0;
  *port83=0xb0; /* T2: 方式0; RD/WR 2Byte  */
  *port82=0; *port82=0;

 sfflg=0;   /* 0: 接收  1: 发送  */
 recflg=0;  /* 0: 不接收  1: 接收帧  */
 *port83=0x12; /* T0: 方式1; RD/WR 1Byte  */
 *port83=0x52; /* T1: 方式1; RD/WR 1Byte  */
 *port83=0x9a; /* T2: 方式5; RD/WR 1Byte  */
 P10=0;P11=1;  /* 初始化 D触发器 */
 P12=1;EX0=0;
 while(INT0==1);
 *port82=0xff;
 TL0=0;TH0=0;TR0=1;
 TL1=0;TH1=0;TR1=1;

	    /* 接收/空闲状态 */
pwmck_1:
   if(INT0==1)
   {    /* 160 */
    TL1=0;TH1=0;
    while(INT0==1);
    cht2=TL0;TL0=0;
/*    if((cht2<140)&&(cht2>90)&&(TH0==0))    45: 帧开始    186+/-5  */
    if((cht2<84)&&(cht2>50)&&(TH0==0))  /*  45: 帧开始    186+/-5  */
    {
     TL1=0;
     recsj=0;rcount=0x80;
     P15=0; goto pwmrec1; /* 接收帧开始 */
    }
    else TH0=0;
   }
   else   /* INT0=0 */
   {
     TL0=0;TH0=0;
     if(TH1>0) /* 28*6 */
      {P15=1; /* 接收帧结束 */
       if(TXD==0)  /* 转发送帧 */
       {
	sendsj=*portmc;
/*	sfflg=1;*/
	TMOD=0x11;TR0=1;
	EX0=0;
	scount=0x80;pwmsflg=1;pwmsdf=1;
	while((TH0<3)||(INT0==1)) {if(INT0==1) TH0=0;} /* 检测空闲 */
	P10=0;P11=1;  /* 初始化 D触发器 */
	*port83=0x12;*port80=62;  /* 60 */
	P10=1;P11=0;P11=1;  /* 发送启动位 */
	*port83=0x52;*port81=34;/* 38 */
	P17=0;   /* 发送帧开始 */
	pwmsend();
       }
       else TH1=4;
      }
   }
   goto pwmck_1;


pwmrec1:    /* 接收帧 */
   if(INT0==1)
   {    /* 160 */
pwmrec2:
    TL1=0;
    while(INT0==1);
pwmrec3:
    if(TL0<22) recsj=recsj|rcount;
    TL0=0;
    rcount>>=1;
    if(rcount==0)
    {
	*portmc=recsj;
	recsj=0;rcount=0x80;
	if(TL0!=0)
	{TL1=0;
	 goto pwmrec2;
	}
    }
   }
   else   /* INT0=0 */
   {
     if(TL1>48) /* 50: 15*3.5 */
     { P15=1; /* 接收帧结束 */
       if(TXD==0)  /* 转发送帧响应 */
       {
	sendsj=*portmc;
/*	sfflg=1;*/
	scount=0x40;
	P10=0;P11=1;  /* 初始化 D触发器 */
	*port83=0x12;
	while(TL1<65);  /* 73--13, 77--14,  */
	if((sendsj&0x80)==0)
	{*port80=32;
	 P10=1;P11=0;P11=1;  /* 发送启动位 */
	 *port83=0x52;*port81=16;
	 P17=0;   /* 发送帧开始 */
	 pwmsend();
	}
	else
	{*port80=16;
	 P10=1;P11=0;P11=1;  /* 发送启动位 */
	 *port83=0x52;*port81=32;
	 P17=0;   /* 发送帧开始 */
	 pwmsend();
	}
       }
       goto pwmck_1;
     }
   }
   goto pwmrec1;
}



void pwmsend()
{
pwmsc1:
/*     while(P16==1); */
     if((sendsj&scount)==0) /*  位为0 */
     {
       while(P16==1);
       *port80=32;
       scount>>=1;
       if(scount==0)
       {
	while(P16==0);
	*port81=16;
	if(TXD==0)   /* 发送下一字节 */
	{sendsj=*portmc;
	 scount=0x80;
	 goto pwmsc1;
	}
	else {P17=1;goto pwmsc2; }  /* 发送帧结束 */
       }
       while(P16==0);
       *port81=16;
       goto pwmsc1;
     }
     else
     {
       while(P16==1);
       *port80=16;
       scount>>=1;
       while(P16==0);
       *port81=32;
       if(scount==0)
       {if(TXD==0)   /* 发送下一字节 */
	{sendsj=*portmc;
	 scount=0x80;
	 goto pwmsc1;
	}
	else {P17=1;goto pwmsc2; }  /* 发送帧结束 */
       }
       goto pwmsc1;
     }
pwmsc2:   /* 发送帧结束处理 */
/*      sfflg=0;*/
      if(pwmsfack)
      {
       while(P16==1);
       P12=1; P10=0;P11=1;
       *port82=0xff;
       TMOD=0x19;
       TL0=0;TH0=0;TR0=1;
       TL1=0;TH1=0;TR1=1;
       recsj=0;rcount=0x80;
       P15=0;
    pwmsfrc1:    /* 接收"发送帧"内响应 */
       if(INT0==1)
       {    /* 160 */
    pwmsfrc2:
	TL1=0;
	while(INT0==1);
	if(TL0<22) recsj=recsj|rcount;
	TL0=0;
	rcount>>=1;
	if(rcount==0)
	{
	 *portmc=recsj;
	 recsj=0;rcount=0x80;
	 if(TL0!=0)
	 {TL1=0;
	  goto pwmsfrc2;
	 }
	}
       }
       else   /* INT0=0 */
       {TL0=0;
	if(TL1>90) /* 50: 15*3.5 */
	{ P15=1; /* 接收帧结束 */
	  goto pwmsc3;
	}
       }
       goto pwmsfrc1;
      }
      else {  while(P16==1); }

pwmsc3:
      P12=1; P10=0;P11=1;
      rbflg=0;
      *port82=0xff;
      TMOD=0x19;
      TL0=0;TH0=0;TR0=1;
      TL1=0;TH1=0;TR1=1;return;

}
void time10ms(void) interrupt 1
{TH0=0XBE; TL0=0XE6;
 ms10count++;enable;
}

void EX0_int(void) interrupt 0
{
	     /* VPW */
  TH0=0;TL0=0;TR0=1;EX0=0;
  *port83=0x80; /* 锁存输出 */
  cht2=*port82;
  if(cht2<170)      /* 102: 帧开始 */
  {recflg=1;recsj=0;
   rcount=0x80;
   P15=0;  /* 置接收开始标记 */
  }
  else
  {if(recflg)
   {if(cht2<204) rcount=rcount>>1; /* 68 */
    else
    {if(cht2<238) {recsj=recsj+rcount;rcount=rcount>>1;}  /* 34 */
     else recflg=0;
    }
    if(rcount==0)
    {
     *portmc=recsj;
     recsj=0;rcount=0x80;
    }
   }
  }
}

void fout1()
{ EA=0;
  TMOD=1; TCON=0X10;
cf_start1:
  T1=0;
  TH0=sett0h;TL0=sett0l;
  while(!TF0);
  TF0=0;T1=1;
  TH0=sett0h;TL0=sett0l;
  if(!TXD)
  {
   if(*portmc==0x0f) {T1=1;EA=1;return;}
  }
  while(!TF0);
  TF0=0;
  goto cf_start1;
}

void fout2()
{data unsigned char count;
  EA=0;
  TMOD=1; TCON=0X10;
cf_start2:
  T1=0;
  count=sett0md;
  while(count>0)
  {TL0=0;TH0=0;TF0=0;
   while(TF0==0);
   count--;
  }
  TH0=sett0h;TL0=sett0l;
  while(!TF0);
  TF0=0;T1=1;
  count=sett0md;
  while(count>0)
  {TL0=0;TH0=0;TF0=0;
   while(TF0==0);
   count--;
  }
  TH0=sett0h;TL0=sett0l;
  if(!TXD)
  {
   if(*portmc==0x0f) {T1=1;EA=1;return;}
  }
  while(!TF0);
  TF0=0;
  goto cf_start2;
}







⌨️ 快捷键说明

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