Hallo leute, ich habe die Bibliothek von peter Fleury benutzt um eine programm zu shreiben. das programm sollte daten empfangen und senden via ein Puffer. so weit funktionniert das Progamm reltiv gut. aber es gibt eine klein problem: einigen daten gehen verloren und das hängt normalerweise von der Flusscontrol ab. als Flusscontrol benutze ich die Hardware handshake. aber es funktionniert immer nicht. als CTS und RTS habe ich zwei Pin des PORTD gewählt und zwar Pin 4 als CTS und Pin3 als RTS. Das Programm sollte so reagieren: wenn die Empfang Puffer voll ist soll die controller zu dem PC signalisiert das sie keine Daten mehr empfangen kann (also sein CTS ausschalten) dannach sollte er die Puffer ausleern dafür sendt er die Daten zurrückt zur Hyperterminal des PC und wenn die Empfang Puffer leer ist sollt die Controller wieder zum PC signalisiert das sie daten noch empfangen kann also CTS wieder einschalten. Hier untern ist mein code mit dem Hilfe von Peter fleury Lib. Bitte schauen Sie die mal und helfen sie mir die Hardware handshake zu lösen vielen danke ISR(USART_RXC_vect) //SIGNAL(UART0_RECEIVE_INTERRUPT) /*********************************************************************** ** Function: UART Receive Complete interrupt Purpose: called when the UART has received a character ************************************************************************ **/ { unsigned char tmphead; unsigned char data; unsigned char usr; unsigned char lastRxError; /* read UART status register and UART data register */ usr = UART0_STATUS; data = UART0_DATA; /* */ #if defined( AT90_UART ) lastRxError = (usr & (_BV(FE)|_BV(DOR)) ); #elif defined( ATMEGA_USART ) lastRxError = (usr & (_BV(FE)|_BV(DOR)) ); #elif defined( ATMEGA_USART0 ) lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) ); #elif defined ( ATMEGA_UART ) lastRxError = (usr & (_BV(FE)|_BV(DOR)) ); #endif /* calculate buffer index */ tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK; if ( tmphead == UART_RxTail ) { /* error: receive buffer overflow */ // lastRxError = UART_BUFFER_OVERFLOW >> 8; PORTD = 0x04;// RTS ein CTS aus controller kann senden und kann // nicht empfangen return; }else{ /* store new index */ UART_RxHead = tmphead; /* store received data in buffer */ UART_RxBuf[tmphead] = data; } PORTD = 0x04; UART_LastRxError = lastRxError; } ISR(USART_UDRE_vect) //SIGNAL(UART0_TRANSMIT_INTERRUPT) /*********************************************************************** ** Function: UART Data Register Empty interrupt Purpose: called when the UART is ready to transmit the next byte ************************************************************************ **/ { unsigned char tmptail; if ( UART_TxHead != UART_TxTail) { /* calculate and store new buffer index */ tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK; UART_TxTail = tmptail; /* get one byte from buffer and write it to UART */ UART0_DATA = UART_TxBuf[tmptail]; /* start transmission */ }else{ PORTD = 0x08;//CTS ein Dien Controller kann wieder empfangen /* tx buffer empty, disable UDRE interrupt */ UART0_CONTROL &= ~_BV(UART0_UDRIE); } } /*********************************************************************** ** Function: uart_init() Purpose: initialize UART and set baudrate Input: baudrate using macro UART_BAUD_SELECT() Returns: none ************************************************************************ **/ //void uart_init(unsigned int baudrate) void uart_init(void) { UART_TxHead = 0; UART_TxTail = 0; UART_RxHead = 0; UART_RxTail = 0; UCSRB |= (1<<TXEN) |(1<<RXEN)|(1<<RXCIE); // tx/rx enable UCSRC |= (1<<URSEL)|(3<<UCSZ0); // Asynchron 8N1 #if F_CPU < 2000000UL && defined(U2X) UCSRA |= (1<<U2X); /* improve baud rate error by using 2x clk */ UBRRL = (F_CPU / (8UL * UART_BAUD)) - 1; #else UBRRL = (F_CPU / (16UL * UART_BAUD)) - 1; #endif } /*********************************************************************** ** Function: uart_getc() Purpose: return byte from ringbuffer Returns: lower byte: received byte from ringbuffer higher byte: last receive error ************************************************************************ **/ unsigned int uart_getc(void) { unsigned char tmptail; unsigned char data; if ( UART_RxHead == UART_RxTail ) { return UART_NO_DATA; /* no data available */ } /* calculate /store buffer index */ tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK; UART_RxTail = tmptail; /* get data from receive buffer */ data = UART_RxBuf[tmptail]; PORTD = 0x04;// RTS einschalten Controller kann jetzt senden return (UART_LastRxError << 8) + data; }/* uart_getc */ /*********************************************************************** ** Function: uart_putc() Purpose: write byte to ringbuffer for transmitting via UART Input: byte to be transmitted Returns: none ************************************************************************ **/ void uart_putc(unsigned char data) { unsigned char tmphead; tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK; while ( tmphead == UART_TxTail ){ ;/* wait for free space in buffer */ } UART_TxBuf[tmphead] = data; UART_TxHead = tmphead; PORTD = 0x08;// CTS ein (Die controller ist wieder bereit zu empfangen) /* enable UDRE interrupt */ UART0_CONTROL |= _BV(UART0_UDRIE); }/* uart_putc */ int main(void) { DDRD = 0xFF; PORTD = 0x08;// 4.Pin des PORTD eischalten um das CTS //anzusprechen (empfangt Bedingung im seit der controller) unsigned int c; char buffer[7]; int num=134; /* * Initialize UART library, pass baudrate and AVR cpu clock * with the macro * UART_BAUD_SELECT() (normal speed mode ) * or * UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode) */ //uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); uart_init(); /* * now enable interrupt, since UART library is interrupt controlled */ sei(); /* * Transmit string to UART * The string is buffered by the uart library in a circular buffer * and one character at a time is transmitted to the UART using interrupts. * uart_puts() blocks if it can not write the whole string to the circular * buffer */ uart_puts("String stored in SRAM\n"); /* * Use standard avr-libc functions to convert numbers into string * before transmitting via UART */ itoa( num, buffer, 10); // convert interger into string (decimal format) uart_puts(buffer); // and transmit string to UART /* * Transmit single character to UART */ //uart_putc('\r'); for(;;) { /* * Get received character from ringbuffer * uart_getc() returns in the lower byte the received character and * in the higher byte (bitmask) the last receive error * UART_NO_DATA is returned when no data is available. * */ c = uart_getc(); if ( c & UART_NO_DATA ) { /* * no data available from UART */ } else { /* * send received character back */ uart_putc( (unsigned char)c ); } } }
Ich habe den Code jetzt nicht im Detail analysiert. Aber: Wenn du dem Sender die Sendefreigabe erst dann entziehst, wenn du feststellst, dass im Empfangsbuffer kein Platz mehr ist, dann ist das zu spät! 1) Du hast bereits ein Zeichen empfangen aber keinen Platz um es abzuspeichern. Was tun mit dem Zeichen? Es muss also verlorengehen 2) Nachdem du dem Sender die Sendefreigabe entzogen hast, solltest du besser damit rechnen, dass noch mindestens 1 Zeichen über die Leitung kommt. Denn: Was soll denn der Sender machen, wenn er bereits mit der Übertragung eines Zeichens angefangen hat und mittendrinn kommt ihm dein CTS/RTS in die Quere. Er kann ja die bereits angefangene Übertragung nicht rückgängig machen. -> Dem Sender wird die Sendefreigabe bereits entzogen, wenn dein Buffer so bei ca. 80% gefüllt ist. Hängt auch von der Buffergröße ab. Bei größeren Buffern wird man die Grenze vielleicht bei 90% ansetzen. Wichtig ist jedoch: Du darfst nicht warten, bis der Buffer randvoll ist. Auch wenn du RTS/CTS setzt, kann da noch was eintrudeln, was im Buffer gespeichert werden muss.
ich verstehe schon was du meinst. wenn du zeit hast Karl analysiert meine code und sagt mir wo ich der empfanger freischalten bzw abschalten genauso für das senden (wenn die Controller daten zurrückt zum PC schicken will) Danke. MFG R.Jano
R.Jano wrote: > ich verstehe schon was du meinst. wenn du zeit hast Karl analysiert > meine code und sagt mir wo ich der empfanger freischalten bzw abschalten > genauso für das senden (wenn die Controller daten zurrückt zum PC > schicken will) Ganz sicher nicht.
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.