Forum: Mikrocontroller und Digitale Elektronik serielle Ausgaben auf AT89S52 Baud-Raten-Generator startet nicht


von Anon A. (anon1234)


Angehängte Dateien:

Lesenswert?

Hallo allesamt,
ich versuche gerade mit meinem AT89S52 ausgaben auf der seriellen 
schnittstelle zu machen.
Ich benutzte den folgenden code und teste ihn im simulator von 
keilµvision.
Den Code habe ich eigentlich von einem c515c-l.
Wenn ich bei Keil als µC den c515c-l einstelle funktioniert auch alles 
tadellos. Bloß mit meinem AT89S52 nicht.
Es scheint mir so, als wenn der Baud-Raten-Generator (bei serial mode 1 
sollte dies der Timer1 sein) nicht gestartet wurde.
Im Datenblatt hab ich jetzt schon mehrfach nachgelesen, aber ich finde 
nicht, wie der Timer gestartet wird, bzw. wie man überhaupt ersteinmal 
einstellt, dass der Timer als Baud-Raten-Generator genutzt wird.
1
$include(reg515c.inc)
2
3
main:
4
  call serinit
5
  mov a,#'H'
6
  call serout 
7
  mov a,#'e'
8
  call serout 
9
  mov a,#'l'
10
  call serout 
11
  mov a,#'l'
12
  call serout 
13
  mov a,#'o'
14
  call serout 
15
  mov a,#' '
16
  call serout 
17
  mov a,#'W'
18
  call serout 
19
  mov a,#'o'
20
  call serout 
21
  mov a,#'r'
22
  call serout 
23
  mov a,#'l'
24
  call serout 
25
  mov a,#'d'
26
  call serout 
27
  mov a,#'!'
28
  call serout 
29
  jnb ti,$
30
  jmp main
31
32
33
;initializes serial interface with a
34
; 9600 BAUD, 8 databits, 1 stopbit and no paritybit
35
serinit:  
36
  mov srelh,#0FFh     ; baud-rate counter high-byte
37
  mov srell,#0D9h     ; baud-rate counter low-byte
38
  orl pcon,#10000000b ;Setze SMOD-Bit im Register PCON
39
                ;(verdoppelt Baud-Rate). 
40
  setb bd           ;sets BD-bit ir register ADCON0
41
          ;(Baud rate generator enable). 
42
  mov scon,#01010010b ;sets bits in register SCON
43
    ;(from left to right): 
44
      ;SM0=0, SM1=1, SM2=0:
45
      ;serial mode 1, as 8-bit-UART
46
      ;with variable baud-rate,
47
      ;with a start and a stopbit
48
     ;REN=1: Receiver enable.
49
     ;TB8=0: not used (only needed in modes 2 and 3)
50
     ;RB8=0: not used (only needed in modes 2 and 3)
51
     ;TI=1: Transmitter-Interrupt-Flag. 
52
           ;RI=0: Receiver-Interrupt-Flag. 
53
  ret   
54
  
55
  
56
serin:
57
  jnb ri, $   ; Warte auf Eingabe 
58
  clr ri ; Lösche das Eingabe-Flag
59
  mov a,sbuf  ; Lesen des Eingabezeichen aus dem Buffer 
60
  ret   
61
  
62
serout:
63
  jnb ti,$
64
  clr ti
65
  mov sbuf,a
66
  ret
67
  
68
end

Im Anhang hab ich noch das Datenblatt und ein Dokument von Atmel zu 
Atmels 8051µCs.

Falls jemand sich auskennt würde ich mich total über eure Hilfe freuen 
;)

Anon1234

von Georg G. (df2au)


Lesenswert?

Anon Anon schrieb:
> $include(reg515c.inc)

Sollte hier nicht besser das für den AT89C52 passende File stehen?

von Anon A. (anon1234)


Lesenswert?

Georg G. schrieb:
> Anon Anon schrieb:
>> $include(reg515c.inc)
>
> Sollte hier nicht besser das für den AT89C52 passende File stehen?

Hi Georg danke für den Tipp, da hab ich iwie garnicht dran gedacht..
Hab mittlerweile at89s53.inc eingebunden, da ich at89s52.inc bzw. 
at89c52.inc nirgends finden konnte..

Dafür habe ich unter:
http://manpage-textcube.blogspot.de/2009/12/8051%EC%A7%81%EB%A0%AC%ED%86%B5%EC%8B%A0-command-mode-%ED%9D%89%EB%82%B4%EB%82%B4%EA%B8%B0.html

endlich ein Beispiel gefunden, wie man die serielle Schnittstelle beim 
AT89S52 initialisiert:
1
;initializes serial interface with a baudrate of 19200bps
2
serinit:         
3
        MOV     TMOD, #20H   ; [GATE|C/T_|M1|M0|GATE|C/T_|M1|M0] #00100000B
4
        MOV     SCON, #52H     ; [SM0|SM1|SM2|REN|TB8|RB8|TI|RI] #01010010B
5
        MOV     A, PCON     
6
        SETB    ACC.7
7
        MOV     PCON, A      ; [SMOD|-|-|-|GF1|GF0|PD|IDL] SMOD=1
8
        MOV     TH1, #0FDH     ; 19200bps
9
        SETB    TR1          
10
        RET

Wie ich mir schon gedacht hatte muss man den Timer dabei selbst 
einstellen und starten.

Ich habe es jetzt in meinen Code eingebaut und es funktioniert :
1
$include(AT89S53.inc)
2
3
main:
4
  call serinit
5
  mov a,#'H'
6
  call serout 
7
  mov a,#'e'
8
  call serout 
9
  mov a,#'l'
10
  call serout 
11
  mov a,#'l'
12
  call serout 
13
  mov a,#'o'
14
  call serout 
15
  mov a,#' '
16
  call serout 
17
  mov a,#'W'
18
  call serout 
19
  mov a,#'o'
20
  call serout 
21
  mov a,#'r'
22
  call serout 
23
  mov a,#'l'
24
  call serout 
25
  mov a,#'d'
26
  call serout 
27
  mov a,#'!'
28
  call serout 
29
  jnb ti,$
30
  jmp main
31
32
33
;initializes serial interface with a baudrate of 19200bps
34
serinit:         
35
        MOV     TMOD, #20H   ; [GATE|C/T_|M1|M0|GATE|C/T_|M1|M0] #00100000B
36
        MOV     SCON, #52H     ; [SM0|SM1|SM2|REN|TB8|RB8|TI|RI] #01010010B
37
        MOV     A, PCON     
38
        SETB    ACC.7
39
        MOV     PCON, A      ; [SMOD|-|-|-|GF1|GF0|PD|IDL] SMOD=1
40
        MOV     TH1, #0FDH     ; 19200bps
41
        SETB    TR1          
42
        RET   
43
  
44
  
45
serin:
46
  jnb ri, $   ; Warte auf Eingabe 
47
  clr ri ; Lösche das Eingabe-Flag
48
  mov a,sbuf  ; Lesen des Eingabezeichen aus dem Buffer 
49
  ret   
50
  
51
serout:
52
  jnb ti,$
53
  clr ti
54
  mov sbuf,a
55
  ret
56
  
57
end

: Bearbeitet durch User
von Route_66 H. (route_66)


Lesenswert?

Anon Anon schrieb:
> endlich ein Beispiel gefunden, wie man die serielle Schnittstelle beim
> AT89S52 initialisiert:

> Wie ich mir schon gedacht hatte muss man den Timer dabei selbst
> einstellen und starten.

Das ist der Standard-8051-Mode, ohne dem Baudratengenerator des 89"S"52.
Kann man machen, hilft aber bei "krummen" Quarzfrequenzen manchmal 
nicht.

: Bearbeitet durch User
von Georg G. (df2au)


Lesenswert?

Route 66 schrieb:
> ohne dem Baudratengenerator des 89"S"52

Verrätst du uns auch, wo der versteckt ist? In der SFR-Map steht er 
leider nicht :-(

von Anon A. (anon1234)


Lesenswert?

Georg G. schrieb:
> Verrätst du uns auch, wo der versteckt ist? In der SFR-Map steht er
> leider nicht :-(

Das würde mich auch interessieren, ich hab nämlich leider nicht gefunden 
wie sich der richtige Baud-Raten-Generator starten lässt, bzw welche 
SFRs ich dafür brauche..

von Route_66 H. (route_66)


Lesenswert?

Georg G. schrieb:
> Verrätst du uns auch, wo der versteckt ist?

Der steckt im dritten Timer: Timer2.
Der 8051 hat nur Timer0 und Timer1; und den Timer1 verwendet er hier.

von Georg G. (df2au)


Lesenswert?

Route 66 schrieb:
> Der steckt im dritten Timer

Du bist ein echter Witzbold. Der TO kommt vom 80C515. Der hat einen 
separaten Baudraten Generator für 4800Bd und 9600Bd bei 12MHz Takt. So 
etwas gibt es im 89S52 nicht.

Und der im Link des Datenblattes für den UART genannte BDRCON existiert 
auch nicht. Da hat Atmel falsch abgeschrieben.

Dass man T1 oder T2 für die Baudraten Erzeugung verwenden kann, ist 
trivial.

von Anon A. (anon1234)


Lesenswert?

Route 66 schrieb:
> Der steckt im dritten Timer: Timer2.
> Der 8051 hat nur Timer0 und Timer1; und den Timer1 verwendet er hier.

Naja den Timer 2 gibt es im AT89S52 auf jeden fall auch.
Aber den seperaten Baud-Raten-Generator glaube ich nicht oder?
Ist es denn jetzt generell möglich mit anderen Baud-Raten zu arbeiten?
Beispielsweise 9600?
Und welche Baudrate hat mein Beispiel von oben?
Sind das tatsächlich 19200?

von Anon A. (anon1234)


Lesenswert?

Weiß das irgendjemand? :)

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Anon Anon schrieb:
> Aber den seperaten Baud-Raten-Generator glaube ich nicht oder?
> Ist es denn jetzt generell möglich mit anderen Baud-Raten zu arbeiten?

Ein eigenes Baudraten Register gibt es beim 89S(C)52 nicht, du kannst 
allerdings Timer 2 mit seinen 16 bit als Baudratengenerator benutzen. 
Andere Baudraten sind dann möglich, wenn auch meistens sinnlos, weil 
viel zu langsam. Es befreit allerdings Timer 1 für andere Aufgaben.
Sinnvoll ist der Einsatz eines 'Baudratenquarzes', wie z.B. 11,592 Mhz 
als Takt, wenn du genaue Baudraten brauchst.
Hol die am besten mal das "Atmel 8051 Microcontrollers
Hardware Manual", da steht alles über die Atmel MCS-51 Serie drin.

: Bearbeitet durch User
von Georg G. (df2au)


Lesenswert?

Matthias Sch. schrieb:
> Hol die am besten mal das "Atmel 8051 Microcontrollers
> Hardware Manual", da steht alles über die Atmel MCS-51 Serie drin.

Aber bitte Vorsicht! Da steht speziell zum Thema UART auch Falsches drin 
(gerade die Baudraten Erzeugung). Im Zweifelsfall immer mit dem 
Datenblatt des jeweiligen Typs genau vergleichen.

von Anon A. (anon1234)


Lesenswert?

Matthias Sch. schrieb:
> Ein eigenes Baudraten Register gibt es beim 89S(C)52 nicht, du kannst
> allerdings Timer 2 mit seinen 16 bit als Baudratengenerator benutzen.
> Andere Baudraten sind dann möglich, wenn auch meistens sinnlos, weil
> viel zu langsam. Es befreit allerdings Timer 1 für andere Aufgaben.
> Sinnvoll ist der Einsatz eines 'Baudratenquarzes', wie z.B. 11,592 Mhz
> als Takt, wenn du genaue Baudraten brauchst.
> Hol die am besten mal das "Atmel 8051 Microcontrollers
> Hardware Manual", da steht alles über die Atmel MCS-51 Serie drin.

Danke für die schnelle Antwort, dann weiß ich ja erstmal bescheid.
Ich denke mal fast ich bleibe auf dem Timer und mach die anderen Sachen 
auf dem Timer0.
Das Manual guck ich  mir aber glaub ich trotzdem mal an.
Was mich bloß noch interssieren würde ist, welche Baudrate ich denn nun 
tatsächlich mit meinem Beispielcode da oben habe.
Ich will die Ausgaben nämlich mit dem PC auslesen und dazu wäre es gut 
eine genaue Angabe zu haben, damit man diese dann am PC einstellen kann.
Ich verwende einen 12Mhz Quarz und setze TH1 auf #0FDH.
Laut Kommentar sollten das dann 19200baud sein. Aber stimmt das?

von Route_66 H. (route_66)


Lesenswert?

Anon Anon schrieb:
> Ich verwende einen 12Mhz Quarz und setze TH1 auf #0FDH.
> Laut Kommentar sollten das dann 19200baud sein. Aber stimmt das?

Genau 19200 wären es bei 11.0592 MHz Quarz.

von Peter D. (peda)


Lesenswert?

Wenn man die üblichen MC-Quarze (7,3728; 11,0592; 14,7456MHz usw.) 
nimmt, geht alles glatt mit T1 zu machen und man hat den 
leistungsfähigeren T2 für andere Sachen frei.

von Anon A. (anon1234)


Lesenswert?

Aah okay...
doofer Weise brauche ich eigentlich meinen 12,000 MHz Quarz, weil ich 
1-Wire-Sensoren mit dran habe und da das Timing passen muss.
Und mit nem 12Mhz Quarz, hat jeder Timerschritt genau 1µs. Das finde ich 
eigentlich sehr elegant..
Meint ihr, dass der PC das auch so erkennt, oder wisst ihr ne Lösung, 
wie ich entweder ne gerade Baudrate rausbekomme oder mein Signal so 
wieder hingebogen bekomme, dass der PC es erkennen kann?

von Georg G. (df2au)


Lesenswert?

Mit 12MHz Quarz und Timer 1 musst du runter mit der Baudrate, damit es 
gut passt. 110Bd wäre da ein (nicht ganz ernst gemeinter) Vorschlag.

In dem schon angesprochenen DOC4316.PDF findest du auf Seite 99 die 
Tabelle 2-21. Die zeigt dir die Möglichkeiten. 4800Bd ist da der obere 
Anschlag.

: Bearbeitet durch User
von Route_66 H. (route_66)


Lesenswert?

Anon Anon schrieb:
> Meint ihr, dass der PC das auch so erkennt, oder wisst ihr ne Lösung,
> wie ich entweder ne gerade Baudrate rausbekomme oder mein Signal so
> wieder hingebogen bekomme, dass der PC es erkennen kann?

Mit 12 MHz und dem Timer2 als Baudratengenerator sind 9600 drin,
bei RCAP2H=0FFh und RCAP2L=0D9h

von Lothar (Gast)


Lesenswert?

Anon Anon schrieb:
> AT89S52

Falls Du umsteigen kannst, ich habe hier den LPC935 der schafft mit dem 
internen 7.373MHz Oszillator mit dem BRG stabil 115200 Baud

von Peter D. (peda)


Lesenswert?

Anon Anon schrieb:
> weil ich
> 1-Wire-Sensoren mit dran habe und da das Timing passen muss.

Du hast Dir das 1-Wire Timing noch nie angesehen, stimmts?
Da sind so große Toleranzen erlaubt, daß es ohne Änderung bei 11 und 
12MHz klappen muß. Oder es war schon bei 12MHz auf Kante genäht.

Das Start-Low muß >1µs sein, gelesen werden muß <15µs nach der 
Low-Flanke.
Z.B. Startpuls = 5µs, lesen nach weiteren 5µs sind gültige Werte.
Da ist also Luft ohne Ende.

von Anon A. (anon1234)


Lesenswert?

Peter Dannegger schrieb:
> Du hast Dir das 1-Wire Timing noch nie angesehen, stimmts?
> Da sind so große Toleranzen erlaubt, daß es ohne Änderung bei 11 und
> 12MHz klappen muß. Oder es war schon bei 12MHz auf Kante genäht.
>
> Das Start-Low muß >1µs sein, gelesen werden muß <15µs nach der
> Low-Flanke.
> Z.B. Startpuls = 5µs, lesen nach weiteren 5µs sind gültige Werte.
> Da ist also Luft ohne Ende.

Hab mir das Timing sogar schon ein bisschen mehr angeguckt und auch 
größtenteils implementiert.
Aber ehrlich gesagt, hab ich mir keine Gedanken darüber gemacht, was die 
andere Taktfrequenz vom Quarz für einen zeitlichen Unterschied bei den 
Timerschritten macht. Dafür hatte ich noch keine Zeit und habs dann erst 
einmal damit abgehakt, weil ich dachte es ist wsl einfacher die sache 
mit der seriellen Schnittstelle anzupassen als das Timing von den 1-Wire 
Geräten.
Aber jetzt wo du's sagsts stimmt schon.
Wenn ich richtig gerechnet hab würde sich die Zeit für einen 
Timerschritt bei nem 11,0592 Mhz Quarz 0,0784µs verlängern :D
Das ist ja wirklich nicht so dramatisch

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.