Guten Tag,
ich versuche gerade, einen Software UART (bzw. die Transmit-Leitung
davon) auf einem Attiny85 zu implementieren. Das integrierte Terminal
Window in Atmel Studio erkennt zumindest schonmal, das etwas übertragen
wird. Mein Code sieht aktuell so aus:
1
#define F_CPU 8000000UL
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
6
volatile uint8_t bytesToTransmit = 0x74;
7
volatile int position = -1;
8
volatile uint8_t needPause = 0;
9
ISR(TIMER1_OVF_vect){
10
if(needPause == 1){
11
needPause = 0;
12
} else {
13
if(position == -1){ //start of transmission
14
PORTB &=~(1<<PINB3); //Start Bit
15
position++;
16
} else {
17
if(position == 8){ //end of transmission
18
position = -1;
19
PORTB |= (1<<PINB3); //Stop Bit
20
needPause = 1;
21
} else{
22
if((bytesToTransmit >> position) & 0x01){
23
PORTB |= (1<<PINB3);
24
} else {
25
PORTB &=~(1<<PINB3);
26
}
27
position++;
28
}
29
}
30
}
31
}
32
33
void initTimer(){
34
TCCR1 |= (0b0010<<CS10); //CK/2
35
TIMSK |= (1<<TOIE1); //enable OVF interrupt
36
sei(); //Enable Interrupts
37
}
38
39
int main(void)
40
{
41
DDRB |= (1<<PINB3); //PINB1 as output
42
PORTB |= (1<<PINB3);
43
initTimer();
44
while(1){
45
46
}
47
}
Eigentliche sollte das Terminal Window 74 im Hex-Modus anzeigen, es
wird jedoch 8f angezeigt, und das, obwohl ich der Meinung bin, dass
die Messung des Logic Analyzers so passt (siehe Bild). Die Baudrate
(15625) hab ich so errechnet: 8MHz / 256 (Timer Overflow) / 2
(Prescaler).
Ich bin für jeden Tipp dankbar.
Der PC kann tatsächlich 15625baud?
Dem LA ist das sicher egal, und wenn da alles gut aussieht, bleib eh nur
die Baud-Rate.
Ich würde erst mal versuchen mit Standard-Speed zu senden: 19200, 38400,
...
Die Grafik sieht OK aus, allerdings solltest du den Ausgang in
Sendepausen dauerhaft auf '1' halten.
Kannst du denn auch mit 15625 Bd empfangen? Das ist ja keine
übliche Baudrate.
Hallo,
Peter (peda) hat vor Jahren sich der Fragestellung angenommen.
Beitrag "Software UART mit FIFO"
Ich nutze diesen Ansatz auch und habe Portierungen auf für attiny85
programmiert.
Danke für eure Antworten,
Carl D. schrieb:> Der PC kann tatsächlich 15625baud?
Man kann die Baudrate beliebig im Terminal Window einstellen. Als
serielle Schnittstelle kommt ein UART / USB Konverter zum Einsatz.
Carl D. schrieb:> Ich würde erst mal versuchen mit Standard-Speed zu senden: 19200, 38400,
Das gestaltet sich bei den festen Prescalern als schwierig, außer ich
benutze die Compare-Interrupts (Edit: Und selbst dann wird es schwer,
die genaue Baudrate zu treffen).
Jakob schrieb:> Kannst du denn auch mit 15625 Bd empfangen? Das ist ja keine> übliche Baudrate.
Ja, wiegesagt. Ich empfange etwas, nur stimmt der Wert nicht.
Jakob schrieb:> Die Grafik sieht OK aus, allerdings solltest du den Ausgang in> Sendepausen dauerhaft auf '1' halten.
Es gibt keine Sendepause, direkt nach dem "Pause" bzw. "Rest"-Bit geht
es wieder von vorne los.
Karl M. schrieb:> Ich nutze diesen Ansatz auch und habe Portierungen auf für attiny85> programmiert.
Danke, werde ich mir mal anschauen.
Alexander S. schrieb:> Warum benutzt du nicht die USI?
Ich hab im Internet mal etwas gestöbert und hab da die Aussage gefunden,
dass sich der USI nicht ganz problemfrei programmieren lässt. Ich schaue
mir den mal an.
Alexander S. schrieb:> Warum benutzt du nicht die USI?
Das USI ist nicht wirklich brauchbar. Typische Beispiel für: Hauptsache
wir sparen, egal was es kostet.
Falls der Tiny85 nicht quarzgenau getaktet wird, würde es sich
noch anbieten, die Baudrate des PCs etwa +/-10% in 1%-Schritten
zu variieren.
- Wenn er das auch kann!
Einstellen darf man manchmal viel, gemacht wird daraus manchmal
nur irgendwas (im besten Falle) Naheliegendes.
Jedenfalls: Ab 3% Abweichung sind "merkwürdige" Empfangsdaten
schnell möglich.
UART mit USI nachbilden? Der Zusatzaufwand beim Programmieren
ist nicht viel geringer, als bei der SW-UART. Die Prozessor-
last könnte etwas geringer sein.
Zu den "Habe ich so-und-so schon gemacht"-Beiträgen:
Eine SW-UART (4,194 MHZ Quarz / 19200 Bd) habe ich auch schon
hinbekommen.
Ehrlicherweise war dabei Vollduplex kein Thema, aber viel Spaß
dabei, das mit der USI-UART zu stricken...
Max M. schrieb:>> Die Grafik sieht OK aus, allerdings solltest du den Ausgang in>> Sendepausen dauerhaft auf '1' halten.>> Es gibt keine Sendepause, direkt nach dem "Pause" bzw. "Rest"-Bit geht> es wieder von vorne los.
Das könnte das Problem sein. Der Empfänger braucht mindestens 13
Stopbits, um sich zuverlässig wieder auf ein Startbit zu
synchronisieren.
fchk
Jakob schrieb:> Einstellen darf man manchmal viel, gemacht wird daraus manchmal> nur irgendwas (im besten Falle) Naheliegendes.
Hm, das kann ich leider schlecht kontrollieren, was da im Hintergrund
wirklich passiert. Ich vertraue dem Programm einfach mal.
Ich versuche gerade mit dem CTC-Modus etwas näher an übliche Baudraten
zu kommen und bin da etwas vom Datenblatt verwirrt. Im TCCR1-Register
muss ich das CTC1-Bit setzen, um den Compare-Match zu aktivieren. Nun
steht in der Bit-Beschreibung:
"When the CTC1 control bit is set (one), Timer/Counter1 is reset to $00
in the CPU clock cycle after a compare
match with OCR1C register value."
Okay, es wird also immer der Wert im OCR1C-Register verglichen. Dann
verstehe ich allerdings nicht, warum man dieses Register nicht als
Interrupt-Ursprung im TIMSK-Register setzen kann, sondern nur OCR1A und
OCR1B?
Frank K. schrieb:> Das könnte das Problem sein. Der Empfänger braucht mindestens 13> Stopbits, um sich zuverlässig wieder auf ein Startbit zu> synchronisieren.
Woher hast du die Information? Im Terminal kann man nur zwischen "1",
"1.5" und "2" Stopbits wählen. Du meinst wahrscheinlich 13 bits
insgesamt pro Übertragung?
Max M. schrieb:> Frank K. schrieb:>> Das könnte das Problem sein. Der Empfänger braucht mindestens 13>> Stopbits, um sich zuverlässig wieder auf ein Startbit zu>> synchronisieren.>> Woher hast du die Information? Im Terminal kann man nur zwischen "1",> "1.5" und "2" Stopbits wählen. Du meinst wahrscheinlich 13 bits> insgesamt pro Übertragung?
Nein, ich meine 13 Bits Pause zwischen zwei Zeichen. Oder zumindest
zwischen zwei Telegrammen. 1 Start Bit plus 8 Datenbits plus Parity plus
2 Stopbits sind 12 Bits, länger kann ein Zeichen nie sein, d.h. mit 13
Bits klappt es garantiert.
Wenn durchgehend zufällige Bytes gesendet werden, wie soll der
Empfänger, wenn er mittendrin anfängt zu hören, das Startbit finden? Das
könnte ja genauso ein Datenbit sein. Jede 1-0-Kombination könnte als
Stop-Startbit vom Empfänger missverstanden werden. Daher 13 Bits Pause
zwischendrin einlegen, um die Synchronisation zuverlässig zu
ermöglichen.
fchk
Warum beim Tiny25/45/85 auf diese Weise (CTC-Bit und OCR1C-
Register) die CTC-Frequenz eingestellt wird, aber keine
Interruptquelle ist, brauchste hier nicht fragen. Ist so.
Für einen zeitgerechten Interrupt musst du noch OCR1A, oder
OCR1B (Wert <= Wert von OCR1C) bemühen und dazu OCIE1A bzw.
OCIE1B aktivieren.
Max M. schrieb:> Danke für eure Antworten,>> Carl D. schrieb:>> Der PC kann tatsächlich 15625baud?>> Man kann die Baudrate beliebig im Terminal Window einstellen. Als> serielle Schnittstelle kommt ein UART / USB Konverter zum Einsatz.
Ich hatte nicht gefragt, ob man das einstellen kann, sondern ob es auch
funktioniert. Das ist nicht das gleiche.
> Carl D. schrieb:>> Ich würde erst mal versuchen mit Standard-Speed zu senden: 19200, 38400,>> Das gestaltet sich bei den festen Prescalern als schwierig, außer ich> benutze die Compare-Interrupts (Edit: Und selbst dann wird es schwer,> die genaue Baudrate zu treffen).
Benutzung der CompareRegister ist aber keine Hexerei. Falls doch, dann
gilt es diese Wissenlücke zu schließen.
> Jakob schrieb:>> Kannst du denn auch mit 15625 Bd empfangen? Das ist ja keine>> übliche Baudrate.>> Ja, wiegesagt. Ich empfange etwas, nur stimmt der Wert nicht.
wenn ein Startbit erkannt wird, dann werden eben n-Datenbits abgetastet
und wenn danach Ruhe auf der Leitung ist, dann ist gut. Ob das erwartete
Stopbits dann wirklich nach den Datenbits kommt, oder das gesendete x00
als x0F ankommt, weil doppelt so schnell gesendet wurde wie empfangen,
ist da nicht klar. Wenn nur die Pause zwischen 2Bytes lang genug ist.
Wie schon geschrieben, wenn der LA ein ordentliches Serial-Byte-Frame
zeigt, aber die Baudrate ungewöhnlich ist, dann sollte der erste
Lösungsversuch eigentlich auf der Hand liegen. Ist nicht so schwer:
F_CPU/Baudrate muß kleiner als Timer-Max sein. Sonst mit F_CPU/Prescaler
noch mal versuchen, bis ein Wert paßt. Dieser kommt dann in OCR1A, Mode
CTC durch CTC1-Bit, ISR(TIMER1_Comp1A_vect) feuert im Bit-Takt.
Einfacher wäre natürlich der Standard-AVR-Timer0, denn Timer1 ist beim
TINYn5 etwas anders als üblich.
Hallo,
Jakob schrieb:> die CTC-Frequenz eingestellt wird, aber keine> Interruptquelle ist, brauchste hier nicht fragen. Ist so.
Stimmt nicht ganz, steht im Datenblatt als Overflow Interrupt !
Ja und funktioniert auch.
Ich verstehe nicht, warum ihr über Startbit-Erkennung und Interrupts
diskutiert, wo doch der TO nur
> einen Software UART (bzw. die Transmit-Leitung> davon) auf einem Attiny85 zu implementieren
will. Zum Senden reichen doch simple delays!
Stefan U. schrieb:> Ich verstehe nicht, warum ihr über Startbit-Erkennung und> Interrupts> diskutiert, wo doch der TO nur>>> einen Software UART (bzw. die Transmit-Leitung>> davon) auf einem Attiny85 zu implementieren>> will. Zum Senden reichen doch simple delays!
Das ist doch blockierend und nicht die feine Art.
Ich verwenden immer einen Sendepuffer und das Senden läuft dann über
einen Timer im Hintergrund.
So kann der AVR µC immer weiter arbeiten und bleibt ansprechbar für
weitere Aufgaben.
Frank K. schrieb:> Nein, ich meine 13 Bits Pause zwischen zwei Zeichen. Oder zumindest> zwischen zwei Telegrammen.
Ich hab das mal versucht umzusetzen:
1
volatile uint8_t bytesToTransmit = 0x74;
2
volatile int position = -1;
3
volatile uint8_t needPause = 0;
4
volatile uint8_t pauseBits = 13;
5
ISR(TIMER1_COMPA_vect){
6
if(needPause == 1 && pauseBits > 0){
7
pauseBits--;
8
if(pauseBits == 0){
9
pauseBits = 13;
10
needPause = 0;
11
}
12
} else {
13
if(position == -1){ //start of transmission
14
PORTB &=~(1<<PINB3); //Start Bit
15
position++;
16
} else {
17
if(position == 8){ //end of transmission
18
position = -1;
19
PORTB |= (1<<PINB3); //Stop Bit
20
needPause = 1;
21
} else{
22
if((bytesToTransmit >> position) & 0x01){
23
PORTB |= (1<<PINB3);
24
} else {
25
PORTB &=~(1<<PINB3);
26
}
27
position++;
28
}
29
}
30
}
31
}
Logic Analyzer Diagramm ist angehängt, der richtige Wert wird trotzdem
nicht erkannt.
Carl D. schrieb:> Ist nicht so schwer:> F_CPU/Baudrate muß kleiner als Timer-Max sein. Sonst mit F_CPU/Prescaler> noch mal versuchen, bis ein Wert paßt. Dieser kommt dann in OCR1A, Mode> CTC durch CTC1-Bit, ISR(TIMER1_Comp1A_vect) feuert im Bit-Takt.> Einfacher wäre natürlich der Standard-AVR-Timer0, denn Timer1 ist beim> TINYn5 etwas anders als üblich.
Ich hab das mal so probiert:
1
#define F_CPU 3993600UL
2
.
3
.
4
.
5
void initTimer(){
6
TCCR1 |= (1<<CTC1); //Enable CTC
7
TCCR1 |= (0b0010<<CS10); //CK/2
8
OCR1A = 104-1;
9
TIMSK |= (1<<OCIE1A); //enable compare interrupt
10
sei(); //Enable Interrupts
11
}
1
3993600 / 2 (Prescaler) / 104 (CTC-Wert) = 19200
Der Wert stimmt leider immer noch nicht. Wo liegt mein Fehler?
Wie kommst du auf F_CPU = 3993600?
Schriebst du nicht anfangs, sie ist 8 MHz?
Hättest du einen Zähler, könntest du FCPU und die Baudrate
mit NULL-Bytes (ohne die überflüssige Stoppbit-Verlängerung)
messen.
Hast du exakt 4, oder 8 MHz?
Der Internal RC-Oscillator ist nicht sehr genau.
Hast du eigentlich schon mal nach CKDIV8 geschaut?
Wo setzt du das OCR1C-Register für 19,2 kBd?
Bei 8 MHz, CKDIV8 = disable, Prescaler = 2 musst du
OCR1C = 208 - 1 = 207 setzen.
Bei 4 MHz, CKDIV8 = disable, Prescaler = 2 musst du
OCR1C = 104 - 1 = 103 setzen.
OCR1A kann auch 1 sein, dann kannst du OCR1C nach Belieben
zwischen 2 und 254 variieren.
Jakob schrieb:> Wie kommst du auf F_CPU = 3993600?
Hab ich in meinem letzten Abschnitt beschrieben, so komme ich auf 19200
Baud, sofern meine Rechnung stimmt?
Jakob schrieb:> Schriebst du nicht anfangs, sie ist 8 MHz?
Ja, zu Beginn war sie das auch. Da jedoch die empfangenen Bits nicht
stimmen, versuche ich aktuell verschiedene Lösungsansätze.
Jakob schrieb:> Der Internal RC-Oscillator ist nicht sehr genau.
Was genaueres (einen externen Crystal) hab ich leider nicht.
Jakob schrieb:> OCR1A kann auch 1 sein, dann kannst du OCR1C nach Belieben> zwischen 2 und 254 variieren.
Anscheinend hab ich die Funktionsweise von CTC nicht ganz verstanden.
Muss ich etwa in OCR1A den gleichen Wert wie in OCR1C schreiben? OCR1A
ist dann wohl dafür da, um den Interrupt zu erzeugen und in OCR1C steht
der Wert, der tatsächlich mit dem Zählerstand verglichen wird?
F_CPU ist aber nicht ein beliebig wählbarer Wert, sondern ein Konstante,
die der echten CPU-Taktfrequenz entsprechen soll/muß.
Mit internem RC-Oszillator und (ab Werk gesetzter) DIV8-Fuse, läuft der
Tiny85 mit knapp unter 1MHz. Das ist der richtige Wert für F_CPU.
Jakob schrieb:> Warum beim Tiny25/45/85 auf diese Weise (CTC-Bit und OCR1C-> Register) die CTC-Frequenz eingestellt wird, aber keine> Interruptquelle ist, brauchste hier nicht fragen. Ist so.
Nein, ist es nicht. In diesem Modus erzeugt der Compare-Match mit OCR1C
den Überlauf-Interrupt. So steht es im DB und so ist es auch
tatsächlich.
Gedacht ist die Sache hauptsächlich für PWM. OCR1C steuert die
Zykluszeit, mit OCR1A und OCR1B hat man zwei PWM-Kanäle.
Die Funktionalität entspricht in etwa dem Timer1 der Megas. Bei denen
heisst das Register allerdings ICR, weil es zusätzlich noch als
Capture-Register dienen kann. Diese Funktionalität existiert bei den
Tinys leider nicht, aber irgendwie mussten sie das Register halt nennen:
So wurde halt OCR1C daraus.
> Für einen zeitgerechten Interrupt musst du noch OCR1A, oder> OCR1B (Wert <= Wert von OCR1C) bemühen und dazu OCIE1A bzw.> OCIE1B aktivieren.
Nein. Das wiederum ist das Vorgehen bei Timern, die weder ICR- noch
OCRC-Register besitzen. Da spielt dann OCRA die Rolle des Begrenzers des
Zählumfangs und es bleibt mit OCRB nur ein PWM-Kanal. Nur mit vollem
Zählumfang (und entsprechend eingeschränkten Möglichkeiten zur
Einstellung der Zykluszeit) hat man bei diesen Timern 2 PWM-Kanäle.
Aber warum erzähle ich das eigentlich alles? Steht doch haarklein in den
jeweiligen Datenblättern. Man muss es nur noch lesen.
Max M. schrieb:> Eigentliche sollte das Terminal Window 74 im Hex-Modus anzeigen, es> wird jedoch 8f angezeigt, und das, obwohl ich der Meinung bin, dass> die Messung des Logic Analyzers so passt (siehe Bild).
Ich sehe im LA Bild aber (start) + 2E + (stop). Oder halt (stop) +
74 + (start) ...
Carl D. schrieb:>> Carl D. schrieb:>>> Der PC kann tatsächlich 15625baud?>>>> Man kann die Baudrate beliebig im Terminal Window einstellen. Als>> serielle Schnittstelle kommt ein UART / USB Konverter zum Einsatz.>> Ich hatte nicht gefragt, ob man das einstellen kann, sondern ob es auch> funktioniert. Das ist nicht das gleiche.
Der OP hat einen LA, damit kann er die Baudrate und Polarität des USB
Adapters prüfen.
Das sollte er auch mal tun, da könnte es böse Überraschungen geben.
Jim M. schrieb:> Carl D. schrieb:>>> Carl D. schrieb:>>>> Der PC kann tatsächlich 15625baud?>>>>>> Man kann die Baudrate beliebig im Terminal Window einstellen. Als>>> serielle Schnittstelle kommt ein UART / USB Konverter zum Einsatz.>>>> Ich hatte nicht gefragt, ob man das einstellen kann, sondern ob es auch>> funktioniert. Das ist nicht das gleiche.>> Der OP hat einen LA, damit kann er die Baudrate und Polarität des USB> Adapters prüfen.>> Das sollte er auch mal tun, da könnte es böse Überraschungen geben.
Solange er vermutet, mit F_CPU könnte man den Oszillator trimmen ... ;-)
Eric B. schrieb:> Max M. schrieb:>>> Eigentliche sollte das Terminal Window 74 im Hex-Modus anzeigen, es>> wird jedoch 8f angezeigt, und das, obwohl ich der Meinung bin, dass>> die Messung des Logic Analyzers so passt (siehe Bild).>> Ich sehe im LA Bild aber (start) + 2E + (stop). Oder halt (stop) +> 74 + (start) ...
Es wird bei UART aber Start/LSB/...../MSB/Stop gesendet. Also das
zumindest ist richtig. Wenn der LA UART analysieren kann, dann wird er
aber bestimmt mit der Baudrate Probleme haben. Da aber keine Zeiten dran
stehen, kann man nur spekulieren. Mein 8€-LA läuft mit sigrok und kann
das alles.
@ c-hater:
Wo steht das denn im DB?
Ich finde nur:
TOV1 im Normal-Mode bei Überlauf, also 0xFF -> 0x00
oder:
TOV1 im PWM-Mode bei Compare-Match mit OCR1C
Jakob schrieb:> Wo steht das denn im DB?
Nirgends.
> Ich finde nur:> TOV1 im Normal-Mode bei Überlauf, also 0xFF -> 0x00> oder:> TOV1 im PWM-Mode bei Compare-Match mit OCR1C
So ist es auch. Was ich schrieb, gilt nur für den PWM-Modus, aber nicht
für CTC. Im CTC-Modus ist tatsächlich OCR1A für die Begrenzung des
Zählumfangs zuständig. Und der Match löst wohl nicht den TOV1 aus,
zumindest ist das nicht im DB erwähnt.
Das hatte ich irgendwie falsch in Erinnerung. Man sollte halt doch
einfach noch mal in's DB schauen, bevor man was postet...
Spannend wäre mal, was eigentlich passiert, wenn das CTC- und PWM-Bit
gleichzeitig gesetzt sind. Warum gibt's für den TinyX5 nicht so'ne
schicke übersichtliche Modustabelle wie für fast jeden anderen Timer
fast jedes anderen AVR8?
Hallo,
Carl D. schrieb:>> Ich sehe im LA Bild aber (start) + 2E + (stop). Oder halt (stop) +>> 74 + (start) ...
das war mir auch aufgefallen.
>> Es wird bei UART aber Start/LSB/...../MSB/Stop gesendet. Also das
Ernsthaft? Die LA-Bilder bzw. Oszibilder, die ich bisher ausgewertet
habe,
waren anders, MSB first, meine ich...
Aber ich kann mich da irren.
> zumindest ist richtig. Wenn der LA UART analysieren kann, dann wird er> aber bestimmt mit der Baudrate Probleme haben. Da aber keine Zeiten dran> stehen, kann man nur spekulieren. Mein 8€-LA läuft mit sigrok und kann> das alles.
Ahoi, Martin
Nee-nee, LSB first ist schon richtig.
Aber unser TO hat noch Probleme mit der F_CPU.
Mit internem RC-Oscillator sind es nun mal keine genauen 8 MHz
+/-2%, auch wenn man einen Wert per Definition zuweist...
- Und nicht bestätigen kann, wie CKDIV8 gesetzt ist.
- Und vielleicht ohne TTL-RS232-Wandler an einen PC geht.
Da kommt oft auch (irgend)-was an!
@ c-hater
Respekt! Kannst auch kleine Fehlerchen zugeben.
Das bestätigt meinen Eindruck, dass du hier so gut wie immer
fundierte Kenntnisse verbreitest.
Carl D. schrieb:> Mit internem RC-Oszillator und (ab Werk gesetzter) DIV8-Fuse, läuft der> Tiny85 mit knapp unter 1MHz. Das ist der richtige Wert für F_CPU.
Stimmt, im Datenblatt steht:
"The device is shipped with CKSEL = “0010”, SUT = “10”, and CKDIV8
programmed. The default clock source setting
is therefore the Internal RC Oscillator running at 8 MHz with longest
start-up time and an initial system clock
prescaling of 8, resulting in 1.0 MHz system clock."
Ich hab F_CPU nun auf 1000000UL korrigiert.
Jakob schrieb:> - Und vielleicht ohne TTL-RS232-Wandler an einen PC geht.> Da kommt oft auch (irgend)-was an!
Ich hab schon diverse UARTs verschiedener uC benutzt und da gab es
bisher keine Probleme, am Adapter kann es also damit meiner Meinung nach
nicht liegen.
Jakob schrieb:> Und nicht bestätigen kann, wie CKDIV8 gesetzt ist.
Ich hab weiter oben den Text aus dem Datenblatt zitiert, CKDIV8 ist per
default gesetzt.
Carl D. schrieb:> Mein 8€-LA läuft mit sigrok und kann> das alles.
In Salae Logic gibt es kein UART zum auswählen im Analyzer-Tab.
Ich wollte noch mal auf die Pausen-Bits zu sprechen kommen, in diesem
Artikel steht nichts davon, dass die gesamte Länge einer Übertragung 13
bits haben muss?
https://www.mikrocontroller.net/articles/UART
Dieter F. schrieb:> Welche Version hast Du denn?
1.2.10
Ich hab die Pausen-Bits noch mal weggelassen, jetzt komm ich bei 4854
BAUD auf ein Ergebnis, dass relativ nah am Ursprungswert ist, nämlich
73 statt 74. Auf 4854 komme ich durch 1MHz // 2 // 103 (Timer CRC).
Max M. schrieb:> Ich wollte noch mal auf die Pausen-Bits zu sprechen kommen, in diesem> Artikel steht nichts davon, dass die gesamte Länge einer Übertragung 13> bits haben muss?
Muss sie ja auch nicht, denn die Länge eines Datenworts hängt natürlich
vom Frameformat ab. Das längste besteht aus Startbit, 9 Datenbits, einem
Paritätsbit und zwei Stopbits. Insgesamt also 13.
Wenn du nun zu einem zufälligen Zeitpunkt beginnst, das Signal eines
Senders zu empfangen, kann du an jedem Punkt eines solchen Frames sein.
Sprich: du empfängst Rhabarber, weil das erste Low-Bit, was vorbeikommt,
von deinem Empfänger als Startbit interpretiert wird (auch wenn es
tatsächlich überhaupt keins ist).
Sendet nun der Sender kontinuierlich (also Frame an Frame) weiter,
empfangst du mit recht hoher Wahrscheinlichkeit weiter Rhabarber, weil
du ja weiterhin irgendwo in der Mitte des Frames mit deinem nächsten
Empfangsframe beginnst. Wie lange dieser unhaltbare Zustand anhält, wird
nur durch den Inhalt der gesendeten Nachrichten bestimmt. Mit ein bissel
Glück fällt der Empfänger nach wenigen Frames in das korrekte
Frameraster, mit etwas weniger Gück empfängt er aber bis in alle
Ewigkeit nur Rhabarber.
Macht der Sender nun aber gelegentlich eine Pause mit der maximalen
Framelänge, dann ist der Empfänger ab dem nächsten Byte SICHER im
korrekten Frameraster. Einfach deshalb, weil sichergestellt ist, dass in
dieser Zeit kein Startbit vorkommt und ein kein Bit, was
fälschlicherweise als Startbit interpretiert werden könnte. D.h.: der
Empfänger hat auf jeden Fall irgendwann in dieser Zeit erstmal fertig
und wartet auf das Startbit. Und das nächste, was der Sender dann
absondert, ist tatsächlich ein echtes Startbit. Und alle sind
glücklich...
Übrigens kann der Sender für diese Sicherheitspause die Stopbits seiner
normalerweise gesendeten Frames mitrechnen. Wenn er also normalerweise
schon 2 Stopbits sendet, braucht er bloss noch 11 Bitzeiten zusätzlich
Pause zu machen, um die Framesyncronisation des Empfängers unabhängig
vom tatsächlich verwendeten Frameformat sicherzustellen.
Hallo,
Max M. schrieb:>> In Salae Logic gibt es kein UART zum auswählen im Analyzer-Tab.
Doch, heisst "Async serial" und kann auch Autobaud. (in V1.2.10)
Ahoi, Martin
DocMartin schrieb:> Doch, heisst "Async serial" und kann auch Autobaud. (in V1.2.10)
Ah, danke! Da bekomme ich einen Frame Error (mit den vielen Pausen-Bits)
:(
Jetzt wieder (ich war das Wochenende unterwegs).
Der Frameerror liegt wohl eher an der unpassenden Baudrate (ich vermute,
die Punkte stellen den Abtastzeitpunkt dar), sie scheint zu langsam zu
sein.
Setze doch mal den Autobaud-Marker und lasse die Baudrate bestimmen.
Ahoi, Martin
Ich melde mich zurück nachdem ich mal wieder etwas Zeit gefunden habe.
DocMartin schrieb:> Setze doch mal den Autobaud-Marker und lasse die Baudrate bestimmen.
Hab ich, es wird eine Baudrate von 73619 erkannt. Wenn ich die 13
Pause-Bits weglasse, wird eine Baudrate von 34833 erkannt, so oder so
ist das falsch. Ich verstehes nicht, warum erkennt der Analyzer das
Muster nicht?
Max M. schrieb:> ist das falsch. Ich verstehes nicht, warum erkennt der Analyzer das> Muster nicht?
Und ich verstehe nicht warum du nicht 0x0AA oder 0x55 sendest ?
Marc V. schrieb:> Und ich verstehe nicht warum du nicht 0x0AA oder 0x55 sendest ?
Wenn du mir begründest, warum ich das machen sollte, könnte ich dir
vielleicht auch eine Antwort darauf geben, aber so...
Zudem passt in diese Bitfolgen mein 0x74 nicht?
Edit: Jetzt hab ich deinen Hintergedanken verstanden. Ich habs mal
probiert, aber der Analyzer erkennt auch das nicht (0x55). Mit
Pausen-Bits auch nicht.
Ist vielleicht das UART-Protokoll doch ganz anders?
> Wenn du mir begründest, warum ich das machen sollte
Weil das einen regelmäßigen High/Low Wechsel erzeugt, an dem man
blitzschnell ablesen kann, welche Baudrate tatsächlich gesendet wird.
Dein Logic Analyzer tastet das Signal zu schnell ab. Die Baudrate von
dem Gerät ist höher eingestellt, als beim Sender.
> Ist vielleicht das UART-Protokoll doch ganz anders?
Nein nur die Bitrate der beiden Geräte stimmt nicht überein.
Stefan U. schrieb:> Nein nur die Bitrate der beiden Geräte stimmt nicht überein.
Warum gibt es dann die Auto-Baud Funktion überhaupt? Ich mein, wenn ich
erst die Samplerate auf die Baudrate anpassen muss, muss diese doch
bekannt sein?
Mein Terminal erkennt auch 0x55 nicht. Ich nehme aber mal an, die
Rechnung:
1MHz / 2 (Prescaler) / 103 (Timer-Register OCR1A-Wert) = 4854
eignet sich um die Baudrate zu bestimmen?
Max M. schrieb:> Marc V. schrieb:>> Und ich verstehe nicht warum du nicht 0x0AA oder 0x55 sendest ?>> Wenn du mir begründest, warum ich das machen sollte, könnte ich dir> vielleicht auch eine Antwort darauf geben, aber so...
Weil du jetzt gleich sehen kannst, daß die tatsächliche Baudrate etwa
10-12% niedriger ist als beim LA eingestellt und von dir angenommen...
Marc V. schrieb:> daß die tatsächliche Baudrate etwa> 10-12% niedriger ist als beim LA eingestellt...
Meinst du die automatisch ermittelte Baudrate oder die Samplerate des
LA? Eingestellt hab ich die Baudrate beim LA nicht, die wurde
automatisch (falsch) ermittelt. Die Samplerate kann ich in der Software
nur in festen Schritten von 24Ms/s auf 16Ms/s reduzieren.
Max M. schrieb:> Mein Terminal erkennt auch 0x55 nicht. Ich nehme aber mal an, die> Rechnung:>> 1MHz / 2 (Prescaler) / 103 (Timer-Register OCR1A-Wert) = 4854>> eignet sich um die Baudrate zu bestimmen?
Damit kriegst du genau 52us, was einer Baudrate von 19200 entspricht.
Der Fehler sollte unter 1% liegen.
Max M. schrieb:> Meinst du die automatisch ermittelte Baudrate oder die Samplerate des> LA? Eingestellt hab ich die Baudrate beim LA nicht, die wurde
Schick doch mal ein richtiges Screenshot mit Zeitmarkern. Auf diesen
Briefmarken die du schickst, kann kein Mensch was erkennen.
Marc V. schrieb:> Damit kriegst du genau 52us
Wie kommst du auf diesen Wert?
Marc V. schrieb:> Auf diesen> Briefmarken die du schickst, kann kein Mensch was erkennen.
Bitte.
Max M. schrieb:> Meinst du die automatisch ermittelte Baudrate oder die Samplerate des> LA? Eingestellt hab ich die Baudrate beim LA nicht, die wurde
Hier.
Deine Baudrate liegt ungefähr 11% niedriger.
Max M. schrieb:>> Damit kriegst du genau 52us>> Wie kommst du auf diesen Wert?
Sorry, falsch gerechnet
1MHz = 1us
/ 2 = 2us
* 104 = 208 us = 4800B
Deine tatsächliche Baudrate sollte bei etwa 4300 - 4400B liegen.
OK ?
Marc V. schrieb:> OK ?
Danke (an dich und an alle Helfenden)!
Durch trial & error hab ich die Punkte des Analyzers versucht, auf die
Bit-Höcker auszurichten und kam dabei auf eine Baud-Rate von 31500, wenn
ich die in meinem Terminal einstelle, wird der richtige Wert erkannt
(übrigens auch, wenn ich keine 13 Pause-Bits mache), juhuu! Wie man aber
nun auf 31500 kommt, ist mir ein Rätsel.
Trotzdem, immerhin funktionierts.
Edit: Falls der Code für jemanden einen Wert haben sollte, stelle ich
ihn gerne zu Verfügung, auch wenn das höchstwahrscheinlich nicht der
Fall sein wird: