?? iso.c
字號:
/*************************************************************************
** AVR ISO 9141/14230-2 Interface
** by Michael Wolf
**
** Released under GNU GENERAL PUBLIC LICENSE
**
** contact: webmaster@mictronics.de
** homepage: www.mictronics.de
**
** Revision History
**
** when what who why
**
**************************************************************************/
#include <avr/io.h>
#include <avr/signal.h>
#include "iso.h"
/*
**---------------------------------------------------------------------------
**
** Abstract: ISO hardware setup
**
**
** Parameters: none
**
**
** Returns: none
**
**
**---------------------------------------------------------------------------
*/
void iso_hardware_init(void)
{
ISO_INIT_LED_DIR |= _BV(ISO_INIT_LED_OUT); // make LED pin output
bus_init_led_off(); // LED off
ISO_K_LINE_DIR |= _BV(ISO_K_LINE_OUT); // make K line output an output
iso_k_high(); // set K line high
ISO_K_LINE_DIR &=~ _BV(ISO_K_LINE_IN); // make K line input an input
ISO_K_LINE_DIR |= _BV(ISO_L_LINE_OUT); // make L line output an output
iso_l_high(); // set L line high
}
/*
**---------------------------------------------------------------------------
**
** Abstract: Wait for ISO bus idle
**
** Parameters: none
**
** Returns: none
**
**---------------------------------------------------------------------------
*/
void iso_wait_idle(void)
{
timer1_start(T1_PRESCALER);
while(TCNT1 < TIME_W5_MIN) // wait for minimum bus idle time
{
if(!is_k_in_high()) timer1_set(0); // restart timer1 when bus not idle
}
}
/*
**---------------------------------------------------------------------------
**
** Abstract: 5 Baud bus init routine
**
**
** Parameters: Address byte
**
**
** Returns: Error code
**
**
**---------------------------------------------------------------------------
*/
char iso_5_baud_init(unsigned char addr)
{
bus_init_led_off(); // turn off indication LED
iso_wait_idle(); // wait for bus idle time
unsigned char inv_addr = ~addr; // store inverse address
unsigned char bit_cnt;
for(bit_cnt = 0; bit_cnt < 10; ++bit_cnt)
{
/* Start bit */
if( bit_cnt == 0)
{
iso_k_low(); // force K line low
iso_l_low(); // force L line low
}
/* Stop bit */
else if ( bit_cnt == 9 )
{
iso_k_high(); // force K line high
iso_l_high(); // force L line high
}
/* Addr bit */
else
{
if( addr & 1 ) // check addr LSB and set lines
{
iso_k_high(); // force K line high
iso_l_high(); // force L line high
}
else
{
iso_k_low(); // force K line low
iso_l_low(); // force L line low
}
addr >>= 1; // next bit
}
timer1_set(0);
while(TCNT1 < TIME_5_BAUD_BIT) // hold bit level
{
if(is_k_out_high() && is_k_in_high()) // check for bus errors
{
return ISO_RETURN_CODE_BUS_ERROR; // error, bus collision!
}
}
} // end for loop
/* transmit 5 baud addr complete, wait for response now */
SETBIT(iso_glob.uart_status, AUTOBAUD); // detect baud rate from synch pattern
iso_uart_init(); // init iso uart
// wait W1_MAX for synch pattern
timer1_set(0);
while(TCNT1 < TIME_W1_MAX)
{
if( CHECKBIT(iso_glob.uart_status, RDY) )
{
CLEARBIT(iso_glob.uart_status, RDY);
if( iso_glob.uart_buffer != 0x55)
return ISO_RETURN_CODE_INIT_ERROR; // end if synch pattern is not correct
// wait W2_MAX for keybyte 1
timer1_set(0);
while(TCNT1 < TIME_W2_MAX)
{
if( CHECKBIT(iso_glob.uart_status, RDY) )
{
CLEARBIT(iso_glob.uart_status, RDY);
iso_glob.keybyte1 = iso_glob.uart_buffer; // store keybyte 1
// wait W3_MAX for keybyte 2
timer1_set(0);
while(TCNT1 < TIME_W3_MAX)
{
if( CHECKBIT(iso_glob.uart_status, RDY) )
{
CLEARBIT(iso_glob.uart_status, RDY);
iso_glob.keybyte2 = iso_glob.uart_buffer; // store keybyte 2
timer1_set(0);
while(TCNT1 < TIME_W4_MIN); // wait W4_MIN
iso_uart_putc(~iso_glob.keybyte2); // send keybyte 2 inverse to bus
// wait W4_MAX for inverse address from bus
timer1_set(0);
while(TCNT1 < TIME_W4_MAX)
{
if( CHECKBIT(iso_glob.uart_status, RDY) )
{
CLEARBIT(iso_glob.uart_status, RDY);
if(iso_glob.uart_buffer != inv_addr)
return ISO_RETURN_CODE_INIT_ERROR; // end if inverse addr is not correct
// else
bus_init_led_on(); // indicate successful bus init
return ISO_RETURN_CODE_OK; // init complete and OK
} // end if flag RDY wait for inverse address
} // end while TIME_W4_MAX
return ISO_RETURN_CODE_INIT_ERROR; // end with error if inverse addr timeout
} // end if flag RDY wait for keybyte2
} // end while TIME_W3_MAX
return ISO_RETURN_CODE_INIT_ERROR; // end with error if keybyte2 timeout
} // end if flag RDY wait for keybyte1
} // end while TIME_W2_MAX
return ISO_RETURN_CODE_INIT_ERROR; // end with error if keybyte1 timeout
} // end if flag RDY wait for synch pattern
} // end while TIME_W5_MAX
return ISO_RETURN_CODE_INIT_ERROR; // end with error if synch pattern timeout
}
/*
**---------------------------------------------------------------------------
**
** Abstract: fast bus init routine
**
**
** Parameters: none
**
**
** Returns: Error code
**
**
**---------------------------------------------------------------------------
*/
char iso_fast_init(void)
{
bus_init_led_off(); // turn off indication LED
iso_wait_idle(); // wait for bus idle time
iso_glob.uart_n_baud = N_10400; // set baud rate to 10,4kBaud
// send fast init wakeup pattern
iso_k_low();
iso_l_low();
timer1_start(T1_PRESCALER);
while(TCNT1 < TIME_TiniL); // force L and K line 25ms low
iso_k_high();
iso_l_high();
timer1_start(T1_PRESCALER);
while(TCNT1 < TIME_TiniH); // force L and K line 25ms high
/* send StartCommRequest message */
unsigned char start_comm[4] = {0xC1, 0x33, 0xF1, 0x81};
if( iso_send_msg(start_comm, sizeof(start_comm)) != ISO_RETURN_CODE_OK)
return ISO_RETURN_CODE_BUS_ERROR;
unsigned char time_count = 0;
unsigned int cnt = 0;
unsigned char iso_msg_buf[10];
unsigned char *iso_msg_pntr;
do
{
iso_msg_pntr = &iso_msg_buf[0]; // reset pointer
/*
Run this loop until we received a valid response frame, or response timed out
response timeout is P2 max = 50ms
This loop will run a maximum of 12 times, because iso_recv_msg() has its own
timeout of 4ms
*/
cnt = iso_recv_msg(iso_msg_buf); // receive ISO respond
cnt -= 1; // exclude checksum
// check for error free response and valid checksum
if( !(cnt & 0x8000) && (iso_checksum(iso_msg_buf, cnt) == *(iso_msg_pntr+cnt) ) )
{
// check if StartCommPositiveResponse message
if(*(iso_msg_pntr+cnt-3) == 0xC1)
{
iso_glob.keybyte1 = *(iso_msg_pntr+cnt-2); // store keybyte 1
iso_glob.keybyte2 = *(iso_msg_pntr+cnt-1); // store keybyte 2
bus_init_led_on(); // indicate successful bus init
return ISO_RETURN_CODE_OK; // init complete and OK
}
}
++time_count;
} while(time_count < TIME_FASTINIT_P2_MAX);
return ISO_RETURN_CODE_INIT_ERROR;
}
/*
**---------------------------------------------------------------------------
**
** Abstract: This routine coordinates the transmition and reception of bits. This
** routine is automatically executed at a rate equal to the baud-rate. When
** transmitting, this routine shifts the bits and sends it. When receiving,
** it samples the bit and shifts it into the buffer.
**
**
** Parameters: none
**
**
** Returns: status register flags (uart_status)
** BUSY This bit indicates whenever the UART is busy
** TD Transmit Data. Set when the UART is transmitting
** RDR Receive Data Ready. Set when new data has arrived
**
**
**---------------------------------------------------------------------------
*/
SIGNAL(SIG_OVERFLOW0)
{
TCNT0 = iso_glob.uart_reload; // load timer0 for 1 bitlength
--iso_glob.uart_bit_cnt; // start bit allready send
/* transmit section */
if( CHECKBIT(iso_glob.uart_status, TD) ) // check for transmit in progress
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -