PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] UART bei ATTINY AVR 1 Serie (ATTINY 412)



Gnom67
25.12.2018, 23:01
Hallo!

Ich scheitere daran, den UART eines ATTINY412 zum Laufen zu bekommen... Ich möchte erstmal einfach Zeichen übertragen mit 9600 Baud, 8N1. An der Gegenstelle (Notebook) hängt ein USB-UART-Konverter (CP2102) und ein einfacher serieller Monitor (ich benutze den von der Arduino IDE). Damit habe ich auch schon Daten von einem ATTINY13 mit Soft-Serial-Emulation empfangen. Wenn ich Daten vom Notebook sende und TX mit RX verbinde, kommen sie über diesen Loopback auch an. Also der Monitor geht.

Das Programmieren grundsätzlich klappt - ein Blinkskript kriege ich jedenfalls zum Laufen. (Zum Programmieren verwende ich ATMEL Studio 7.)
Ich hab zwar einige Erfahrung mit Computern, Programmierung und Elektronik, aber mit Mikrocontrollern bin ich noch nicht besonders erfahren. Dazu kommt, dass die "neuen" Tinys" irgendwie etwas anders funktionieren, als die früheren Modelle (ATMEGA328, TINY85, ...). Deshalb finde ich auch keine Codeschnipsel, aus denen ich mir was basteln kann.

Was ich bisher probiert habe, läuft auf folgende Codeteile hinaus:



#define FOSC 20000000UL //Clock Speed
#define BAUDX 9600UL
#define MYUBRR FOSC/16/BAUDX-1

#include <avr/io.h>
#include <util/delay.h>

void USART_Init( unsigned int ubrr)
{
// Set Tx to output
PORTA_DIRSET = 2;
// Set Tx high
PORTA_OUTSET = 2;
// Set baud rate
USART0_BAUDL = (unsigned char)ubrr;
USART0_BAUDH = (unsigned char)(ubrr>>8);
// Enable transmitter
USART0_CTRLB = (1<<USART_TXEN_bp);
// Set Frame format 8 bit, 1 stop
USART0_CTRLC = 3;
}

int main(void)
{

USART_Init(MYUBRR);

while (1)
{

// Put data into buffer
USART0_TXDATAL = ('A');
_delay_ms(1000);
}
}


Wenn ich das Programm mit dem Simulator und Debugger teste, schreibt er auch alle Register wie erwartet.
- PA1 wird auf Output high gesetzt.
- In USART0.BAUD steht 129
- CTRLC und B werden entsprechend gesetzt.

Unsicher bin ich mir bei der Baudeinstellung. Aus dem Datenblatt werd ich nicht schlau - es heißt dort, dass die oberen 10 Bit des 16-Bit-Registers für die Ganzzahl sind, die unteren 6 für den Nachkommaanteil. Wie soll das funktionieren?
Ist der RC-Takt von 20000000 für die Berechnung maßgeblich oder der interne Takt (standardmäßig mit Prescaler 6, also auf 3333333 Hz)? Ichhab beides probiert - ohne Erfolg.


Hat jemand von euch ein Codebeispiel mit dem man das Ding zum Laufen kriegt? Mir genügt es erstmal, wenn wenigstens einzelne Buchstaben ankommen - darauf könnte ich dann wenigstens aufbauen.

seite5
25.12.2018, 23:27
Wenn das das komplette Programm ist, dann läuft der tiny wahrscheinlich nicht mit 20MHz, sondern mit 3.33MHz.
Manual, Seite 59:
"After any Reset, CLK_MAIN is provided by the 16/20MHz oscillator (OSC20M) and with a Prescaler
division factor of 6."

mfg
Achim

Gnom67
25.12.2018, 23:35
Das stimmt, der Tiny läuft definitiv mit 3333333 Hz - die Frage ist nur, von welchem Takt der UART ausgeht - vom RC-Takt oder vom runtergeteilten Systemtakt.
Ich hab aber wie gesagt beides ausprobiert - ohne Erfolg. Daran alleine kanns also nicht liegen.

seite5
26.12.2018, 08:09
Also lt. Block (S. 57) nimmt der UART seinen Takt auch vom MAIN CLOCK PRESCALER.
Ich weiß nicht, wie genau der interne RC-Takt ist, vielleicht hilft's, den Wert fürs Baudraten-Register etwas nach oben oder unten zu variieren?
mfg
Achim

wkrug
26.12.2018, 08:11
Ich hab man kurz ins Datenblatt geschaut.
Der USART hat hier insgesamt 13 Register - Sind die auch alle richtig befüllt?
Soweit Ich das verstehe sind auch 3 unterschiedliche Taktquellen möglich.

Ausgehend von den "alten" Tiny Controllern würde ich vermuten, das der USART mit dem Prozessortakt läuft.
Wenn Du ein Oszilloskop hast, könntest Du ja mal gucken, welche Bitlänge Du hast - Dann sollte das eindeutig sein.
Das Startbit ist ja eigentlich immer 0 und sollte sich so detektieren lassen. Mit dem Bitmuster 0xAA sollte dann auch ein ständiger Wechsel zwischen 0 und 1 detektierbar sein.

seite5
26.12.2018, 08:44
Woher stammt Deine Baudratenformel? Auf Seite 252, Datenblatt, steht was ganz anderes.
mfg
Achim

Gnom67
26.12.2018, 11:12
Also lt. Block (S. 57) nimmt der UART seinen Takt auch vom MAIN CLOCK PRESCALER.
Ich weiß nicht, wie genau der interne RC-Takt ist, vielleicht hilft's, den Wert fürs Baudraten-Register etwas nach oben oder unten zu variieren?
mfg
Achim

Auf der Zeichnugn finde ich keinen UART - nur "Other Peripherals" und laut Text und Bild nehmen alle Teile außer NVM, RAM und CPU den Takt von CLK_PER. So stehts auch in Kapitel 24.3.2.1. Also, der UART müsste mit 3333333Hz laufen.
Variieren ist nicht das Thema, denn es kommt ja gar nichts an - wenns nur ein wenig verzerrt wäre, hätte ich wenigsens Buchstabensalat. Außerdem hat der 412 eine interne Kalibrierung, die wohl ab Werk eingemessen ist.

- - - Aktualisiert - - -


Ich hab man kurz ins Datenblatt geschaut.
Der USART hat hier insgesamt 13 Register - Sind die auch alle richtig befüllt?
Soweit Ich das verstehe sind auch 3 unterschiedliche Taktquellen möglich.

Ausgehend von den "alten" Tiny Controllern würde ich vermuten, das der USART mit dem Prozessortakt läuft.
Wenn Du ein Oszilloskop hast, könntest Du ja mal gucken, welche Bitlänge Du hast - Dann sollte das eindeutig sein.
Das Startbit ist ja eigentlich immer 0 und sollte sich so detektieren lassen. Mit dem Bitmuster 0xAA sollte dann auch ein ständiger Wechsel zwischen 0 und 1 detektierbar sein.

Laut Datenblatt sind für die Initialisierung Tx auf out high zu schalten, BAUD und Frame zu setzen, Operation mode zu setzen und Tx zu aktivieren.
Die meisten Register sind schon nach Initialisierung korrekt. Mode und Frame müsste man gar nicht setzen.
Ich hab im Simulator die Register geprüft - es wird alles so weit ich das beurteilen kann - korrekt gesetzt. CLK steht auf 20 MHz internal und Prescaler enabled und 0x8 (also Prescaler 6).

Oszi hab ich nicht. Aber irgendwas müsste ja rauskommen. Selbst wenn ich eine LED an den Ausgang hänge, hab ich keinerlei Flackern oder sowas.

- - - Aktualisiert - - -

- - - Aktualisiert - - -


Woher stammt Deine Baudratenformel? Auf Seite 252, Datenblatt, steht was ganz anderes.
mfg
Achim

Stimmt. Hab ich inzwischen auch korrigiert - die Formel war aus einem Codeteil eines Atmega328. Jetzt lautet es:
#define MYUBRR 4 * FOSC/BAUDX

Bringt aber auch nichts.



Laut Anleitung soll der BAUD-Wert in das 16-Bit-Register BAUD. Dabei wären die oberen 10 Bit der Ganzzahlteil und die unteren 6 Bit der Nachkommaamteil (Kap. 24.3.2.1). Versteht das jemand?
Wenn ich rechne, komme ich auf 4 * 3333333 / 9600 = 1388,88875.
1388 passt schon mal nicht in 10 Bit, da ist ja bekanntlich bei 1023 Schluss.
Und wie soll man den Nachkommaanteil in das Register bekommen?
Mein Code schreibt brav 0x56C in das 16-Bit Regsiter - das entspricht aber nicht der Teilung auf 10 und 6 Bit.
Das mit den Nachkommastellen versteh ich eh nicht. Da hätte man doch auch den Wert gleich mit 64 multiplizieren können um alles 6 Bit nach links zu shiften... Außerdem kommt mir ein Prescaler mit Nachkommastellen etwas komisch vor.
Kanns ich da jemand einen Reim drauf machen?

seite5
26.12.2018, 12:56
Datenblatt: The USART.BAUDL and USART.BAUDH register pair represents the 16-bit value, USART.BAUD (s. 273)
Wie kommst Du auf 10bit?
Schreib die Werte doch mal direkt:
Datenblatt: For a write operation, the low byte of the 16-bit register must be written before the high byte.
USART0_BAUDL=0x6C;
USART0_BAUDH=0x05;

mfg
Achim

Ich glaube, Du verwendest ein falsches Datenblatt.

Gnom67
26.12.2018, 13:00
Für die Auswahl des richtigen Datenblattes reicht mein IQ glaube ich gerade noch.
Kannst ja mal selsbt schauen... Wie ich drauf komme, hatte ich verwiesen: Kapitel 24.3.2.1.
Seite 252: For asynchronous operation, the BAUD register value is 16 bits. The 10 MSBs (BAUD[15:6])
hold the integer part, while the 6 LSBs (BAUD[5:0]) hold the fractional part.

Das widerspricht ja auch nicht der Aussage auf Seite 273, dass zwei 8-Bit-Register zusammen einen 16-Bit-Wert speichern.

Holomino
26.12.2018, 15:52
Mal Anmerken:
- Die LED siehst Du nicht flackern, wenn Du nur 1 Byte pro Sekunde sendest. Da kannst Du mal eine 0 senden bei vielleicht 3..5ms Wiederholrate.
- Alle Peripherien sind mittlerweile in den neueren Controllern als Strukturen definiert. Statt z.B. USART0_CTRLB = … kann man auch USART0.CTRLB = … schreiben. Dann kommt man auch in den Genuss des _WORDREGISTER-Features (Schreiben eines 16-Bit-Registerpaares in einem Rutsch).
- Du hast beachtet, dass beim UART-Wandler die TxD-Leitung des Controllers an RxD des Wandlers angeschlossen werden muss?

seite5
26.12.2018, 16:54
Wollte Dir nicht auf die Füße treten ...
Bleiben ja nicht mehr viele Möglichkeiten. Hab ehrlich gesagt den Port-MUX bei diesem Controller nicht ganz verstanden (War in früheren Atmel-DBs einleuchtender
formuliert). Evtl. muß der Port auf alternative Nutzung gesetzt werden: PORTMUX.CTRLB |= 1; ?

mfg
Achim

Gnom67
26.12.2018, 17:01
Mal Anmerken:
- Die LED siehst Du nicht flackern, wenn Du nur 1 Byte pro Sekunde sendest. Da kannst Du mal eine 0 senden bei vielleicht 3..5ms Wiederholrate.
- Alle Peripherien sind mittlerweile in den neueren Controllern als Strukturen definiert. Statt z.B. USART0_CTRLB = … kann man auch USART0.CTRLB = … schreiben. Dann kommt man auch in den Genuss des _WORDREGISTER-Features (Schreiben eines 16-Bit-Registerpaares in einem Rutsch).
- Du hast beachtet, dass beim UART-Wandler die TxD-Leitung des Controllers an RxD des Wandlers angeschlossen werden muss?

Hm, ja, das stimmt - so ein Byte braucht nur ne Millisekunde - bei 10 siehts man es noch - bei einer ist es zu kurz.

Dann kann ich also den Wert in BAUD auch mit USART0.BAUD = baud schreiben... klingt gut. Wenn ich es so mache, schreibt er (im Simulator) brav E77B in das 16 Bit-Register BAUD. Die oberen 10 Bit entsprechen dann 1010110110, also dezimal 694 - Das stimmt mit meiner Rechnung überein byubrr = 4 * 3333333) / 19200 (ich hab jetz mal 19200 baud gewählt, weil bei 9600 der Wert über 1023 kommt und er mir die erste Binärstelle abschneidet).
Wenn ich mal rückwärts rechne, komme ich bei 3333333Hz auf eine minimale Datenrate von 13033 baud, bei 20 MHz auf 78201 baud. Das kann doch irgendwie nicht sein, dass man den Mikroconroller bei voller Taktrate nicht mit kleineren baudraten betreiben kann - das ist doch widersinnig.

Ja, den Anschluss habe ich so gemacht. Tx des Tiny412 ist Pin 4, den hab ich an Rx des USB-UART-Adapters angeschlossen. Ich habe auch GND des USB-UART mit GND des Tiny verbunden.


Ich hab ein bisschen gemessen. Der Rx-Anschluss des USB-UART-Adapters liegt auf 3,3 Volt. Der Tx des Tiny ist auf OUT HIGH geschaltet - liegt auf ca. 4 Volt (Stromversorgung aus dem USB-Port des Notebooks über einen Arduino Nano, der als ISP dient).
Wenn ich das richtig sehe, müsste der UART beim Senden den Tx-Port auf LOW schalten und die Spannung auf GND ziehen.
Wenn ich beim USB-UART Rx gegen GND "kurzschließe", messe ich 1,5 mA - das sollte der Tx-Pin des Tiny ohne Probleme auf GND bringen können - meines Wissens können die Pins bis zu 40 mA Sourcce und Sink verkraften.
Der Serielle Monitor emprängt auch Buchstabensalat, wenn ich willkürlich Rx auf GND kontakte.

Hat noch jemand Ideen?

oberallgeier
26.12.2018, 17:19
.. der Tiny läuft definitiv mit 3333333 Hz - die Frage ist nur, von welchem Takt der UART ausgeht ..Mal n´ etwas schräger Vorschlag (mit dem Hintergrund - egal welche Baudrate - es blinkt wenn gesendet wird) : für meinen Fuseretter (https://www.roboternetz.de/community/threads/45827-Fuse-irrt%C3%BCmlich-auf-extern-Takt-Hier-die-einfachste-L%C3%B6sung%21) war eine der Grundideen, dass beim Senden sehr vieler "U"s mit 8N1 die Bitfolge "010101010101010101010101010101010101010101.." übermittelt wird. WENN Du also an Deinem RX-Pinn (oder misstrauisch auch am TX) eine LED anschließt und von Deinem Controller mal ne Kiste "U"s sendest:


init_uart0 ((u16)(F_CPU/ 600 / 16 - 1.0)); //
for (u16 n=0; n<10000; n++) // LED blinken lassen
{ // TestLED
uputs0 ("U");
} // Ende von for (u16 n=0; n<10000; n++)

dann werden entsprechend viele "U" gesendet, binär eben diese "..0101010101.."-Kolonne. Das sieht man am Flackern der LED selbst bei 600 Bd. Mit 400 Bd noch deutlicher *gg* - habe ich grad mit nem mega328p getestet. Ergebnis: auch ohne Oszilloskop sieht man grob, ob etwas gesendet wird.

Im Übrigen: viel Erfolg - egal wie.

Nachtrag: als grobe Beurteilung könnte man noch (optisch - mit der MEthode des genauen Hinsehens) prüfen, ob zwischen 600 Bd und 400 Bd bzw. 300 Bd ein deutlicher Unterschied feststellbar ist.

Nachtrag2: das große "C", ASCII 0b 100 0011, geht noch deutlicher *gg*.

Gnom67
26.12.2018, 17:49
Wollte Dir nicht auf die Füße treten ...
Bleiben ja nicht mehr viele Möglichkeiten. Hab ehrlich gesagt den Port-MUX bei diesem Controller nicht ganz verstanden (War in früheren Atmel-DBs einleuchtender
formuliert). Evtl. muß der Port auf alternative Nutzung gesetzt werden: PORTMUX.CTRLB |= 1; ?

mfg
Achim

Es gibt zwar ein Register PORTMUX CTRLB USART0 - aber laut Tabelle gibt es keine alternativen Ports...

IRRTUM!!!

In Atmel Start kann man Ports PA1/2 oder PA6/7 konfigurieren. Und siehe da, im Start-Mustercode finde ich, dass 6/7 die Standardkonfiguration ist und 1/2 (die einzige, die im Datenblatt steht) ist die alternative... als, Stecker in Pin 2 statt Pin 4 und hurra - es blinkt am USB-UART...
Empfang funktioniert allerdings nur bei 300 Baud, obwohl ich die Rechnung mit 19200 gemacht habe... das deutet doch irgendwie drauf hin, dass die Formel nicht stimmen kann (was ja schon wunderlich wäre, wenn man wiee gesagt bei 20 Mhz eine minimale Baudrate von 70K hätte). Mit der Baudrate tüftel ich jetzt noch etwas rum...

Danke für die Hilfe. Achim, den Portmux hätte ich nicht in Frage gestellt, wenn du das nicht noch mal aufs Tapet gebracht hättest...


Letzter Stand: Die Formel Stimmt - aber das Ergebnis wird schlicht und einfach in das 16-Bit-Register geschrieben und nicht in die oberen 10 Bit. Was der Schwachsinn im Datenblatt soll mit den 10 MSB und den 6 LSB (Seite 252) ist mir rätselhaft. Dieses miserable Datenblatt hat mich nun zwei Tage meines Lebens gekostet (zum Glück nur zwei eh ziemlich öde Weihnachtsfeiertage ;-) ).

oberallgeier
26.12.2018, 18:13
.. Dieses miserable Datenblatt ..Ich war auch schon mal recht erbost über ein Datenblatt von Microchip (https://www.roboternetz.de/community/threads/71472-ATmega328-P-TC1-Control-Register-A-schlecht-dokumentiert) Technology, bei dem die im Vorgänger von Atmel herausgegebene Dokumentation an einer völlig unnötigen und unschönen Stelle gekürzt wurde - nämlich bei benummerten Namen von Registerbits, z.B. bei TCCR1A werden die lediglich als COM1 beschrieben, müssen aber als COM1A0/~1 bzw COM1B0/~1 programmiert werden. Zum Glück hatte ich noch die alte Version von ATMEL gespeichert . . . Mein Kommentar dazu am microchip blieb bis heute (ziemlich genau 1 Jahr) unbeantwortet . . .

Gnom67
26.12.2018, 18:53
Ärgerlich, sowas!!! Kann doch nciht so schwer sein, solche Sachen mal zu korrigieren. Ich hab das Datenblatt bei Microchip direkt von der Website geladen. Die könnten das ruhig mal aktualisieren.

wkrug
26.12.2018, 19:04
Ärgerlich, sowas!!! Kann doch nciht so schwer sein, solche Sachen mal zu korrigieren. Ich hab das Datenblatt bei Microchip direkt von der Website geladen. Die könnten das ruhig mal aktualisieren.
Na ja, die Microchip Jünger haben die ATMEL Leute ja immer belächelt, denn "Bei Microchip ist ja alles viel Professioneller".
Ich fürchte auch, das es das ATMEL Studio auch nicht mehr lange geben wird und das dann in irgendeiner Microchip Variante mit eingebunden wird.

Gnom67
26.12.2018, 21:52
Hab etwas rumgegoogelt. Der halbwegs vergleichbare Attiny202/402 hat wenigstens die korrekten Belgungen der Mux-Tabelle. Dafür ist dort PA1 auf Pin 5 und PA2 auf Pin 4 angegeben - es ist aber andersrum und der Quatsch mit dem 10 und 6 Bits steht da auch. (Der Faktor 64 in der Formel ist wohl genau dieses Shifting der 6 Nachkommastellen in die unteren 6 Bits - man kann es auch kompliziert machen!) Dafür stimmt wengistens die Pinanordnung in der Pinout-Grafik (in beiden Datenblättern).

Atmel Start liefert die Pindaten ebenso falsch, wenn man in der Konfiguration die alternativen Ports PA1/2 wählt und sich das dann in der Pinmux-Übersicht anschaut. Zwar stimmt die Zuordnung der PAn, aber die Pinnummern stimmen nicht und die Grafik ist falsch.

Falls also noch jemand mal den UART eines neueren Tiny nutzen will:

Die UART-Standardbelegung des Attiny412 ist
Tx = PA6 = Pin 2
Rx = Pa7 = Pin 3
Die alternative Pinbelegung ist:
Tx = PA1 = Pin 4
Rx = PA2 = Pin 5
(Rx hab ich allerdings in beiden Fällen noch nicht ausprobiert...)

Der Berechnete Wert BAUD = (64 * CLK_PER) / (S * fBAUD), im NORMAL MODE = 4 * CLK_PER / fBaud wird ganz einfach in das 16-Bit-Regsiter BAUD geschrieben.

- CLK-PER ist der durch den Prescaler PDIV runtergeteilte Systemtakt (Standard also 3333333, weil 20000000 durch den Standard-Prescaler 6 geteilt wird).
- S ist 16 im NORMAL MODE und 8 im CLK2X MODE (letzteres hab ich nicht probiert).
- fBAUD ist die gewünschte Baudrate (9600, ...). Maximal müsste der Tiny 20000000/16 = 1250000 schaffen (NORMAL MODE).

Ich habs bis 500000 probiert - mehr macht mein Serial Monitor nicht mit. Die übertragung läuft über 10 Meter dünnen Schaltdraht einwandfrei. Der Interne Taktgeber reicht dafür offenbar aus - in der Hinsicht sind die AVR-1-Serie Controller wohl echt besser als die alten.

wkrug
27.12.2018, 08:10
Der Interne Taktgeber reicht dafür offenbar aus - in der Hinsicht sind die AVR-1-Serie Controller wohl echt besser als die alten.
Bei den Alten war die Geschwindigkeit des internern Oszillators stark von der Temperatur abhängig.
Nicht, das Du Dir da das nächste Problem einfängst.

Gnom67
27.12.2018, 22:17
Bei den Alten war die Geschwindigkeit des internern Oszillators stark von der Temperatur abhängig.
Nicht, das Du Dir da das nächste Problem einfängst.

Die neuen AVR 1 Series haben eine Kalibrierung und sind angeblich recht genau. Außerdem ist die Temperaturabhängigkeit zwischen ca. 10 und 70 °C nach der Zeichnung im Datenblatt relativ gering. Damit sollte es deutlich weniger Probleme geben als mit den alten AVR.
Die ersten Testübertragungen mit 500000 Baud über 10 m lütten Schaltdraht haben jedenfalls schon mal gut funktioniert. Hoffen wir also das Beste.