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 #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 #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
#2533828
Lesenswert?

spess53 schrieb:
>> TX Aktivieren
>
>>    lds temp, UCSR0C,
>>    sbrs temp, TXEN0
>
> Da wird nix aktiviert. TXEN0 befindet sich im Register UCSR0B.

Und selbst wenn es das richtige Register wäre ...

sbrs = Skip if Bit in Register is Set
und nicht etwa "Set Bit in Register"
(außerdem würde in dem Fall dann auch immer noch das Zurückschreiben 
fehlen)
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?

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