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

📄 hwdevice111.c

📁 SZ328片上设备驱动程序,应用于龙珠系列CPU的应用开发.
💻 C
📖 第 1 页 / 共 3 页
字号:

	*(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 + -