Forum: Compiler & IDEs Flusscontrol steurung(RTS/CTS)


von R.Jano (Gast)


Lesenswert?

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 );
        }
    }

}

von Karl H. (kbuchegg)


Lesenswert?

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.

von R.Jano (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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
Noch kein Account? Hier anmelden.