Forum: Mikrocontroller und Digitale Elektronik ATTiny85 - Software UART Probleme


von Max M. (maxmicr)


Angehängte Dateien:

Lesenswert?

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.

von Carl D. (jcw2)


Lesenswert?

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, 
...

von Jakob (Gast)


Lesenswert?

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.

von Karl M. (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

Hier, der Code sollte auf allen AVR's gehen. Iach habe ihn auf einem 
ATTiny13A getestet.

http://www.stefanfrings.de/avr_hello_world/HelloTiny.zip

von Alexander S. (alex998)


Lesenswert?

Warum benutzt du nicht die USI? Bietet sich beim Tiny85 doch an:
Atmel Appnote AVR307: Half Duplex UART Using the USI Module

von Max M. (maxmicr)


Lesenswert?

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.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

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.

von Jakob (Gast)


Lesenswert?

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...

von Frank K. (fchk)


Lesenswert?

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

von Max M. (maxmicr)


Lesenswert?

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?

: Bearbeitet durch User
von Frank K. (fchk)


Lesenswert?

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

von Jakob (Gast)


Lesenswert?

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.

von Carl D. (jcw2)


Lesenswert?

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.

von Karl M. (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

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!

von Karl M. (Gast)


Lesenswert?

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.

von Max M. (maxmicr)


Angehängte Dateien:

Lesenswert?

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?

von Jakob (Gast)


Lesenswert?

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.

von Max M. (maxmicr)


Lesenswert?

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?

: Bearbeitet durch User
von Carl D. (jcw2)


Lesenswert?

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.

von c-hater (Gast)


Lesenswert?

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.

von Eric B. (beric)


Lesenswert?

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)  ...

von Jim M. (turboj)


Lesenswert?

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.

von Carl D. (jcw2)


Lesenswert?

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 ... ;-)

von Carl D. (jcw2)


Lesenswert?

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.

von Jakob (Gast)


Lesenswert?

@ 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

von c-hater (Gast)


Lesenswert?

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?

von DocMartin (Gast)


Lesenswert?

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

von Jakob (Gast)


Lesenswert?

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.

von Max M. (maxmicr)


Lesenswert?

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

von Dieter F. (Gast)


Lesenswert?

Max M. schrieb:
> In Salae Logic gibt es kein UART zum auswählen im Analyzer-Tab.

Welche Version hast Du denn?

von Max M. (maxmicr)


Lesenswert?

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).

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

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.

von DocMartin (Gast)


Lesenswert?

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

von Dieter F. (Gast)


Angehängte Dateien:

Lesenswert?

Max M. schrieb:
> 1.2.10

Das verstehe ich jetzt nicht (Hardcopy im Anhang)

von Max M. (maxmicr)


Angehängte Dateien:

Lesenswert?

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) 
:(

von DocMartin (Gast)


Lesenswert?

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

von Max M. (maxmicr)


Angehängte Dateien:

Lesenswert?

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?

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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 ?

: Bearbeitet durch User
von Max M. (maxmicr)



Lesenswert?

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?

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

> 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.

von Max M. (maxmicr)


Lesenswert?

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?

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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...

: Bearbeitet durch User
von Max M. (maxmicr)


Lesenswert?

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.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Vielleicht kann der LA nur bestimmte gängige Baudraten automatisch 
erkennen.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von Max M. (maxmicr)


Angehängte Dateien:

Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Angehängte Dateien:

Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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 ?

: Bearbeitet durch User
von Max M. (maxmicr)


Lesenswert?

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:
1
#define F_CPU 1000000UL
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
6
volatile char str[] = {0x48,0x65,0x6C,0x6C,0x6F,0x0A}; //Hello\n
7
volatile uint8_t charNo = 0;
8
volatile int position = -1;
9
10
volatile uint8_t needPause = 0;
11
12
ISR(TIMER1_COMPA_vect){
13
  if(needPause == 1){
14
      needPause = 0;
15
  } else {
16
    if(position == -1){ //start of transmission
17
      PORTB &=~(1<<PINB3); //Start Bit LOW
18
      position++;
19
    } else {
20
      if(position == 8){ //end of transmission
21
        if(charNo == sizeof(str) - 1){
22
          charNo = 0;
23
          } else {
24
          charNo++;
25
        }
26
        position = -1;
27
        PORTB |= (1<<PINB3); //Stop Bit HIGH
28
        needPause = 1;
29
      } else{
30
        if((str[charNo] >> position) & 0x01){ //transmit bits
31
          PORTB |= (1<<PINB3);
32
        } else {
33
          PORTB &=~(1<<PINB3);
34
        }
35
        position++;
36
      }
37
    }
38
  }
39
}
40
41
void initTimer(){
42
  TCCR1 |= (1<<CTC1); //Enable CTC
43
  TCCR1 |= (0b0010<<CS10); //CK/2
44
  OCR1A = 104-1;
45
  TIMSK |= (1<<OCIE1A); //enable compare interrupt
46
  sei(); //Enable Interrupts
47
}
48
49
int main(void)
50
{
51
  DDRB |= (1<<PINB3); //PINB1 as output
52
  PORTB |= (1<<PINB3); //PINB3 HIGH
53
  initTimer();
54
  while(1){
55
56
  }
57
}

: Bearbeitet durch User
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.