Im Interrupt funktionen benutzen?

Ich habe hier eine ISR die immer ausgelöst wird wenn ein Zeichen an der Seriellen Schnittstelle zu lesen ist.
Eingehängt ist diese an ISR(UART2_RX_IRQ).
Ich hoffe es richtig zu verstehen, das ich dann im UDR2 Register den Wert lesen kann.

volatile uint8_t  MPNGRCInput::raw_data[34]	
...
/* ISR for SRLX on UART2 */
void MPNGRCInput::_SERIAL_SRLX_isr(void) 
{
uint8_t wert;
static uint8_t ctr;
          wert=UDR2;
         if (wert==0xA2) ctr=0;
         	if (ctr<=34) {
         		raw_data[ctr]=wert;     		       		
         		 	     ctr++	 
         	            } 
              	if (ctr=34)
              		        {
           		          // Telegramm komplett, hier müsste ein CRC Check erfolgen etwa so
      	         		   uint16_t    crc=0;
                                         for(i=0; i<=32; i++)           
                                                  crc=CRC16(crc,raw_data[i]);
  
      	         		              uint16_t   checkcrc=(raw_data[33]<<8 | raw_data[34]);  
                                          if (crc==checkcrc) {
                                                               // Daten in Ordnung 
                                                                             
                                                                           }
         	         		        }      


}

Die Funktion sollte ab Startbyte 0xA2 ein 35 Byte großes Array füllen.
Wenn das Array voll ist, muss ich aus den ersten 33 Byte ein CRC berechenen.
Die Funktion habe ich schon in einem ähnlichen Projekt verwendet und funktioniert

uint16_t CRC16(uint16_t crc, uint8_t value)
{
uint8_t i; 
crc = crc ^ (uint16_t)value<<8;
for (i=0; i<8; i++)
    {
      if (crc & 0x8000)
          crc=crc << 1 ^0x1021;
          else
           crc = crc << 1;
    }
    return crc;
}

Aber:
Kann oder darf ich in der ISR die Funktion checkcrc aufrufen ? Und wenn ja wenn muss diese volatile definiert sein ?
Oder ist der Code in der ISR generell zu umfangreich ?

Grundsätzlich geht sowas. Und die Funktion sieht auch nicht so teuer aus. Im schlimmsten Fall nimmst Du eben die Baudrate runter auf 9600 Baud. Und weil es eine Funktion ohne Seiteneffekte ist brauchst Du auch nirgends volatile. Volatile brauchst Du eigentlich nur bei (globalen) Variablen auf denen Du in Interrupts Seiteneffekte erzeugst.

Danke für die Info.
Nur mit dem Runtersetzen der Baudrate wird es schwierig.
Der Arduino hängt nämlich an einem Multiplex Empfänger der die Stellungen der Regler Digital an einer seriellen Schnittstelle mit
115200 Baud ! liefert. (Und die Baudrate ist nicht veränderbar)
Das ganze ist Teil der Steuerung für einen Quadrokopter.

Schon wegen der hohen Baudrate habe ich Bedenken, denn laut Datenblatt mache ich bei 16 mhz einen Fehler von +2.1%
Wenn U2X2 gesetzt

        UBRR2 = 16;	// 115200 Baud    
	UCSR2A |= (1 << U2X2);

Wenn U2X2 nicht gesetzt einen Fehler von -3.5%.

Ich hatte dies schon in dem Multiwii Projekt unter Benutzung der Arduino Seriell Funktionen, dort funktionierte es.
Nur dieses Projekt ist mit dem Multiwii Projekt kaum zu vergleichen, da deutlich umfangreicher,
Die CPU läuft hier schon fast auf Anschlag,
Wobei jetzt die externen Interupts für die Pulsweitenmessung nicht mehr gebraucht werden.
Also try'n error :wink:

Diese Baudraten Fehler sind bei den geraden Taktraten normal. Mal mehr, mal weniger. Da die Baudrate vom Prozessortakt abgeleitet ist. Um die Baudrate exakt einzuhalten bräuchte man einen krummen Prozessortakt wie z.B. 11,059 MHz. Die Quarze gibt es, aber dann ändern sich natürlich auch die anderen Timings. Die Fehler sind auch ok, solange sie sich in Grenzen halten.