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

📄 iso.c

📁 AVR ISO9141 OBDII Souce code
💻 C
📖 第 1 页 / 共 2 页
字号:
  {
    if( (iso_glob.uart_bit_cnt > 1) && (iso_glob.uart_bit_cnt <= 9) ) // check for databit
    {
      if( iso_glob.uart_buffer&0x01 ) // check LSB status
      {
        iso_k_high();  // send 1 bit
      }
      else
      { 
        iso_k_low();  // send 0 bit
      }
      iso_glob.uart_buffer = iso_glob.uart_buffer>>1;  // next bit
    }
		else // in case of last bit
		{
		  iso_k_high();  // send stop bit
		}

    if(iso_glob.uart_bit_cnt <= 0) // check if stop bit send
    {
		  GIFR = _BV(INTF0);  // clear INT0 flag
		  GICR = _BV(INT0);  // enable INT0
      TIMSK = 0;  // disable timer0 interrupts
      CLEARBIT(iso_glob.uart_status, BUSY); // free uart
			CLEARBIT(iso_glob.uart_status, TD);
    }
  }
  /* receive section */
  else
  { 
    if( (iso_glob.uart_bit_cnt == 9) && is_k_in_high() )  // check for start bit
		{
			SETBIT(iso_glob.uart_status, ERROR);  // set error flag if start bit is not 0
		}
    if( (iso_glob.uart_bit_cnt > 0) && (iso_glob.uart_bit_cnt < 9) )
    {
      iso_glob.uart_buffer >>= 1;
      if( is_k_in_high() )
      { 
        iso_glob.uart_buffer |=0x80;            
      }
    }                          
    else if (iso_glob.uart_bit_cnt <= 0)
    {
      SETBIT(iso_glob.uart_status, RDY);  // set data byte ready
			GIFR = _BV(INTF0);  // clear INT0 flag
		  GICR = _BV(INT0);  // enable INT0
      TIMSK = 0;  // disable timer0 interrupts
      CLEARBIT(iso_glob.uart_status, BUSY); // free uart
			if( !is_k_in_high() )
			{
				SETBIT(iso_glob.uart_status, ERROR);  // set error flag if stop bit is not 1
			}
    } 
  }

}


/* 
**--------------------------------------------------------------------------- 
** 
** Abstract: This routine is executed when a negative edge on the incoming serial
**           signal is detected. It disables further external interrupts and enables
**           timer interrupts (bit-timer) because the UART must now receive the
**           incoming data. 
** 
** Parameters: none
** 
** 
** Returns: none
** 
**--------------------------------------------------------------------------- 
*/
SIGNAL(SIG_INTERRUPT0)
{
  iso_glob.uart_bit_cnt = 10;  // receive 10 bits; start, 8 data, stop
	// check if baud rate detection is required
	if( CHECKBIT(iso_glob.uart_status, BAUDMEAS) && CHECKBIT(iso_glob.uart_status, AUTOBAUD) )
	{
		iso_glob.uart_n_baud = TCNT0;  // store counter value
		--iso_glob.uart_bit_cnt;  // decrement bit count, startbit used for measuring baud rate
		CLEARBIT(iso_glob.uart_status, AUTOBAUD);  // only one detection cycle
		CLEARBIT(iso_glob.uart_status, BAUDMEAS);
		MCUCR ^= _BV(ISC00);  // reset INT0 trigger edge to setting from init
	}
	else if( !CHECKBIT(iso_glob.uart_status, BAUDMEAS) && CHECKBIT(iso_glob.uart_status, AUTOBAUD) )
	{
	  timer0_start(T0_PRESCALER);
		TCNT0 = 0;  // reset counter
		MCUCR ^= _BV(ISC00);  // toggle INT0 edge trigger
		SETBIT(iso_glob.uart_status, BAUDMEAS);
	}

	if(!CHECKBIT(iso_glob.uart_status, AUTOBAUD))	
	{
		SETBIT(iso_glob.uart_status, BUSY);  // set UART busy
		TCNT0 = 256-(iso_glob.uart_n_baud/2)+(iso_glob.uart_n_baud/8);  // load timer 0.5 bit length	+ time tuning value
		TIFR = (1<<TOIE0);  // clear timer0 overflow interrupt flag
		TIMSK = (1<<TOIE0);  // enable timer0 overflow interrupt
		iso_glob.uart_buffer = 0x00;  // clear receive buffer
		GICR = 0;  // disable INT0
		iso_glob.uart_reload = (256-iso_glob.uart_n_baud)+(iso_glob.uart_n_baud/48);  // reload value 1 bit length	+ time tuning value
	}
}


/* 
**--------------------------------------------------------------------------- 
** 
** Abstract: This routine send one data byte via ISO UART.
**           Start bit is send from here, data bits and stop bit in
**           Timer0 overflow interrupt routine.
**
** 
** Parameters: none
** 
** 
** Returns: none
** 
**--------------------------------------------------------------------------- 
*/
void iso_uart_putc(char data)
{               
  SETBIT(iso_glob.uart_status, BUSY);  // set uart busy, enable transmit
	SETBIT(iso_glob.uart_status, TD);
  GICR = 0;  // disable INT0
  iso_glob.uart_bit_cnt = 10;  // send 10 bits; start, 8 data, stop 
  iso_glob.uart_buffer = data;  // store data byte   
  TIFR = (1<<TOIE0);  // clear timer0 ovrf interrupt flag      
  TIMSK = (1<<TOIE0);  // enable timer0 ovrf interrupt
	iso_glob.uart_reload = (256-iso_glob.uart_n_baud);  // timer reload value 1 bit length
  TCNT0 = iso_glob.uart_reload+(iso_glob.uart_n_baud/16);  // load timer 1 bit length for start bit + time tuning value
  iso_k_low(); // send start bit
}                                                            


/* 
**--------------------------------------------------------------------------- 
** 
** Abstract: Init ISO UART, prepare INT0 and Timer0
**
**
** Parameters: none
** 
** 
** Returns: none
** 
**--------------------------------------------------------------------------- 
*/
void iso_uart_init(void)
{
  timer0_start(T0_PRESCALER);
	#ifdef ISO_K_LINE_IN_NEG
		MCUCR |= _BV(ISC01)|_BV(ISC00);   // interrupt on INT0 rising edge K line is inverted by hardware
	#else
		MCUCR |= _BV(ISC01);  // interrupt on INT0 falling edge                          
	#endif
  GIFR = _BV(INTF0);  // clear INT0 flag
  GICR = _BV(INT0);  // enable INT0
} 


/* 
**--------------------------------------------------------------------------- 
** 
** Abstract: Calculates the checksum for ISO message
**
** Parameters: pointer to message buffer, message length
** 
** 
** Returns: checksum
** 
**--------------------------------------------------------------------------- 
*/
unsigned char iso_checksum(unsigned char *msg_buf, unsigned int nbytes)
{
	unsigned char checksum = 0;
	for(;nbytes > 0; --nbytes)
	{
		checksum += *msg_buf;
		++msg_buf;
	}
	return checksum;
}


/* 
**--------------------------------------------------------------------------- 
** 
** Abstract: Send ISO message
**
** Parameters: pointer to message buffer, message length (excluding checksum)
** 
** 
** Returns: Error code
** 
**--------------------------------------------------------------------------- 
*/
char iso_send_msg(unsigned char *msg_buf, unsigned int nbytes)
{
	if(nbytes > 259)	return ISO_RETURN_CODE_DATA_ERROR;	// error, message to long

	unsigned char checksum = 0;
	signed int i;
	for(i=0 ; i < nbytes; ++i)
	{
		checksum += *msg_buf;  // make checksum from all message bytes
		
		iso_uart_putc(*msg_buf++);  // send each byte
		while( CHECKBIT(iso_glob.uart_status, BUSY) );  // poll ISO UART
	}

	iso_uart_putc(checksum);  // send checksum
  while( CHECKBIT(iso_glob.uart_status, TD));  // wait transmission complete
  
	return ISO_RETURN_CODE_OK;
}


/* 
**--------------------------------------------------------------------------- 
** 
** Abstract: Receive ISO message
**
** Parameters: pointer to message buffer
** 
** 
** Returns: Number of received bytes OR in case of error, error code with
**          bit 15 set as error indication
** 
**--------------------------------------------------------------------------- 
*/
unsigned int iso_recv_msg(unsigned char *msg_buf)
{
  CLEARBIT(iso_glob.uart_status, RDY);  // clear receive complete bit
	/*
		wait for responds
		return after 4ms IDLE with error
	*/
	timer1_start(T1_PRESCALER);
	while(!CHECKBIT(iso_glob.uart_status, RDY))
	{
		if(TCNT1 >= TIME_4ms)	// check for respons timeout 4ms
		{
			timer1_stop();
			return ISO_RETURN_CODE_NO_DATA | 0x8000;	// error, no responds within 4ms
		}
	}	


	/* we allread got the first received byte here - format byte */
	unsigned char format_byte = iso_glob.uart_buffer;  // store format byte
	int nbytes =  format_byte & FMT_MSG_LENGTH;  // get message length from format byte
	if(nbytes == 0)  // if length is zero, additional length byte required
	{
		nbytes = 3;  // receive at least 3 more bytes
	}
	else
	{
		if( (format_byte & FMT_ADDR)) // check if addr exists
			nbytes += 2;  // +2 additional address bytes
    
    nbytes += 1;  // +1 checksum byte
	}
	
	int byte_cnt = 0;  // message byte counter
	for(; byte_cnt < nbytes; ++byte_cnt)
	{
		*(msg_buf++) = iso_glob.uart_buffer;  // store received byte in buffer
    
		CLEARBIT(iso_glob.uart_status, RDY);
	
		timer1_start(T1_PRESCALER);
		while(!CHECKBIT(iso_glob.uart_status, RDY))  // wait for next byte
    {
			if(TCNT1 >= TIME_P1_MAX)	// check for response inter byte timeout
			{
				timer1_stop();
				return ISO_RETURN_CODE_NO_DATA | 0x8000;	// return error
			}
		}

		/* store additonal length byte here to receive the complete message */
		
    // format length = 0 and no address
		if( (byte_cnt == 0) && !(format_byte & FMT_MSG_LENGTH) && !(format_byte & FMT_NO_ADDR))
		{
			nbytes = iso_glob.uart_buffer +1 +1;  // store message length, +1 additional header byte
		}                                       // +1 checksum
    
    // format length = 0 but with address
		if( (byte_cnt == 2) && !(format_byte & FMT_MSG_LENGTH) && (format_byte & FMT_ADDR))
		{
			nbytes = iso_glob.uart_buffer + 3 +1;  // store message length, +3 additional header bytes
		}                                        // +1 checksum
    
	}
	*(msg_buf) = iso_glob.uart_buffer;  // store checksum
	
  return byte_cnt +1;  // return message length + format byte
}

⌨️ 快捷键说明

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