Forum: Mikrocontroller und Digitale Elektronik UART - Receive-Transmit -Problem


von Parvis S. (parvis)


Lesenswert?

Hallo zusammen,

ich habe folgendes Problem:

Ich sende Zeichen vom Computer zum ATMEGA8 und der uC sendet diese 
gleich zurueck (via Interrupt). Das klappt soweit ganz gut, ausser das 
der uC manchmal die Zeichen nicht sofort wieder zuruecksendet, sondern 
ich erst wieder Zeichen senden muss, welche er mir dann mit den 
vorherigen Zeichen zurueckgibt.
Meine Vermutung ist, dass die Zeichen manchmal im Transmit Shift 
Register haengen bleiben (wie gross ist das eigentlich?).
Wenn ich nun nach dem Einlesen ins UDR einige Zeit warte (=mehr als 100 
Zyklen ... genau weiss ich das Momentan nict), dann tritt das Problem 
nicht auf. Ich verwende einen Baudratenquarz mit 7372800Hz und das 
STK500-Board. Programmierung in ASM.

Kann mir da jemand vielleicht weiterhelfen?

Der Code ist in gekuerzter Fassung folgender (volle Version im Anhang):
1
.include "m8def.inc"
2
.def temp1     = r16         ; allgemeines temp Register
3
.def temp2     = r17         ;
4
.def temp3     = r18         ;
5
.def temp4     = r19         ;
6
.def temp5     = r20 
7
8
.equ F_CPU = 7372800                          ; Systemtakt in Hz
9
.equ BAUD  = 115200                            ; Baudrate
10
.equ SENSORS = 6
11
 
12
; Berechnungen
13
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
14
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
15
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille
16
 
17
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
18
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
19
.endif
20
21
.org 0x000
22
  rjmp init
23
 
24
.org URXCaddr
25
    rjmp int_rxc
26
27
;---------------------------------------------------------------------------------
28
; Start des Programms
29
30
init:
31
   ; Stackpointer initialisieren   
32
33
      ldi temp1, LOW(RAMEND)      ; LOW-Byte der obersten RAM-Adresse
34
      out SPL, temp1
35
      ldi temp1, HIGH(RAMEND)     ; HIGH-Byte der obersten RAM-Adresse
36
      out SPH, temp1
37
;----------------------------------------------------------------------------------
38
    ; Baudrate einstellen 
39
    ldi     temp1, HIGH(UBRR_VAL)
40
    out     UBRRH, temp1
41
    ldi     temp1, LOW(UBRR_VAL)
42
    out     UBRRL, temp1 
43
    ; Frame-Format: 8 Bit 
44
    ldi     temp1, (1<<URSEL)|(3<<UCSZ0)
45
    out     UCSRC, temp1 
46
    sbi     UCSRB,TXEN                  ; TX aktivieren
47
    sbi     UCSRB, RXEN                 ; RX (Empfang) aktivieren
48
    sbi     UCSRB, RXCIE                ; Interrupt bei Empfang 
49
    sei                                 ; Interrupts global aktivieren
50
;----------------------------------------------------------------------------------
51
52
main:
53
rjmp main;
54
55
;--- Receive Data -----------------------------------------------------------------
56
int_rxc:
57
    push    temp1                       ; temp1 auf dem Stack sichern
58
    in      temp1, sreg                 ; SREG sichern
59
    push    temp1
60
61
    in      temp1, UDR                  ; UART Daten lesen
62
    rcall serout_byte;
63
  
64
    pop     temp1
65
    out     sreg, temp1                 ; SREG wiederherstellen
66
    pop     temp1                       ; temp1 wiederherstellen
67
reti
68
69
;----- Fuer RS232 -------------------------------------------------------------------------
70
71
serout_byte:
72
  push temp3;
73
  in temp3, SREG
74
  push temp3
75
  serout_byte_wait:
76
      sbis    UCSRA,UDRE ; Warten bis UDR bereit ist
77
  rjmp serout_byte_wait;
78
  out UDR, temp1;
79
80
  pop temp3
81
  out SREG, temp3
82
  pop temp3
83
ret

Ich danke schonmal im voraus fuer jede Hilfe und Anregung.

Gruss,

Parvis

von spess53 (Gast)


Lesenswert?

Hi

Das Datenregister UDR ist gepuffert. D.h. 'sbis    UCSRA,UDRE' testet ob 
der Puffer frei ist, nicht ob das Byte gesendet wurde. Wenn du sicher 
sein willt, das das Byte gesendet wurde musst du 'TXC' abfragen ->
'sbis    UCSRA,TXC'.

MfG Spess

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Wenn UDRE gesetzt ist, kann man auch in das Transmit-Register schreiben. 
Der Schreibvorgang auf UDR triggert in jedem Fall die Ausgabe. 
Schlechtestenfalls kommen halt 2 Bytes direkt nacheinander. Dabei kann 
es aber nicht zu Aussetzern kommen. Ich vermute das Problem eher auf 
PC-Seite und dessen Pufferbehandlung. Wenn Du kannst, prüfen den TXD-Pin 
mal mit einem Oszilloskop. Bin fast 100%-ig sicher, daß der Controller 
immer sendet.

von Parvis S. (parvis)


Lesenswert?

spess53 wrote:
> Hi
>
> Das Datenregister UDR ist gepuffert. D.h. 'sbis    UCSRA,UDRE' testet ob
> der Puffer frei ist, nicht ob das Byte gesendet wurde. Wenn du sicher
> sein willt, das das Byte gesendet wurde musst du 'TXC' abfragen ->
> 'sbis    UCSRA,TXC'.

Ich habe das mal ausprobiert und direkt nach dem schreiben in UDR 'sbis 
UCSRA,TXC' als Schleife eingesetzt. Gleiches Resultat (wenn ich das 
testweise davor mache, dann bleibt er in eine Endlosschleife haengen)! 
Oder wo wuerde man die Abfrage sonst hinmachen?

Gruss,

Parvis

von Parvis S. (parvis)


Lesenswert?

> Wenn UDRE gesetzt ist, kann man auch in das Transmit-Register schreiben.
> Der Schreibvorgang auf UDR triggert in jedem Fall die Ausgabe.
> Schlechtestenfalls kommen halt 2 Bytes direkt nacheinander. Dabei kann
> es aber nicht zu Aussetzern kommen. Ich vermute das Problem eher auf
> PC-Seite und dessen Pufferbehandlung. Wenn Du kannst, prüfen den TXD-Pin
> mal mit einem Oszilloskop. Bin fast 100%-ig sicher, daß der Controller
> immer sendet.
Meinst Du, dass das im Empfangs-Puffer vom Computer ist oder der 
Computer es noch nicht angenommen und es deshalb beim uC haengen 
bleibt?? Dann duerfte aber eigentlich der TXC im UCSRA nicht geloescht 
werden, oder? Leider habe ich gerade kein Oszi zur Hand. Gebe es denn 
noch eine andere Moeglichkeit das zu testen??? Welche Variablen koennte 
ich denn noch testen? Eins ist sicher, der uC empfaengt alle Daten (mit 
via LCD-Display nachgeprueft) und bleibt auch soweit in keiner Schleife 
haengen.

Gruss,

PArvis

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.