Ich hab mal was mit mehreren AVR aufgebaut.
Die Komm. erfolgt im Multi-Prozessor-Comm.-Mode mit RS422.
Weiß nicht ob es dir was nützt:
Variablen:
volatile uint8_t cluster_address;
volatile uint8_t send_counter;
volatile uint8_t send_numbers;
volatile uint8_t send_buffer[256];
volatile uint8_t rx_data_buffer[256];
volatile uint8_t rx_data_valid[256];
volatile uint8_t rx_state;
volatile uint8_t rx_data_counter;
volatile uint8_t rx_data_sum;
|
Initialisierung:
void init_comm ( void )
{
//-- port directions --------------------------------------------
DDRD |= (1<<PD4) | (1<<PD3); // recv/send pin to output
DDRB |= (1<<PB4) | (1<<PB6); // bus send/recvd leds
PORTB |= (1<<PB4) | (1<<PB6); // switch off send/revc-led
//-- uart registers ---------------------------------------------
UBRR1H = 0;
UBRR1L = 25; // 38.4kbaud @ 16MHz
UCSR1A = (1<<MPCM);
UCSR1B = (1<<RXCIE) | (1<<RXEN) | (1<<TXEN) | (1<<UCSZ2);
UCSR1C = (3<<UCSZ0); // 9bit mode
//-- timer for timing surveillance ------------------------------
TIMSK |= (1<<TOIE0);
|
Funktion zum Senden von Frames:
void send_packet ( uint8_t destination,
uint8_t counts,
uint8_t *data )
{
//-- local var's ------------------------------------------------
uint8_t loop = 0x00;
uint8_t checksum = 0x00;
//-- destination address ----------------------------------------
send_buffer[ 0x00 ] = destination;
checksum += destination;
//-- source address ---------------------------------------------
send_buffer[ 0x01 ] = cluster_address;
checksum += cluster_address;
//-- number of data bytes ---------------------------------------
send_buffer[ 0x02 ] = ( counts + 0x01 );
checksum += ( counts + 0x01 );
//--wait until last transm finished -----------------------------
while ( send_counter != send_numbers );
//-- fill data into send-buffer ---------------------------------
for ( loop = 0x00; loop <= counts; loop++ )
{
send_buffer[loop + 0x03] = *data;
checksum += *data;
data++;
}
//-- calculate checksum -----------------------------------------
send_buffer[loop + 0x03] = ( ~checksum + 1 );
//-- preload values to sending ----------------------------------
send_numbers = counts + 0x04;
send_counter = 0x00;
//-- state led: send data ---------------------------------------
PORTB &= ~(1<<PB6); // switch on send-led
PORTD |= (1<<PD4); // switch to bus send
//-- enable transmitter int -------------------------------------
UCSR1B &= ~(1<<RXCIE); // switch off receiver
UCSR1B |= (1<<UDRIE);
}
ISR ( USART1_UDRE_vect )
{
//-- wait until UDR is empty ------------------------------------
while ( !( UCSR1A & (1<<UDRE)) );
//-- first byte: mark as address --------------------------------
if ( send_counter == 0x00 )
{
UCSR1B |= (1<<TXB8);
}
else
{
UCSR1B &= ~(1<<TXB8);
}
UDR1 = send_buffer[send_counter];
//-- still char's to send? --------------------------------------
if ( send_counter == send_numbers )
{
UCSR1B &= ~(1<<UDRIE);
UCSR1B |= (1<<TXCIE);
}
else
{
send_counter++;
}
}
ISR ( USART1_TX_vect )
{
//-- switch off transmitter & back to recev ---------------------
PORTB |= (1<<PB6); // switch off send-led
PORTD &= ~(1<<PD4); // switch to bus recv
UCSR1B |= (1<<RXCIE); // switch on receiver
UCSR1B &= ~(1<<TXCIE); // switch off transmitter
}
|
Empfang von Frames
ISR ( USART1_RX_vect )
{
uint8_t temp;
//-- fetch receiced data & store --------------------------------
temp = UDR1;
switch ( rx_state )
{
//-- address received -------------------------------------------
case ( rx_state_idle ):
//-- address match? ---------------------
if ( ( temp == cluster_address )
|| ( temp == 0xFF ) ) // broadcast address
{
//-- start timing surveilance -------
TIFR |= (1<<TOV0); // clear overflow flag
TCNT0 = 0x00; // preload timer
TCCR0 = (3<<CS00); // clk/32
//-- data receive -------------------
UCSR1A &= ~(1<<MPCM); // switch off mcpm
//-- data counter & storage ---------
rx_data_counter = 0x00;
rx_data_sum = temp;
rx_data_buffer[rx_data_counter] = temp;
//-- state led: receive data --------
PORTB &= ~(1<<PB4); // switch on recv-led
//-- next state in state maschine ---
rx_state = rx_state_receving;
}
break;
//-- data received ------------------------------------------
case ( rx_state_receving ):
//-- restart timing surveilance ---------
TIFR |= (1<<TOV0); // clear overflow flag
TCNT0 = 0x00; // preload timer
TCCR0 = (3<<CS00); // clk/32
//-- data counter & storage -------------
if ( rx_data_counter == 255 ) // packet overlength
{
//-- stopp timing surveilance -------
TCCR0 = 0x00;
//-- state led: receive data --------
PORTB |= (1<<PB4); // switch off recv-led
//-- prepare for new address --------
UCSR1A = (1<<MPCM); // switch on mcpm
rx_state = rx_state_idle;
}
else
{
rx_data_buffer[++rx_data_counter] = temp;
rx_data_sum += temp;
}
break;
}
}
ISR ( TIMER0_OVF_vect )
{
uint8_t loop_counter = 0x00;
//-- stopp timing surveilance -----------------------------------
TCCR0 = 0x00;
//-- state led: receive data ------------------------------------
PORTB |= (1<<PB4); // switch off recv-led
//-- prepare for new address ------------------------------------
UCSR1A = (1<<MPCM); // switch on mcpm
rx_state = rx_state_idle; // reset state maschine
//-- test recvd data for errors ---------------------------------
if ( ( rx_data_buffer[2] + 3 == rx_data_counter ) // no data missing?,
&& ( (uint8_t) rx_data_sum == 0x00 ) )// checksum ok
{
//-- do public for application ----------
for ( loop_counter = 0x00; loop_counter != rx_data_counter; loop_counter++)
{
rx_data_valid[loop_counter] = rx_data_buffer[loop_counter];
}
}
}
|