Probleme mit Uart (Atmega88)

Gast #2530854
Lesenswert?

Hallo!

Hab mir soeben ein Programm zum Testen für den Uart geschrieben. 
Allerdings will der µC kein Zeichen ausgeben. Ich befürchte schon das 
ich irgendetwas falsch gemacht oder vergessen habe.

Kann mir da jemand helfen?

(Programm im Anhang)
Angehängte Dateien:
Gast #2530883
Lesenswert?

>.def temp    = r16            ; Register für kleinere Arbeiten
>.def zeichen = r17            ; in diesem Register wird das Zeichen an die

>    ldi r16, 'A'

>sts UBRR0H, r17
> sts UBRR0L, r16

Was denn nun? temp/zeichen oder r16/r17?

Entscheide dich für eine Variante. So wirst du früher oder später, 
eher früher, Probleme bekommen.

MfG Spess
Gast #2531008
Lesenswert?

Hi
Ich hab dir mal die Initialisierung angehängt, die ich für meinen 
Atmega8 immer nehme. Wichtig ist, das du auch den 16 MHz Takt hast, also 
einen Quarz. Ich kenn den Atmega48 nicht, aber er soll ja zum Atmega8 
kompatibel sein. Die folgenden Zeilen hast du vermutlich wie ich auch 
aus dem Tutorial entnommen.
1
;***********************************************************************
2
;* Die folgenden Zeilen definieren Constanten. Diese Werte werden  *
3
;* nur einmal vom  Compiler zugewiesen und dann nicht mehr verändert.  *
4
;***********************************************************************
5
.EQU   F_CPU  = 1600000    ; Systemtakt in Hz
6
.EQU   BAUD  = 9600      ; Baudrate ; Berechnungen
7
.EQU   UBRR_VAL  = ((F_CPU+BAUD*8)/(BAUD*16)-1)    ; clever runden
8
.EQU   BAUD_REAL= (F_CPU/(16*(UBRR_VAL+1)))   ; Reale Baudrate
9
.EQU   BAUD_ERROR= ((BAUD_REAL*1000)/BAUD-1000)    ; Fehler in Promille 
10

11
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))    ; max. +/-10 Promille Fehler  
12
.error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
13
.endif
Du darfst hier nicht davon ausgehen, das du mit
.EQU   F_CPU  = 1600000
den Systemtakt setzt, sondern den mußt du über die Fuses setzen. Aber 
den externen Takt nicht vergessen, sonst ist es Essig mit weiteren 
Zugriffen auf den µC.
Die Initialisierung erfolgt dann bei mir wie folgt:
1
;---------------- Serielle Schnittstelle parametrieren ------------------
2
;***********************************************************************
3
;* Die Parametrierung ist mit dem Koppelpartner abzustimmen.    *
4
;***********************************************************************
5
INIT_UART:  
6
  LDI  Reg_A, HIGH(UBRR_VAL)    ; Baudrate einstellen
7
  OUT  UBRRH, Reg_A
8
  LDI  Reg_A, LOW(UBRR_VAL)
9
  OUT  UBRRL, Reg_A
10
  ; Frame-Format: 8 Bit
11
   LDI  Reg_A, (1<<URSEL)|(3<<UCSZ0)
12
  OUT  UCSRC, Reg_A
13
   SBI  UCSRB, TXEN    ; TX aktivieren
14
  SBI  UCSRB, RXCIE                ; Interrupt bei Empfang    
15
  SBI  UCSRB, RXEN                 ; RX (Empfang) aktivieren
16
RET
Den Interrupt für den Empfang brauchst du ja noch nicht freigeben, wenn 
du es aber tust, dann muß auch eine ISR existieren, oder zumindest ein 
RETI hinter
1
.org URXCaddr  JMP int_rxc  ; USART Receive Complete Interrupt Vector Address
Die Senderoutine ist jedenfalls einfach:
1
;------------- serielle Ausgabe  -----------------------
2

3
SerOut:  SBIS  UCSRA,UDRE  ; Warten Freigabe UDR 
4
  RJMP  SerOut
5
      OUT  UDR, Send_Byte    ; Register Send_byte enthält die Daten 
6
RET
Deine Sendesequenz ist
1
     ldi r16, 'A'
2
     sts UDR0, r16
Wie du siehst, wartest du nicht ab, bis der Wert vom UART auch als 
"versendet" gemeldet wird. des weiteren ist UDR im EA-Bereich und muß 
mit "Out" angesprochen werden.
Zumindest ist das beim Atmega8 so.
Gruß oldmax
Gast #2533705
Lesenswert?

OK danke soweit...

Ich hab mal das ganze überarbeitet, assemblieren lässt es sich zwar aber 
ich bekomm noch immer keine Zeichen??

Mit dem Beispielprogramm vom Atmega8 (AVR_Tutorial) Funktioniert es.

Aber mit meinem Atmega88 bekomm ich es einfach nicht hin.
Außerdem versteh ich nicht ganz warum es UCSR0A, UCSR0B und UCSR0C gibt, 
kann ich mir da irgendeinen aussuchen?

(Code im Anhang)
Angehängte Dateien:
Gast #2533810
Lesenswert?

Hi
Wie wär es mal mit dem Datenblatt ? Kann ich zwar auch auf machen und 
dir dann alles vorlesen, doch ich glaub, du hast dann bestimmt eine 
weitere Frage und ich muß dann weiterlesen....
Gruß oldmax
Gast #2533812
Lesenswert?

Hi

> TX Aktivieren

>    lds temp, UCSR0C,
>    sbrs temp, TXEN0

Da wird nix aktiviert. TXEN0 befindet sich im Register UCSR0B.

>serout:
>    lds temp, UCSR0C
>    sbrs temp, UDRE0

Ähnlichr Fall: UDRE0 ist im Register UCSR0A.

>Außerdem versteh ich nicht ganz warum es UCSR0A, UCSR0B und UCSR0C gibt,
>kann ich mir da irgendeinen aussuchen?

Nein. Die Bits in den Registern UCSR0A, UCSR0B und UCSR0C haben 
unterschiedliche Funktionen.

Tu dir einen Gefallen und lies das Datenblatt. Dort sind sogar Beispiele 
in Assembler drin.

MfG Spess
Gast #2533840
Lesenswert?

Hi

>Und selbst wenn es die richtigen Register wären ...

Ich weiss. Aber der TO hat primär erst einmal ein absolutes 
Verständnisproblem mit der Funktion der einzelnen Register und der darin 
enthaltenen Bits.

MfG Spess
Gast #2533846
Lesenswert?

Als erstes habe ich versucht das Programm von Atmega8 zu ändern.. ohne 
Erfolg
Dann habe ich einige Codebeispiele aus google zusammengestöbseln.. ohne 
Erfolg

Jetzt habe ich mir das Datenblatt angesehen (etwas spät aber doch) und 
auch die Beispielcodes angepasst, da ich ja IN/OUT nicht verwenden kann. 
Warum auch immer das im Datenblatt so geschrieben ist.

USART_Transmit:
    ldi temp, UCSR0A
    sbis temp, UDRE0
    rjmp USART_Transmit
    sts UDR0, temp

Bei sbis bekomm ich einen I/O Fehler, warum?
Ich kann mit sbis im register UCSR0A nicht direkt kontrollieren ob das 
bit 5 (udre0) gesetzt ist. Deshalb auch der umweg über ein Register.

Keine Ahnung aber irgendwie steh ich total auf der Leitung, kann mir 
jemand helfen?

Wenn ich es mit sbrs versuche funktioniert das assemblieren, aber am pc 
tut sich nix?
Angehängte Dateien:
Gast #2533865
Lesenswert?

spess53 schrieb:
> Ich weiss. Aber der TO hat primär erst einmal ein absolutes
> Verständnisproblem mit der Funktion der einzelnen Register und der darin
> enthaltenen Bits.

Stimmt allerdings, da ich beim Atmega8 einfach die im AVR-Tutorial 
verwendeten Codeabschnitte mit den Registern abgeschrieben habe.

Da muss ich mir wohl das Datenblatt des Atmega88 genau durchlesen. Aber 
dennoch verstehe ich nicht warum die Codebeispiele mit IN und OUT 
angegeben sind?
Gast #2533898
Lesenswert?

Hi

>dennoch verstehe ich nicht warum die Codebeispiele mit IN und OUT
>angegeben sind?

Du hast recht, die sind falsch. Ich nehme an, die sind etwas gedankenlos 
von älteren Datenblättern übernommen worden.

Bei älteren oder kleineren AVRs liegen die (meisten) IO-Register in dem 
Bereich, den Befehle in, out und eingeschränkt cbi, sbi, sbis und sbic 
adressieren können.

Im Datenblatt deines AVRs gibt es ein 'Register Summary'. Dort sind die 
Adressen der IO-Register enthalten. Bei Fehlermeldungen kannst du da 
nachsehen ob der Befehl zu dem benutzten Register passt.

MfG Spess
Gast #2533917
Lesenswert?

spess53 schrieb:
> Im Datenblatt deines AVRs gibt es ein 'Register Summary'. Dort sind die
> Adressen der IO-Register enthalten. Bei Fehlermeldungen kannst du da
> nachsehen ob der Befehl zu dem benutzten Register passt.

Danke, das wusste ich auch nicht, aber sehr hilfreich!

Hast du meinen letzten Code angeguckt und irgendwas auffälliges gefunden 
warum mein Code noch immer nicht funktioniert?
Gast #2533945
Lesenswert?

Hi

>Hast du meinen letzten Code angeguckt

Bis eben nicht

>und irgendwas auffälliges gefunden
>warum mein Code noch immer nicht funktioniert?

Was mir sofort auffällt, da (<<<<<<<) fehlt  ein 'ret'

>    rjmp USART_Transmit
>    sts UDR0, temp
     ret                 <<<<<<<<<

>ende:
>    rjmp ende

MfG Spess
Gast #2534141
Lesenswert?

Hi

>USART_Transmit:
    ldi temp2, UCSR0A    !!!!!!!!!!!!!!!!!
    sbrs temp2, UDRE0
    rjmp USART_Transmit
    sts UDR0, temp
    ret

Du willst den Inhalt von UCSR0A, nicht die Adresse.

->     lds temp2, UCSR0A
       ^^^

MfG spess
Gast #2534240
Lesenswert?

Sehr Gut!
Jetzt bekomm ich Datenmüll =)

Aber es ist schon ein Anfang...

Ich habe lt. Engbedded AVR Fuse Calculator folgende Fuse Einstellungen 
vorgenommen: -U lfuse:w:0x7f:m -U hfuse:w:0xdf:m -U efuse:w:0x01:m 
(letzte Quarzauswahl in der Liste)

Die Baudrate beträgt am µC und PC 9600
Der Quarz und Takt 8Mhz

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren