mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik UART ATmega644


Autor: LDer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin!

Ich habe folgenden Code im 
http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART gefunden:
.def temp    = r16                              ; Register für kleinere Arbeiten
.def zeichen = r17                              ; in diesem Register wird das Zeichen an die
                                                ; Ausgabefunktion übergeben
 
.equ F_CPU = 4000000                            ; Systemtakt in Hz
.equ BAUD  = 9600                               ; Baudrate
 
; Berechnungen
.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     temp, HIGH(RAMEND)
    out     SPH, temp
    ldi     temp, LOW(RAMEND)
    out     SPL, temp
 
    ; Baudrate einstellen
 
    ldi     temp, HIGH(UBRR_VAL)
    out     UBRRH, temp
    ldi     temp, LOW(UBRR_VAL)
    out     UBRRL, temp
 
    ; Frame-Format: 8 Bit
 
    ldi     temp, (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0)
    out     UCSRC, temp
 
    sbi     UCSRB,TXEN                  ; TX aktivieren
    ;(einige Sende-Tests)

Fand ich interessant und kam auf die Idee, diesen Code für den Mega8 auf 
meinen Mega644 zuzuschneiden. Also Datenblatt her...

Das ist dabei rausgekommen:
.def temp    = r16                              ; Register für kleinere Arbeiten
.def zeichen = r17                              ; in diesem Register wird das Zeichen an die
                                                ; Ausgabefunktion übergeben
 
.equ F_CPU = 16000000                           ; Systemtakt in Hz
.equ BAUD  = 9600                               ; Baudrate
 
; Berechnungen
.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
 
    lds     temp, HIGH(RAMEND)
    sts     SPH, temp
    lds     temp, LOW(RAMEND)
    sts     SPL, temp
 
    ; Baudrate einstellen
 
    lds     temp, HIGH(UBRR_VAL)
    sts     UBRR0H, temp
    lds     temp, LOW(UBRR_VAL)
    sts     UBRR0L, temp
 
    ; Frame-Format: 8 Bit
 
    lds     temp, (1<<UCSZ01)|(1<<UCSZ00)
    sts     UCSR0C, temp
 
    lds    temp,UCSR0B
    sbr    temp,TXEN0
    sts     UCSR0B,temp                  ; TX aktivieren
    ;(einige Sende-Tests)

Nur leider sendet der µC nach dem Flashen... rein gar nichts!

Woran liegt das? Habe ich ein Bit falsch gesetzt oder Schwachsinn mit 
den Registern angestellt? Ich finde den Fehler jedenfalls nicht mehr 
allein :(

Hoffe, dass mal jemand reinschaut ;)

Gruß,
euer LDer

Autor: nmbx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ist das der komplette Code? Wenn ja: Da wird bisher noch nix gesendet. 
Schreib mal irgendwas in das UDR Register

Autor: LDer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ADD: Ich nehm auch gern C; es muss nicht zwingend Assembler sein ;)

Autor: LDer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@nmbx, nein, danach folgt noch der (Original-)code aus dem Tutorial, wie 
ich mit dem ";(einige Sende-Tests)" versucht habe, anzudeuten, das in 
beiden Codeblöcken am Ende steht.

Für Leute, die das Tut nun nicht auskramen wollen:
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

Gruß,
LDer

Autor: LDer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hrmpf...
sorry, fehlt immernoch was:
serout:  
  lds    temp,UCSR0A
    sbrs    temp,UDRE0                ; Warten bis UDR für das nächste
                                        ; Byte bereit ist
    rjmp    serout
    sts     UDR0, 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

wenn ich euch jetzt noch die Anfangszeile '.include "m644def.inc"' mit 
dazuschreibe, habt ihr die komplette Datei :-D

Gruß,
LDer

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Warum nimmst du nicht einfach die Initialisierung aus dem Datenblatt? 
Die passt.

MfG Spess

Autor: LDer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm, wo finde ich die?
Also das Datenblatt ist ja LANG und ich habe ehrlich gesagt keine große 
Lust, es komplett durchzulesen. Passt auch gerade nicht in mein 
Köpfchen...

Also welcher Punkt?

Gruß,
LDer

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Wahrscheinlich unter ADC, Timer oder so.

MfG spess

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
LDer schrieb:
> Also das Datenblatt ist ja LANG

Wie wärs mit dem Inhaltsverzeichnis?


> Also welcher Punkt?

Wie wärs mit: "16.6 USART Initialization"


Peter

Autor: LDer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:
>> Also welcher Punkt?
>
> Wie wärs mit: "16.6 USART Initialization"

Oh, danke. Also Blindheit meinserseits. Auch gut^^

Da steht folgendes:
USART_Init:
; Set baud rate
out UBRRHn, r17
out UBRRLn, r16
; Enable receiver and transmitter
ldi r16, (1<<RXENn)|(1<<TXENn)
out UCSRnB,r16
; Set frame format: 8data, 2stop bit
ldi r16, (1<<USBSn)|(3<<UCSZn0)
out UCSRnC,r16
ret

nur dumm, dass der out-Befehl nicht auf Register wie UBRRnH bzw konkret 
UBRR0H anwendbar ist. und es eben nicht UBRRHn wie im Datenblatt, 
sondern vielmehr UBRRnH ist. Kann man aber auch noch mit leben.
Zu allem Überfluss steht da doch nichts anderes, als das was ich gemacht 
habe. Oder doch?
Jedenfalls bringt auch die Änderung meines Codes auf Folgendes nichts:
 
    ; Frame-Format: 8 Bit
 
    lds    temp, (1<<USBS0)|(3<<UCSZ00)
    sts    UCSR0C, temp
 
    lds     temp,UCSR0B
    sbr     temp,TXEN0
    sbr    temp,RXEN0
    sts    UCSR0B,temp                  ; TX aktivieren
Wobei ich jetzt nur den relevanten Teil poste.

Gruß,
LDer

Autor: ersthelfer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>    lds     temp, HIGH(RAMEND)
>    sts     SPH, temp
>    lds     temp, LOW(RAMEND)
>    sts     SPL, temp

Was soll denn LDS hier??
Das ist wohl ein bisschen zu viel des Guten.

> Also das Datenblatt ist ja LANG und ich habe ehrlich gesagt keine große
> Lust, es komplett durchzulesen.

Eigentlich habe ich aber auch keine Lust, dir zu helfen. Warum sollte 
ich?

Autor: Sascha Weber (sascha_w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... und
sbr     temp,TXEN0
sbr    temp,RXEN0
setzt nicht etwa die Bits TXEN0 und RXEN0, da der Befehl sbr eine 
Bitmaske und keine Bitnummern haben möchte!
sbr   temp,(1<<TXEN0) | (1<<RXEN0)
sollte da schon eher angebracht sein!

Sascha

Autor: Jörn - M. M. (ldericher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha Weber schrieb:
> setzt nicht etwa die Bits TXEN0 und RXEN0, da der Befehl sbr eine
> Bitmaske und keine Bitnummern haben möchte!
> sbr   temp,(1<<TXEN0) | (1<<RXEN0)
> sollte da schon eher angebracht sein!

cool, danke, ich habe eine Ausgabe!
Also falsch gesetzte Bits. Jetzt habe ich allerdings das Problem, dass 
ich nur Müll empfange, statt "T" bzw. 01010100 (hab es gekürzt, sodass 
nur das T übertragen wird) kommt immer "ô" bzw. 11110100 an... :(
Anscheinend werden die ersten vier Bits (von MSB an gesehen) als 1, 
dafür die letzten Bits korrekt übertragen.

ersthelfer schrieb:
> Was soll denn LDS hier??
> Das ist wohl ein bisschen zu viel des Guten.

Dann sag mir doch, wie ich es besser machen kann :)

ersthelfer schrieb:
> Eigentlich habe ich aber auch keine Lust, dir zu helfen. Warum sollte
> ich?

1. hast du es doch bereits getan, indem du mich auf lds hingewiesen 
hast.
2. Warum versucht du es dann? Niemand zwingt dich.

Gruß,
LDer

ADD: mein derzeitiger Code:
    ; Stackpointer initialisieren
 
    lds     temp, HIGH(RAMEND)
    sts     SPH, temp
    lds     temp, LOW(RAMEND)
    sts     SPL, temp
 
    ; Baudrate einstellen
 
    lds     temp, HIGH(UBRR_VAL)
    sts     UBRR0H, temp
    lds     temp, LOW(UBRR_VAL)
    sts     UBRR0L, temp
 
    ; Frame-Format: 8 Bit

    lds     temp, (1<<UCSZ00)
    sts     UCSR0C, temp
 
    lds     temp,UCSR0B
    sbr     temp,(1<<TXEN0)
    sts     UCSR0B,temp                  ; TX aktivieren
 
loop:
    ldi     zeichen, 0b01010100
    rcall   serout                      ; Unterprogramm aufrufen
    rcall   sync                        
    rjmp    loop

Autor: Jörn - M. M. (ldericher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gut, durch Nachdenken bin ich selbst drauf gekommen. Musste ja doch an 
dem LDS liegen ;) Danke @ersthelfer!

Fürs Protokoll:
.include "m644def.inc"
 
.def temp    = r16                              ; Register für kleinere Arbeiten
.def zeichen = r17                              ; in diesem Register wird das Zeichen an die
                                                ; Ausgabefunktion übergeben
 
.equ F_CPU = 16000000                           ; Systemtakt in Hz
.equ BAUD  = 38400                              ; Baudrate
 
; Berechnungen
.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     temp, HIGH(RAMEND)
    sts     SPH, temp
    ldi     temp, LOW(RAMEND)
    sts     SPL, temp
 
    ; Baudrate einstellen
 
    ldi     temp, HIGH(UBRR_VAL)
    sts     UBRR0H, temp
    ldi     temp, LOW(UBRR_VAL)
    sts     UBRR0L, temp
 
    ; Frame-Format: 8 Bit

    ldi     temp, (3<<UCSZ00)
    sts     UCSR0C, temp
 
    lds     temp,UCSR0B
    sbr     temp,(1<<TXEN0)
    sts     UCSR0B,temp                  ; TX aktivieren
 
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
    rcall   sync                        
    rjmp    loop
 
serout:  
  lds    temp,UCSR0A
    sbrs    temp,UDRE0                ; Warten bis UDR für das nächste
                                        ; Byte bereit ist
    rjmp    serout
    sts     UDR0, 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
Funktioniert blendend!

Grüße,
euer LDer

Autor: ersthelfer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Funktioniert blendend!

... und überhaupt, seit wann kann man SPL und SPH nicht mehr über out 
erreichen?

rumpöbeln hilft hier eben nicht weiter, sondern nachdenken wie du 
gemerkt hast

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.