USART1 beim ATMega644P

Gast #5645095
Lesenswert?
• ▲
▼
Ich versuche gerade, mit den USART1 beim ATMega644P zu verwenden. 
Eigentlich dachte ich ja, das ist ganz einfach, ich kopiere mir den Code 
vom USART0 und ändere einfach die 0 in eine 1:
1
// Initialisuerung, es soll nur TX verwendet werden
2
uint16_t UBRR0_value=(F_CPU/8L/57600)-1;
3
UCSR1A |= (1 << U2X0);
4
UBRR1H = UBRR0_value >> 8;
5
UBRR1L = UBRR0_value;
6
UCSR1B |= (1 << TXEN1);
7

8
// Daten senden
9
if ((UCSR1A & (1<<UDRE0))!=0)
10
{
11
   UDR1 = value;
12
}

Allerdings: der Ausgang ist ständig auf High-Pegel und sendet auch nix. 
Was habe ich übersehen?
Gast #5645113
Lesenswert?
• ▲
▼
Das Bauraten Register ist ein 16-Bit Register. Dazu steht im Datenblatt 
geschrieben:

8.6. Accessing 16-bit Registers
The AVR data bus is 8 bits wide, and so accessing 16-bit registers 
requires atomic operations. These
registers must be byte-accessed using two read or write operations. 
16-bit registers are connected to the
8-bit bus and a temporary register using a 16-bit bus.
For a write operation, the low byte of the 16-bit register must be 
written before the high byte. The low byte
is then written into the temporary register. When the high byte of the 
16-bit register is written, the
temporary register is copied into the low byte of the 16-bit register in 
the same clock cycle.

Und so ganz komplett ist die Tauschaktion "0" gegen "1" wohl auch nicht:
UCSR1A |= (1 << U2X0);
if ((UCSR1A & (1<<UDRE0))!=0)
{
   UDR1 = value;
}
Gast #5645136
Lesenswert?
• ▲
▼
Ok, das Programm sieht jetzt so aus:
1
void serial_init()
2
{
3
// Set baud rate
4
#if BAUD_RATE < 57600
5
   uint16_t UBRR0_value = ((F_CPU / (8L * BAUD_RATE)) - 1)/2 ;
6
   UCSR0A &= ~(1 << U2X0); // baud doubler off  - Only needed on Uno XXX
7
#else
8
   uint16_t UBRR0_value=(F_CPU/8L/BAUD_RATE)-1; // ((F_CPU / (4L * BAUD_RATE)) - 1)/2;
9
   UCSR0A |= (1 << U2X0);  // baud doubler on for high baud rates, i.e. 115200
10
#endif
11
   UBRR0H = UBRR0_value >> 8;
12
   UBRR0L = UBRR0_value;
13

14
   // enable rx, tx, and interrupt on complete reception of a byte
15
   UCSR0B |= (1<<RXEN0 | 1<<TXEN0);
16

17

18
  // Set baud rate
19
#if BAUD_RATE < 57600
20
   UCSR1A &= ~(1 << U2X1); // baud doubler off  - Only needed on Uno XXX
21
#else
22
   UCSR1A |= (1 << U2X1);  // baud doubler on for high baud rates, i.e. 115200
23
#endif
24
   UBRR1H = UBRR0_value >> 8;
25
   UBRR1L = UBRR0_value;
26

27
   // enable tx
28
   UCSR1B |= (1 << TXEN1);
29
  // defaults to 8-bit, no parity, 1 stop bit
30
}
31

32

33
void serial_write_tx1(const uint8_t value)
34
{
35
  if ((UCSR1A & (1<<UDRE1))!=0)
36
  {
37
     UDR1 = value;
38
  }
39
}

USART0 soll RX und TX können, USART1 nur TX. Dass serial_write_tx1() ein 
Byte verliert, wenn das Senden gerade nicht geht, ist gewollt.

Was ich mich frage: muss ich den TX1 pin nicht noch irgendwie von GPIO 
auf UART umschalten?
Gast #5645155
Lesenswert?
• ▲
▼
Zaphod schrieb:
> Ok, das Programm sieht jetzt so aus:

> void serial_write_tx1(const uint8_t value)
> {
>   if ((UCSR1A & (1<<UDRE1))!=0)
>   {
>      UDR1 = value;
>   }
> }
>
> USART0 soll RX und TX können, USART1 nur TX. Dass serial_write_tx1() ein
> Byte verliert, wenn das Senden gerade nicht geht, ist gewollt.
Warum?

> Was ich mich frage: muss ich den TX1 pin nicht noch irgendwie von GPIO
> auf UART umschalten?
Nein,
ich initialisere die UsartX Pins trotzdem und setze den RXn 
(Input-)Pullup auf an.

So kann einen einen USB-TTL-Wandler an- und abstecken ohne Probleme.

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