mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Attiny2313 USART Baudrate stimmt nicht


Autor: StePo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Tag allerseits

Ich möchte mich ein wenig in USART einarbeiten.
Ich habe:

Attiny2313
AVR Studio 4
STK500
HyperTerminal

Ich möchte vom Attiny aus Zeichen an den pc senden. Das ganze 
funktioniert aber nicht. Der HyperTerminal verhält sich recht seltsam, 
manchmal bekomme ich einfach nur datenschrott ( willkührliche 
zeichenketten ), manchmal macht mein Hyperterminal lauter leerzeichen 
und manchmal blinkt der curser vom hyperterminal einfach nur hektisch, 
wenn ich den attiny anschalte.

Vorab mal der quellcode:
.include "C:\Programme\Atmel\AVR Tools\AvrAssembler\Appnotes\2313def_manipuliert.inc"

;Register deffintion

.def zeichen = R17

;Baudrate berechnen
.equ F_CPU = 3686400                           ; Systemtakt in Hz
.equ BAUD  = 2400                              ; Baudrate
 
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille
 
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
.endif


;Stackpointer initialisieren

ldi     R16, LOW(RAMEND)
out     SPL, R16

;Prescaler auf Faktor 1 setzen
sbr R16,CLKPCE
out CLKPR,R16

ldi R16,0
out CLKPR,R16

; Baudrate setzen

ldi R16,HIGH(UBRR_VAL)
out UBRRH,R16
ldi R16,LOW(UBRR_VAL)
out UBRRL,R16

;UART anschalten

ldi R16,0
sbr R16,UCSZ1
SBR R16,UCSZ0
;sbr R16,UMSEL

out UCSRC,R16

sbi UCSRB,TXEN

loop:
    ldi     zeichen, 'T'
    rcall   serout                      ; Unterprogramm aufrufen
    ldi     zeichen, 'e'
    rcall   serout                      ; Unterprogramm aufrufen
    ldi     zeichen, 's'
    rcall   serout                      ; ...
    ldi     zeichen, 't'
    rcall   serout
    ldi     zeichen, '!'
    rcall   serout
    ldi     zeichen, 10
    rcall   serout
    ldi     zeichen, 13
    rcall   serout
    rcall   sync                        
    rjmp    loop
 
serout:
    sbis    UCSRA,UDRE                  ; Warten bis UDR für das nächste
                                        ; Byte bereit ist
    rjmp    serout
    out     UDR, zeichen
    ret                                 ; zurück zum Hauptprogramm
 
; kleine Pause zum Synchronisieren des Empfängers, falls zwischenzeitlich
; das Kabel getrennt wurde
                                    
sync:
    ldi     r16,0
sync_1:
    ldi     r17,0
sync_loop:
    dec     r17
    brne    sync_loop
    dec     r16
    brne    sync_1  
    ret


Da sich der hyperterminal so seltsam verhält, nehme ich an das der 
Fehler irgendwie bei der Baudrate liegt. Es kommt ja auch ein signal aus 
dem controler heraus. Ich habe im simulator überprüft ob der 
Präprozessor den richtigen Wert für das UBRR Register errechnet.

Bei 2400 BAUD = 0x5F = 95
ich habe "zu fuss" den wert 95,5 errechnet

Bei 9600 Baud =  0x17 = 23
zu fuss: 24,5

ich hab das UBRR register auch schon mit allen werten (auf und 
abgerundet) gefüttert, half aber alles nichts.

Ich habe volgende Fehlerquellen schon ausgeschlossen:

-Controler wird vom auf dem STK500 integriertem oszilator mit 3686400 Hz 
gespeist.
-Fuses stehen auf External Clock mit 65ms Start-up time
-CKDIV8 Fuse ist nicht gesetzt
-interner Vorteiler steht auf faktor 1 (siehe quellcode)
-Das programm scheint im Simulator zu laufen (daten werden ins UDR 
Register transportiert)
-Signal kommt aus dem Attiny heraus ( mit osziloskop geprüft )
-Hyperterminal einstellungen überprüft ( 2400 bzw 9600 BAUD 8bit  1 
stoppbit )

so langsam gehen mit die Ideen und die schokolade aus. Währe über etwas 
hilfe sehr erfreut.

mfg Steffen

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
;Prescaler auf Faktor 1 setzen
sbr R16,CLKPCE
out CLKPR,R16
In R16 steht nicht das, was richtig wäre, schließlich war R16 vor dieser 
Operation nicht leer.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dazu kommt, dass
  sbi port,1
Bit 1 setzt, aber
  sbr reg,1
Bit 0 setzt.

Autor: Norbert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Zitat:
>> In R16 steht nicht das, was richtig wäre,
>> schließlich war R16 vor dieser Operation nicht leer.

 ;Prescaler auf Faktor 1 setzen
 sbr R16,CLKPCE
 out CLKPR,R16

 ldi R16,0
 out CLKPR,R16

Die ersten beiden Befehle sind redundant, da sie von den nächsten zwei 
Befehlen komplett ersetzt werden.

Versuch mal kontinuierlich 0xff zu senden, das ergibt ein Startbit (Low) 
und dann neun High Bits.

Man kann dann prima mit dem Oszilloskop die Periode messen und mit dem 
avisierten Ziel vergleichen.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Norbert schrieb:
>>> Zitat:
>>> In R16 steht nicht das, was richtig wäre,
>>> schließlich war R16 vor dieser Operation nicht leer.
>
>  ;Prescaler auf Faktor 1 setzen
>  sbr R16,CLKPCE
>  out CLKPR,R16
>
>  ldi R16,0
>  out CLKPR,R16
>
> Die ersten beiden Befehle sind redundant, da sie von den nächsten zwei
> Befehlen komplett ersetzt werden.

Nein. CLKPR benötigt eine spezielle Zugriffssequenz. Und weil beim 
ersten Zugriff nicht das richtige geschrieben wird, wird CLKPR hier gar 
nicht verändert.

Autor: Norbert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> Nein. CLKPR benötigt eine spezielle Zugriffssequenz. Und weil beim
> ersten Zugriff nicht das richtige geschrieben wird, wird CLKPR hier gar
> nicht verändert.

Da CKDIV8 nicht gesetzt ist, gilt laut Handbuch:

>If CKDIV8 is unprogrammed, the CLKPS bits will be reset to “0000”.

damit ist der Divisor der Taktfrequenz 1.

Da der Teiler sowieso auf 1 gesetzt werden soll gilt:

- da RAM Größe = 128Byte müsste RAMEND <= 0x7f sein.

>> ldi     R16, LOW(RAMEND)

  Damit ist das MSB in R16 nicht gesetzt und es wird beim späteren 
Schreiben auch nicht das CLKPCE Bit gesetzt.

Also haben die beiden out Befehle keine Wirkung.

Autor: Norbert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stop, alles zurück.

>> ;Prescaler auf Faktor 1 setzen
>> sbr R16,CLKPCE
>> out CLKPR,R16

Der hier schlägt fehl, weil noch andere Bits ausser CLKPCE gesetzt sind.
Überbleibsel von RAMEND in R16.
(Anmerkung an mich selbst: RTFM) ;-)

Somit werden die hier nicht funktionieren:
>> ldi R16,0
>> out CLKPR,R16

Asche auf mein Haupt!


Aber im Ergebnis bleibt der ClockPrescaler auf 1 stehen und sollte daher 
mit dem ursprünglichen Problem nichts zu tun haben.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Norbert schrieb:

> Da CKDIV8 nicht gesetzt ist,

Sorry, aber auf solche Aussagen vertraue ich nicht blind. Schon gar 
nicht nach Betrachten des Codes. Würde er den Code diesbezüglich 
korrigieren, wäre es schlicht egal, was CKDIV8 für einen Status hat.

>>> ldi     R16, LOW(RAMEND)
>
>   Damit ist das MSB in R16 nicht gesetzt und es wird beim späteren
> Schreiben auch nicht das CLKPCE Bit gesetzt.

Das MSB alleine ist es nicht. Auch wenn er das MSB später setzen würde, 
würde es nicht gehen, weil der Rest dann nicht Null ist.
EDIT: wie du inzwischen ja auch selbst festgestellt hast. ;-)

> Also haben die beiden out Befehle keine Wirkung.

Sag ich ja. ;-)

Autor: Norbert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, helfen wir noch mal ein bischen...

Versuch mal folgendes:
  ;UART anschalten
  ldi R16,(1<<UCSZ1)|(1<<UCSZ0)
  out UCSRC,R16
  ldi R16,(1<<TXEN)|(1<<RXEN)
  out UCSRB,R16


(aber erst das Prescaler Zeuch aufräumen ;-)

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Controler wird vom auf dem STK500 integriertem oszilator mit 3686400 Hz
>gespeist.

Vergiss es. Nimm einen Quarz.

MfG Spess

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spess53 schrieb:

> Vergiss es. Nimm einen Quarz.

Wo ist da das Problem? der STK500 Taktgenerator ist ebenfalls 
quarzbasiert.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Wo ist da das Problem? der STK500 Taktgenerator ist ebenfalls
>quarzbasiert.

Ich habe das vor längerer Zeit mal nachgemessen und merkliche 
Unterschiede zwischen angezeigter und 'wahrer' Frequenz festgestellt.

MfG Spess

Autor: StePo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal danke für die vielen tipps.
Also das mit dem
sbr R16,CLKPCE
out CLKPR,R16

ldi R16,0
out CLKPR,R16

war natürlich käse, hätte mir schon in der simulation auffallen sollen. 
Mann muss übrigens erst das CLKPCE bit setzen damit man man den wert in 
CLKPR ändern kann. Das fusebit sollte den wert beim fusen zwar auch auf 
0000 bzw 0011 ändern, allerdings kann der Wert immer noch über CLKPR 
geändert werden ohne das das einfluss aufs fusebit hat. Deshalb hab ich 
vorsichtshalber manuell auf 0000 gesetzt.
ldi R16,0
sbr R16,UCSZ1
SBR R16,UCSZ0

hat auch nicht funktioniert. Das hab ich jetzt wie von Norbert 
vorgeschlagen abgeändert.

Außerdem ist mir aufgefallen das hyperterminal noch auf "Flussteuerung: 
Hardware" stand. Ich hab jetzt auf keine umgestellt. Funktionieren tuts 
aber trozdem nicht.
Ich muss mal schauen ob hier irgendwo noch ein quarz durch die gegend 
diffundiert. Wenn ich mein (tast)kopf wiedergefunden hab werd ich das 
signal mal oszillographieren.

Was mich aber wundert ist: warum
ldi R16,0
sbr R16,UCSZ1
SBR R16,UCSZ0
nicht funktioniert sbr ist doch der befehl um einzelne bits in einem 
Register zu setzen. Also syntaxmäßig: R16 Register,Bitnummer aber 
scheinbar übernimmt der den ganzen wert der hinter dem Komma steht ins 
Register, anstadt das entsprechende bit zu setzen.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
StePo schrieb:

> Was mich aber wundert ist: warum
>
> ldi R16,0
> sbr R16,UCSZ1
> SBR R16,UCSZ0
> 
> nicht funktioniert sbr ist doch der befehl um einzelne bits in einem
> Register zu setzen. Also syntaxmäßig: R16 Register,Bitnummer aber
> scheinbar übernimmt der den ganzen wert der hinter dem Komma steht ins
> Register, anstadt das entsprechende bit zu setzen.

Nein, es ist eben nicht der Befehl um ein einzelnes Bit zu setzen, 
sondern um mehrere Bits zu setzten. Der zweite Parameter ist daher 
auch keine Bitnummer, sondern eine Maske.
sbr Rxx,0x81 : Bits 0 und 7 setzen
sbr Rxx,(1<<UCSZ0) : Bit UCSZ0 setzen
sbr Rxx,(1<<UCSZ0)|(1<<UCSZ1) : Bits UCSZ0 und UCSZ1 setzen

So nebenbei: "sbr" ist nur ein Alias für "ori".

PS: Außerdem kannst du dir dieses Schreiben nach UCSRC auch gleich ganz 
sparen. Du schreibst da nur rein, was da sowieso schon drin steht.

Autor: StePo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahhh, danke das erklährt natürlich einiges. Vielleicht sollt ich mir 
doch nochmal das instruction set zu gemüte führen.

Wie auch immer, die programmierfehler sind behoben und ich habe 
inzwischen meinen Tastkopf wiedergefunden :D und folgende seltsame 
enteckung gemacht:
Auf den hinweis von norbert hin habe lasse ich den attiny jetzt nur 0xFF 
senden, sodas ich nur das Start bit habe. Das Start bit ist aber nur 
etwa 20ms lang, was einer Frequenz, bzw bitrate von 50Hz entspricht. Wie 
kann das sein?
Der Attiny bekommt am XTAL1 eingang seine 3,68 MHz, wie genau die sind 
kann ich nicht sagen, mein oszi ist schon etwas älter ;)

Autor: StePo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, ich habe den Fehler gefunden xD Meine include datei war 
unvollständig und ich hab sie manuel vervollständigt. Dabei hab ich das 
UBRRH und UBRRL Register vertauscht x/ Trozdem danke für die viele 
Hilfe.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.