📄 hwdevice111.c
字号:
*(volatile unsigned char *)PDSEL |= 0x20; //PD5 as I/O
*(volatile unsigned char *)PDDIR |= 0x20; //PD5 as output;
*(volatile unsigned char *)PDDATA&= ~0x20; //PD5 output low to open the VCC;
UnlockUart();
while(ReceiveInTime(&byte,1)); //clear FIFO of UART
#endif
}
/*****************************************************************************************
名称:void DeInitializeUart()
功能:关闭串口,并将TX、RX分别设为OUTPUT和INPUT口
参数:无
******************************************************************************************/
void DeInitializeUart()
{
#if __TURBOC__
return;
#else
*(volatile unsigned char *)PEDATA|= 0x20; //PE5(TXD) output high;
*(volatile unsigned char *)PEDIR |= 0x20; //PE5(TXD) as output;
*(volatile unsigned char *)PEDIR &= ~0x10; //PE4(RXD) as input;
*(volatile unsigned char *)PESEL |= 0x30; //PE4(RX), PE5(TX) as I/O
*(volatile unsigned short *)USTCNT &= ~0x8000;
*(volatile unsigned short *)NIPR &= ~0x8000; //use integral divider
OBDII_CtrPinReset();
#endif
}
/*******************************************************************************************************************
名称:unsigned char ShakeWith5bpsAddrCode(unsigned char sys_addr,unsigned char K_LINE_num, unsigned char L_LINE_num)
功能:用5bps发送系统地址码,然后接收系统的应答字符:0x55,测定汽车系统发送该字节的波特率,
并将本机的UART置成相同的波特率。
参数:sys_addr: 系统地址码
K_LINE_num: K线的脚位,如大众车设为7
L_LINE_num: L线的脚位,如大众车设为15
返回值:
1: 表示握手成功
0: 表示握手失败
0xFF:表示未检测到连线
*******************************************************************************************************************/
unsigned char ShakeWith5bpsAddrCode(unsigned char sys_addr,unsigned char K_LINE_num, unsigned char L_LINE_num)
{
unsigned short int timerOverflowCnt=0,timerCnt;
unsigned char i=0,ret = 0;
unsigned char rByte,tmp_addr;
float baudRateDivision;
unsigned long old_level;
#if __TURBOC__
return 0;
#endif
InitializeUart();
while(ReceiveInTime(&rByte,1));//clear uart FIFO
DeInitializeUart(); //串口接收禁止
OBDII_SelectPin(K_LINE_num,L_LINE_num,POSITIVE_LOGIC,POSITIVE_LOGIC,REF_VOLTAGE_12V); //将K线,L线同时选通
SetTxdHigh();
SetRxdToInputPin();
old_level = *IMR;
*IMR = 0xffffffff; //mask all interrupt to assure the accuracy of time counting
SetTxdLow();//发送串口起始位信号
DelayMilliSecond(200);
/*发送串口数据位信号*/
tmp_addr = sys_addr;
for(i=0;i<8;i++)
{
if(tmp_addr & 0x01) SetTxdHigh();
else SetTxdLow();
DelayMilliSecond(200);
tmp_addr >>= 1;
}
SetTxdHigh();//发送串口数据结束位信号
DelayMilliSecond(2);
if(K_LINE_num !=0)//如果K_LINE_num为0,则表示是单K线的,且K线的脚位从第二个参数传过来,也就无需关闭L线
OBDII_SelectPin(K_LINE_num,0,POSITIVE_LOGIC,POSITIVE_LOGIC,REF_VOLTAGE_12V); //选通K线,关闭L线
SetRxdToInputPin();
//initiate timer counter
*(volatile unsigned short *)TCTL = 0x0104;
//Free run mode, timer disable, timer clk source = sys clk / 16,reset counter to zero
*(volatile unsigned short *)TPRER = 0x0; //prescaler: divider = 1
*(volatile unsigned short *)TCMP = 0xFFFF;
ENABLE_TIMER;
timerOverflowCnt = 0;
if(TIMER_COUNTER_OVERFLOW)
CLEAR_TIMER_OVERFLOW_FLAG;
while(RXPIN)//等待RX(PE4)变低
{
if(TIMER_COUNTER_OVERFLOW)
{
timerOverflowCnt++; // overflow time: about 65ms
CLEAR_TIMER_OVERFLOW_FLAG;
if(timerOverflowCnt > 30) //about 30*0.065 seconds
{ //汽车电脑无应答
DISABLE_TIMER;
ret = 0;
goto EXIT;
}
}
}
DISABLE_TIMER;
ENABLE_TIMER;
timerOverflowCnt = 0;
if(TIMER_COUNTER_OVERFLOW)
CLEAR_TIMER_OVERFLOW_FLAG;
//for the maxmimum span of timer can reach 16 ms,
//so the counter should not overflow within one byte transmit in normal case
while(!RXPIN) //start bit
if(TIMER_COUNTER_OVERFLOW)
{
DISABLE_TIMER;
ret = 0;
goto EXIT;
}
for(i = 0; i < 4; i++) //data bit: 8 bits , 0x55 (least bit first)
{
while(RXPIN)
if(TIMER_COUNTER_OVERFLOW)
{
DISABLE_TIMER;
ret = 0;
goto EXIT;
}
while(!RXPIN)
if(TIMER_COUNTER_OVERFLOW)
{
DISABLE_TIMER;
ret = 0;
goto EXIT;
}
}
timerCnt = *(volatile unsigned short *)TCN;
DISABLE_TIMER;
InitializeUart();
baudRateDivision = ((float)timerCnt) / (float)9.0f;
if(!SetUartBaudRate(baudRateDivision))
ret = 0;
else
ret = 1;
#if _DEBUG_
{
char str[100];
unsigned short len;
sprintf(str,"BaudRate:%05.2f\r\n",baudRateDivision);
len = strlen(str);
if(com_ptr>=com_buf && com_ptr+len<com_buf+DEBUG_BUF_SIZE)
{
strcpy(com_ptr,(const char *)str);
com_ptr += len;
}
}
#endif
EXIT:
*IMR = old_level ;
SetTimeoutValueOfTimer(700); //Prepare for next IDLE FRAME exchange
return ret;
}
/*****************************************************************************************
名 称:unsigned char SetUartBaud(unsigned long baud_rate)
功 能:将本机的UART置成指定的波特率。
参 数:baud_rate: 所需设定的波特率,如要将波特率设为10.4K,则将该参数设为10400即可
返回值:
1: 表示设置成功
0: 表示设置失败
******************************************************************************************/
unsigned char SetUartBaud(unsigned long baud_rate)
{
float baud_rate_divisor;
baud_rate_divisor = ((float)(16580000.0f/16.0f)/(float)(baud_rate));
return SetUartBaudRate(baud_rate_divisor);
}
/*
//这两个函数对应的是1.0的硬件,2.0版不再使用
void OBDII_CtrPinReset(void)
{
#if __TURBOC__
return;
#else
SetCtsHigh(); //set CD4060 clk high
SetRtsHigh();
SetCsd1High(); //set PIN1 pull up
SetBootsHigh(); //set CD4067 reset high and set PIN9 pull up
SetPg2Low(); //set VPW Tx low
SetCommToInputPin(); //set VPW Rx pin as input
#endif
}
void OBDII_SelectPin(unsigned char pin_of_group1,unsigned char pin_of_group2,unsigned char switch_on_off)
{
register unsigned char ctr_data,i,mask=0x80;
#if __TURBOC__
return;
#else
ctr_data = 0;
switch(pin_of_group1)
{ //1、6、7、8、9、10、11、13分别对应0至7通道,其它值则禁止该组的所有通道的选通
case 1: ctr_data = 0x00; break;
case 6: ctr_data = 0x01; break;
case 7: ctr_data = 0x02; break;
case 8: ctr_data = 0x03; break;
case 9: ctr_data = 0x04; break;
case 10: ctr_data = 0x05; break;
case 11: ctr_data = 0x06; break;
case 13: ctr_data = 0x07; break;
default: ctr_data = 0x08; break;
}
switch(pin_of_group2)
{ //3、12、14、15分别对应0至3通道(另外4个通道未使用),其它值则禁止该组的所有通道的选通
case 3: ctr_data |= 0x00; break;
case 12: ctr_data |= 0x10; break;
case 14: ctr_data |= 0x20; break;
case 15: ctr_data |= 0x30; break;
default: ctr_data |= 0x40; break;
}
if(switch_on_off) //1时则打开第一组开关选通芯片所连接的RX及第二组开关选通芯片所连接的TX的通路,为0时关闭
ctr_data |= 0x80;
for(i=0;i<8;i++)
{//将控制字置入串行移位寄存器,由于是串行移位,因此在移位过程中存在很多种中间状态,移位结束后才能实现所希望的设定值
SetCtsLow(); //set clk low
if(ctr_data & mask)
SetRtsHigh();
else
SetRtsLow();
SetCtsHigh(); //set clk high
ctr_data<<=1;
}
#endif
}
*/
/***********************************************************************************************************************
名 称:void OBDII_SelectPin(unsigned char pin_of_group1,unsigned char pin_of_group2,unsigned char switch_on_off)
功 能:选择OBDII 16PIN诊断头的相应脚位(即数据通道)。
参 数:
pin_of_group1: 设定第一组脚位选择所连通的脚位,可取的有效值为:1、6、7、8、9、10、11、13,取其它值表示禁止该组的连通
pin_of_group2: 设定第二组脚位选择所连通的脚位,可取的有效值为:3、12、14、15,取其它值表示禁止该组的连通
switch_on_off: 用以控制第一组开关选通芯片所连接的RX及第二组开关选通芯片所连接的TX的通路的开启和关闭,0为关,其它值为开
返回值:无
***********************************************************************************************************************/
void OBDII_CtrPinReset(void)
{
#if __TURBOC__
return;
#else
SetRtsLow(); //disable CD4094 output and disable both of the CD4051
SetCtsHigh(); //set CD4060 clk high
SetCsd1Low(); //set PIN1 pull up high
SetBootsLow(); //set CD4067 reset high and set PIN9 pull up
SetPg2Low(); //set VPW Tx low
SetCommToInputPin(); //set VPW Rx pin as input
#endif
}
void OBDII_SelectPin(unsigned char pin_of_group1,unsigned char pin_of_group2,unsigned char logic_of_group1,
unsigned char logic_of_group2, unsigned char ref_voltage)
{
register unsigned short ctr_data,i,mask=0x0100;
#if __TURBOC__
return;
#else
SetRxdToInputPin(); //设RXD为I/O口,以免将接下来初始化CD4094的TXD的变化信号误认为串口信号
SetRtsLow(); //disable CD4094 output and disable both of the CD4051
ctr_data = 0x00;
switch(pin_of_group1)
{ //1、6、7、8、9、10、11、13分别对应0至7通道,其它值则禁止该组的所有通道的选通
case 1: ctr_data = (0x00<<1); break;
case 6: ctr_data = (0x01<<1); break;
case 7: ctr_data = (0x02<<1); break;
case 8: ctr_data = (0x03<<1); break;
case 9: ctr_data = (0x04<<1); break;
case 14: ctr_data = (0x05<<1); break;
case 11: ctr_data = (0x06<<1); break;
case 13: ctr_data = (0x07<<1); break;
default: ctr_data = 0x01; break;
}
switch(pin_of_group2)
{ //3、12、14、15分别对应0至3通道(另外4个通道未使用),其它值则禁止该组的所有通道的选通
case 3: ctr_data |= (0x00<<1); break;
case 12: ctr_data |= (0x10<<1); break;
case 10: ctr_data |= (0x20<<1); break;
case 15: ctr_data |= (0x30<<1); break;
default: ctr_data |= 0x10; break;
}
if(logic_of_group1 == NEGATIVE_LOGIC)
ctr_data |= 0x80;
if(logic_of_group2 == NEGATIVE_LOGIC)
ctr_data |= 0x0100;
// ctr_data = 0x01FF;//debug use
for(i=0;i<9;i++)
{//将控制字置入串行移位寄存器,为防止出现中间状态,在移位过程结束之前,CD4094的OE(output enable)应一直被禁止
SetCtsLow(); //set clk low
if(ctr_data & mask)
SetTxdHigh();
else
SetTxdLow();
SetCtsHigh(); //set clk high
ctr_data<<=1;
}
SetTxdHigh();
SetRxdToRxdPin(); //复原Rxd脚作为串口接收脚的功能
SetRtsHigh(); //enable CD4094 output to fulfill the function
InitializeUart();
#endif
}
//解密字符串
void DecodeString(unsigned char *str, unsigned long len, unsigned char offset)
{
unsigned char c,xor,tmp;
if(len==0) return;
do
{
c = *str;
xor = offset;
xor <<= 4;
tmp = (offset&0x0f);
xor |= tmp;
xor += 'Y';
c ^= xor;
*str++ = c;
offset++;
}
while(--len);
}
/**************************************************************************************
short int GetErrorMessageFromLib(short handle,unsigned short segment,
unsigned char *err_code_str,unsigned char *message_buf)
功 能:在指定定的文件中查找指定故障代号所对应的故障信息提示(即用来提示给用户阅读的内容)
输入参数:
handle: 存有故障库信息的文件句柄(由调用函数打开文件并将文件句柄传过来)
segment:该系统的故障库在整个库中的段号(从0段开始计算),因为库中存在多个系统的故障内容
error_code_str:故障代号字符串指针,须以0x0作为该串的结束符;
message_buf:由调用者分配,调用者需保证其大小不小于最长故障信息的长度,否则可能导致缓
冲区溢出,本函数将得到的故障信息存于其中,该信息以字符串尾(即0x00)结束。
返回值:如成功找到则返回1; 如找不到对应故障信息则返回0,此时message_buf的内容未知。
********************************************************************************************/
short int GetErrorMessageFromLib(short handle,unsigned short int segment,
unsigned char *err_code_str,unsigned char *message_buf)
{
#define BUF_SIZE 512L
#define EOL_MARK 0x0D
#define MAX_ERR_CODE_LEN 6
long offset,head,tail,file_start,file_end;
unsigned short err_code_str_len;
char file_buf[BUF_SIZE],*cur_ptr,*file_buf_end;
unsigned char xor_offset,tmp[10];
err_code_str_len=strlen((const char *)err_code_str);
if(err_code_str_len>BUF_SIZE-MAX_ERR_CODE_LEN) return 0;
ffseek(handle,0L,0);
ffread(handle,(char *)tmp,2L);
if( segment >= ((((tmp[1]<<8)+tmp[0])>>2)-1) )
return 0; //段号大于库中的最大段号,则返回0
offset = (segment<<2);
ffseek(handle,offset,0);
ffread(handle,(char *)tmp,8L);
head = (tmp[3]<<24)+(tmp[2]<<16)+(tmp[1]<<8)+tmp[0];
tail = (tmp[7]<<24)+(tmp[6]<<16)+(tmp[5]<<8)+tmp[4];
file_start = head; file_end = tail;
xor_offset = tmp[4];
file_buf_end = file_buf+BUF_SIZE-MAX_ERR_CODE_LEN-4;
while(1)
{
if(tail-head<10)
tail = offset = head;
else
offset = (head + tail)>>1;
ffseek(handle,offset,0);
ffread(handle,file_buf,BUF_SIZE);
DecodeString((unsigned char *)file_buf,BUF_SIZE,(unsigned char)(offset+xor_offset));
cur_ptr = file_buf;
if(offset != file_start)
{
while(*cur_ptr != EOL_MARK)
{
cur_ptr++; //look for the next DTC
if(cur_ptr == file_buf_end)
{//表示本次读取到缓冲内的数据不包括回车换行符,需重新读取
offset += (cur_ptr - file_buf);
ffseek(handle,offset,0);
ffread(handle,file_buf,BUF_SIZE);
cur_ptr = file_buf;
}
}
cur_ptr+=2;
}
if(offset+(long)(cur_ptr-file_buf) > file_end - 2) //is end of file
tail = offset;
else
{
short int result,len;
result = strncmp((const char *)err_code_str,(const char *)cur_ptr,err_code_str_len);
if(result<0) // the specific value is less than current value
tail = offset;
else if(result>0) //the specific value is greater than current value
head = offset;
else //the value is hit;
{//the equal value has been found and copy the message of this line to message buffer
len = 0;
while(*cur_ptr != EOL_MARK)
{
*message_buf++ = *cur_ptr++;
len++;
if(cur_ptr == file_buf_end)
{//表示本次读取到缓冲内的数据还不能完整代表该条故障信息,需继续读取
offset += (cur_ptr - file_buf);
ffseek(handle,offset,0);
ffread(handle,file_buf,BUF_SIZE);
cur_ptr = file_buf;
}
}
*message_buf = 0x0;
break;
}
}
if(head == tail)
return 0;
}
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -