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
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
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.
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..
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.
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.
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?
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.
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.
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?
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.
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.
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?
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.
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
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
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.
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