📄 iso.c
字号:
{
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 + -