Forum: Mikrocontroller und Digitale Elektronik Transmit Pin für USART


von Oliver (Gast)


Lesenswert?

Hallo in die Runde,

hätte mal eine kleine Frage, habe folgende Transmit Routine geschieben. 
Doch da ist noch ein "delay" drin. Geht das auch besser? Pin D2 muss auf 
High zum senden.
1
void USART_Transmit( unsigned char data )
2
{
3
  
4
  PORTD |= (1<<PORTD2);
5
  while ( !( UCSR0A & (1<<UDRE0)) )
6
  ;
7
  UDR0 = data;
8
        //das delay....
9
  _delay_ms(1);
10
  PORTD &= ~(1<<PORTD2);
11
  
12
}

Gruß

Oliver

von Jim M. (turboj)


Lesenswert?

Klar geht das kürzer, einfach hinterher warten:
1
void USART_Transmit( unsigned char data )
2
{
3
  
4
  PORTD |= (1<<PORTD2);
5
  
6
  UDR0 = data;
7
        //das delay....
8
  while ( !( UCSR0A & (1<<UDRE0)) )
9
  ;
10
  PORTD &= ~(1<<PORTD2);
11
  
12
}


Aber falls mehr als 1 Byte am Stück gesendet wird möchte man eventuell 
keine Nadel-Impulse auf dem Transmit Pin haben...

von Falk B. (falk)


Lesenswert?

@Oliver (Gast)

>hätte mal eine kleine Frage, habe folgende Transmit Routine geschieben.
>Doch da ist noch ein "delay" drin. Geht das auch besser? Pin D2 muss auf
>High zum senden.

Ja. Nutze den TXC Interrupt.

von Oliver (Gast)


Lesenswert?

Hallo,

Danke für den Tip,

Habe es mit "AVR306: Using the AVR UART in C on tinyAVR and megaAVR 
devices"
probiert, doch leider mache ich da was falsch.

Wo sollte mein Pin AN/Aus hin?
1
ISR(USART_UDRE_vect)
2
{
3
  unsigned char tmptail;
4
5
  /* Check if all data is transmitted */
6
  if ( USART_TxHead != USART_TxTail )
7
  {
8
    PORTD |= (1<<PORTD2);
9
    /* Calculate buffer index */
10
    tmptail = ( USART_TxTail + 1 ) & USART_TX_BUFFER_MASK;
11
    USART_TxTail = tmptail;      /* Store new index */
12
    
13
    UDR0 = USART_TxBuf[tmptail];  /* Start transmition */
14
  }
15
  else
16
  {
17
    UCSR0B &= ~(1<<UDRIE0);         /* Disable UDRE interrupt */
18
    PORTD &= ~(1<<PORTD2);
19
  }
20
}

So schon mal nicht, und hier war auch ohne erfolg:
1
void USART0_Transmit( unsigned char data )
2
{
3
  PORTD |= (1<<PORTD2);
4
  unsigned char tmphead;
5
  /* Calculate buffer index */
6
  tmphead = ( USART_TxHead + 1 ) & USART_TX_BUFFER_MASK; /* Wait for free space in buffer */
7
  while ( tmphead == USART_TxTail );
8
9
  USART_TxBuf[tmphead] = data;           /* Store data in buffer */
10
  USART_TxHead = tmphead;                /* Store new index */
11
12
  UCSR0B |= (1<<UDRIE0);                    /* Enable UDRE interrupt */
13
 PORTD &= ~(1<<PORTD2);
14
  
15
}


sorry, was mach ich da falsch?

Gruß

Oliver

von Hp M. (nachtmix)


Lesenswert?

Oliver schrieb:
> sorry, was mach ich da falsch?

Vielleicht kennst du den Unterschied zwischen einem UART und einem USART 
nicht.

von Oliver (Gast)


Lesenswert?

Hallo,

also der USART ohne Interrupt geht ja, doch das delay ist schlecht. 
Jetzt bin ich dem Tip mit der Interruptroutine gefolgt. Dieser Code ist 
auch an RS232 ohne Tramsmit ON pin funktional. Jetzt ist nur das mit dem 
PD2 on /off
noch mein Problem!?

Cu Oliver

von Oliver (Gast)


Angehängte Dateien:

Lesenswert?

Wo mache ich den Sende Enable pin An bzw aus?

von AVR-ler (Gast)


Lesenswert?

Hallo,

> Wo mache ich den Sende Enable pin An bzw aus?

Das SendEnable-Bit riecht sehr nach einem RS485-Treiberbaustein ...

Zum Thema: das Enable-Bit muss gesetzt werden, BEVOR das 
USART-Datenregister geschrieben wird, und muss zurückgesetzt werden, 
NACHDEM die Übertragung des Datenbytes abgeschlossen ist.
Dazu gibt es im Register "UCSRA" das Bit "TX_complete", das nach 
erfolgtem Aussenden gesetzt wird. Es kann auch einen Interrupt auslösen; 
ansonsten müsste man in der TX-Routine warten, bis dieses Bit gesetzt 
wird (und es danach zurücksetzen).
Nur so ist sichergestellt, dass nicht während des Sendens der Sender 
vorzeitig deaktiviert wird.

von Oliver (Gast)


Lesenswert?

Hallo ist das so OK oder immer noch nicht richtig?
1
ISR(USART_UDRE_vect)
2
{
3
  unsigned char tmptail;
4
5
  /* Check if all data is transmitted */
6
  if ( USART_TxHead != USART_TxTail )
7
  {
8
    //PORTD |= (1<<PORTD2);
9
    /* Calculate buffer index */
10
    tmptail = ( USART_TxTail + 1 ) & USART_TX_BUFFER_MASK;
11
    USART_TxTail = tmptail;      /* Store new index */
12
    
13
    UDR0 = USART_TxBuf[tmptail];  /* Start transmition */
14
  }
15
  else
16
  {
17
    UCSR0B &= ~(1<<UDRIE0);         /* Disable UDRE interrupt */
18
    PORTD &= ~(1<<PORTD2); // Enable abschalten !!!!!!!!!!!!!!
19
  }
20
}
21
22
void USART0_Transmit( unsigned char data )
23
{
24
  PORTD |= (1<<PORTD2); // Enable anschalten !!!!!!!!!!!!!!
25
  unsigned char tmphead;
26
  /* Calculate buffer index */
27
  tmphead = ( USART_TxHead + 1 ) & USART_TX_BUFFER_MASK; /* Wait for free space in buffer */
28
  while ( tmphead == USART_TxTail );
29
30
  USART_TxBuf[tmphead] = data;           /* Store data in buffer */
31
  USART_TxHead = tmphead;                /* Store new index */
32
33
  UCSR0B |= (1<<UDRIE0);                    /* Enable UDRE interrupt */
34
  
35
  
36
}

Gruß

Oliver

von Oliver (Gast)


Lesenswert?

leider erstens Zeichen immer falsch...

von Karl H. (kbuchegg)


Lesenswert?

Oliver schrieb:

> ISR(USART_UDRE_vect)

Der Data Register Empty Interrupt wird ausgelöst, wenn das UDR0 bereit 
ist, das nächste Zeichen aufzunehmen. Da es allerdings 2 fach gebuffert 
ist, bedeutet das noch lange nicht, dass dann das Zeichen schon draussen 
ist. Wie schon gesagt: dazu gibt es den Transmit Complete Interrupt

von Oliver (Gast)


Lesenswert?

Ok danke, doch Lieder habe ich kein tutorial gefunden dass mir das mit 
dem transmit complete näher bringt. Wo könnte ich sowas finden, bitte 
nicht nur Google schreiben. Denn gegoogelt habe ich schon.
Danke für die hilfe.

Gruß oliver

Ps: am Handy getippt. Und bin kein C Profi nur angefangener..

von Karl H. (kbuchegg)


Lesenswert?

Oliver schrieb:
> Ok danke, doch Lieder habe ich kein tutorial gefunden dass mir das mit
> dem transmit complete näher bringt. Wo könnte ich sowas finden

SO wie immer: Du weisst wie der Interrupt heisst, im Datenblatt findest 
du das Register und den Bitnamen um ihn freizuschalten, du weisst wie 
eine ISR geschrieben wird und in der ISR schaltest du den Pin 
entsprechend um.

Der Rest bleibt so wie er ist. Nur das hier
1
    PORTD &= ~(1<<PORTD2); // Enable abschalten !!!!!!!!!!!!!!
wandert in die ISR für den Transmit Complete Interrupt und ist dort die 
einzige Anweisung. Wozu brauchst du da jetzt ein Tutorial?

von Oliver (Gast)


Lesenswert?

Hallo Gemeinde,

DANKE erstmal für die Hilfe, ja es hat gedauert, doch jetzt habe ich
folgendes und es scheint zu funktionieren.
1
void USART0_Init( unsigned int baudrate )
2
{
3
  unsigned char x;
4
  DDRD |= (1<<DDD2);
5
6
  /* Set the baud rate 115200 bei 18,432mHz*/
7
  UBRR0H = (unsigned char) (baudrate>>8);
8
  UBRR0L = (unsigned char) baudrate;
9
  
10
  /* Enable UART receiver and transmitter und TXCIE0 Transmit Complete*/
11
  UCSR0B = ( ( 1 << RXCIE0 ) | ( 1 << RXEN0 ) | ( 1 << TXEN0 ) | ( 1 << TXCIE0) );
12
  
13
  /* Set frame format: 8 data 1stop */
14
  UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);              
15
  
16
  /* Flush receive buffer */
17
  x = 0;
18
19
  USART_RxTail = x;
20
  USART_RxHead = x;
21
  USART_TxTail = x;
22
  USART_TxHead = x;
23
}
24
25
ISR(USART_TX_vect)
26
{
27
  PORTD &= ~(1<<PORTD2);
28
}
29
30
ISR(USART_UDRE_vect)
31
{
32
  unsigned char tmptail;
33
34
  if ( USART_TxHead != USART_TxTail )
35
  {
36
    PORTD |= (1<<PORTD2);
37
    PORTD |= (1<<PORTD2);
38
    
39
    tmptail = ( USART_TxTail + 1 ) & USART_TX_BUFFER_MASK;
40
    USART_TxTail = tmptail;      
41
    
42
    UDR0 = USART_TxBuf[tmptail];  
43
  }
44
  else
45
  {
46
    UCSR0B &= ~(1<<UDRIE0);         
47
  }
48
}

Gruß

Oliver

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.