Hi, ich programmiere mit einem AT32UC3A1512 und nutze das ATMEL AVR Softwareframework. Mein Problem ist folgendes, ich will ein DMX Signal (512 Byte Länge + 1 Startbyte ) empfangen und dieses manipuliert wiedergeben. Hierfür nutze ich den PDCA und USART1. Hier die Initialisierung der USART: // USART options. usart_options_t USART_OPTIONS = { .baudrate = 250000uL, .charlength = 8, .paritytype = USART_NO_PARITY, .stopbits = USART_2_STOPBITS, .channelmode = USART_NORMAL_CHMODE }; portENTER_CRITICAL(); { // first byte is reserved for the pdca CurrentDmxFrame_u8p = &TxChannels_u8[ 0 ][ 1 ]; NextDmxFrame_u8p = &TxChannels_u8[ 1 ][ 1 ]; CurrentReceiveFrame_u8p = &RxChannels_u8[ 0 ][ 0 ]; IdleReceivingFrame_u8p = &RxChannels_u8[ 1 ][ 0 ]; FinishedReceiveFrame_u8p = &RxChannels_u8[ 2 ][ 0 ]; IdleReceivedFrame_u8p = &RxChannels_u8[ 3 ][ 0 ]; DmxInitPdca_v(); // Configure USART. // // Enable USART RXD & TXD pins. if(UsartId == serCOM1) { xUsart = &AVR32_USART0; gpio_enable_module_pin(AVR32_USART0_RXD_0_0_PIN, AVR32_USART0_RXD_0_0_FUNCTION); gpio_enable_module_pin(AVR32_USART0_TXD_0_0_PIN, AVR32_USART0_TXD_0_0_FUNCTION); Irq_u32 = AVR32_USART0_IRQ; } else { xUsart = &AVR32_USART1; gpio_enable_module_pin(AVR32_USART1_RXD_0_0_PIN, AVR32_USART1_RXD_0_0_FUNCTION); gpio_enable_module_pin(AVR32_USART1_TXD_0_0_PIN, AVR32_USART1_TXD_0_0_FUNCTION); Irq_u32 = AVR32_USART1_IRQ; } // Initialize USART in RS232 mode. usart_init_rs232(xUsart, &USART_OPTIONS, CP_PBA_SPEED); // We're not fully done yet: disable receiver and transmitter. xUsart->cr |= AVR32_USART_CR_RXDIS_MASK | AVR32_USART_CR_TXDIS_MASK; // Register the USART interrupt handler to the interrupt controller and // enable the USART interrupt. INTC_register_interrupt((__int_handler)&vUSART_ISR, Irq_u32, AVR32_INTC_INT1); // Enable USART interrupt sources (but not Tx for now)... // xUsart->ier = AVR32_USART_IER_RXRDY_MASK | AVR32_USART_IER_RXBRK_MASK; xUsart->ier = AVR32_USART_IER_RXBRK_MASK; // Enable receiver and transmitter... xUsart->cr |= AVR32_USART_CR_RXEN_MASK | AVR32_USART_CR_TXEN_MASK; } portEXIT_CRITICAL(); Wie man sieht, benutz ich für den Empfang 4 Buffer, welche jeweils ein komplettes Frame halten können. Grund dafür ist, ich dachte das Senden und Empfang auf dem gleichen Speicherbereich könnte problematisch werden, darum ein "Ringbuffer" der immer ein Frame zwischen den aktuellen Schreib bzw. Lesebuffer hält. Hier die Initialisierung für den RX PDCA: // PDCA channel options for RX and receiving the start byte const pdca_channel_options_t pdca_options_0 = { .addr = 0, // memory address .pid = AVR32_PDCA_PID_USART1_RX, // select peripheral - data are transmit on USART RX line. .size = 0, // transfer counter .r_addr = 0, // next memory address .r_size = 0, // next transfer counter .mode = PDCA_MODE_BYTE, // select size of the transfer }; pdca_init_channel( DMX_PDCA_CHANNEL_RX, &pdca_options_0 ); INTC_register_interrupt((__int_handler)&pdca_int_handler_rx, AVR32_PDCA_IRQ_0, AVR32_INTC_INT1); Allerdings aktiviere ich für den RX PDCA kein Interrupt, da ich die Überprüfung des empfangenen Frames und zusätzlich die Synchronsation des Frames im RXBRK machen wollte. Es klappt eigentlich auch ganz gut, allerdings hab ich manchmal ein Glitch drinnen, d.h. das erste Datenbyte stehen manchmal auf der 1. Position im Buffer oder manchmal auch im 2. Dass ich mit dieser Sequenz auch in den im ERRATA Beschriebenen Fall komme (kein TTGR gesetzt und ich deswegen ein BRK mehr bekomme, ist mir bewusst, wird auch ausgeblendet). Hier der Bereich der ISR, die den Receive Break behandelt: // received BREAK if( ulStatus & AVR32_USART_IER_RXBRK_MASK ) { if( ValidBreak_u8 == FALSE ) { ValidBreak_u8 = TRUE; return ( retVal ); } else { ValidBreak_u8 = FALSE; } portENTER_CRITICAL(); { Temp_u8p = FinishedReceiveFrame_u8p; FinishedReceiveFrame_u8p = IdleReceivedFrame_u8p; IdleReceivedFrame_u8p = CurrentReceiveFrame_u8p; CurrentReceiveFrame_u8p = IdleReceivingFrame_u8p; IdleReceivingFrame_u8p = Temp_u8p; pdca_load_channel( DMX_PDCA_CHANNEL_RX, CurrentReceiveFrame_u8p, 514 ); pdca_enable( DMX_PDCA_CHANNEL_RX ); } portEXIT_CRITICAL(); } andere Interrupts wurden für diesen Bereich deaktiviert. Setze ich nun die Timeguard auf 1, ist dieser Effekt (wechselnde Position des 1. Datenbytes im Buffer) auf ein Minimum reduziert, allerdings ist dann das Verhalten so träge, dass es für meinen Einsatzzweck nicht ausreicht. Jetzt hab ich die Frage, mache ich noch etwas falsch oder hat jmd. noch eine Idee?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.