Transmit Pin für USART

Gast #4377371
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
#4377387
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...
Gast #4377576
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
Gast #4377587
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
Gast #4377985
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.
Gast #4378128
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
Gast #4379861
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..
#4381201
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?
Gast #4387308
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren