Opdracht maken van klok, met interupts, serieel sturen en looptlicht

Opdracht:
Ontwerp van een klok met de aanduiding van uren en minuten. De tijdbasis wordt gevormd door timer0 die als 8-bit auto-reload timer geconfigureerd wordt, en die om de 200µs een interrupt genereert.
Elke seconde wordt de tijdsaanduiding in de vorm "uu:mm:ss" ook via de seriële poort naar de PC verstuurd. Baudrate=4800 baud.
Terwijl de tijd wordt weergegeven moet op poort0 (=ledbar) een lichteffect zichtbaar zijn. Tijdens de even minuten moet het een linkslopend looplicht zijn, terwijl het tijdens de oneven minuten een rechtslopend looplicht moet zijn.

Opmerkingen:
1) de klok werkt
2) looplicht werkt
3) het sturen van de seriele poort gaat, maar ik krijg steeds als laatste een 01 in mijn SBUF T.
Bv bij seconde 3: R1 = 03 is de laatste waarde in SBUF T = 01
4) ik heb niet direct gebruik gemaakt van interrupts. De taak moet vanavond ingediend moeten worden, dus dat wordt te moeilijk om nog inorde te krijgen. Graag zou ik toch weten hoe ik het met interrupts had kunnen doen.

code:

     ORG 0h
           LJMP start
           ORG 30h
 
Start:     MOV SCON,#40h         ;serieel kanaal van mode1 8-bit UART variabele baudrate instellen
           MOV TMOD,#22h         ;instellen timer1 als 8-bit auto reload voor baudrategenerator
           ORL PCON,#80h         ;baudrate verdubbelaar activeren
           MOV TH1,#243          ;4800 baudrate
           MOV TL1,#243          ;4800 baudrate
           SETB TR1              ;baudrategenerator activeren
 
           MOV TH0,#037h         ;startwaarde voor 200µs( 65535 - 200 = 65335 = FF37) FF bij de hoogste waarde
           MOV TL0,#037h         ;startwaarde voor 200µs( 65535 - 200 = 65335 = FF37) 37 bij de laagste waarde
           SETB TR0              ;timer0 starten
 
           MOV R1,#000H          ;seconden op 0 
           MOV P1,#0
           MOV R2,#000H          ;minuten op 0
           MOV P2,#0
           MOV R3,#000H          ;uren op 0
           MOV P3,#0 
           MOV R4,#000H		 ; register voor maxwaarde teller om seconde te bekomen (=100)
           MOV R5,#000H		 ; register voor maxwoorde teller om seconde te bekomen (=50)
           MOV P0,#00000001B     ;P0 op 1 zetten, Po wordt gebruikt voor het looplicht 

 
MAIN:      CALL KLOK
	   CALL optellen
           CALL looplicht
           LJMP MAIN
 
KLOK:	   JNB TF0,klok          ;als TF0=0, spring naar klok
           CLR TF0
           RET
 
LOOPLICHT: MOV A,R2
           ANL A,#00000001B
           JNZ ONEVEN            ;bit 0=1; spring naar ONEVEN
 
EVEN:      MOV A,P0
           RL A
           MOV P0,A
           RET
 
ONEVEN:    MOV A,P0
           RR A
           MOV P0,A
           RET
 
optellen:  INC R4
	   CJNE R4,#100,optel_ret
	   MOV R4, #0
	   INC R5
	   CJNE R5,#50,optel_ret
	   MOV R5, #0 
           inc R1
           MOV A, R1
           DA  A                  ;Decimal adjust
           MOV R1, A 	
           CJNE R1,#60h,weergave  ;max.waarde = 59 seconden
           MOV R1,#0
           INC R2                 ;verhogen van de minuten
           MOV A, R2
           DA  A                  ;Decimal adjust 
           MOV R2, A 	
           CJNE R2,#60h,weergave  ;max.waarde = 59 minuten
           MOV R2,#0
           INC R3                 ;verhogen van de uren
           MOV A, R3
           DA  A                  ;Decimal adjust
           MOV R3, A 	
           CJNE R3,#24h,weergave  ;maximumwaarde = 23 uren
           MOV R3,#0
 optel_ret: RET

weergave:;- - - - - - uren
           MOV  A, R3       ;uren laden
           SWAP A           ;nibbles omruilen
           ANL  A, #0Fh     ;msn eraf
           ADD  A, #30h     ;30 hex optellen voor ascii
           MOV  SBUF, A     ;versturen (tientallen)
txwait:    JNB  TI, txwait  ;wachten tot versturen klaar is
           CLR  TI          ;flag clearen
           MOV  A, R3       ;uren laden
           ANL  A, #0Fh     ;msn eraf 
           ADD  A, #30h     ;30 hex optellen voor ascii 
           MOV  SBUF, A     ;versturen (eenheden)  
txwait2:   JNB  TI, txwait2 ;wachten tot versturen klaar is
           CLR  TI          ;flag clearen
 
;- - - - - - dubbelpunt
 
           MOV  A, #03Ah     ;dubbelpunt laden
           MOV  SBUF, A      ;versturen (tientallen)
txwait3:   JNB  TI, txwait3  ;wachten tot versturen klaar is
           CLR  TI           ;flag clearen
 
;- - - - - - minuten
 
           MOV  A, R2        ;minuten laden
           SWAP A            ;nibbles omruilen
           ANL  A, #0Fh      ;msn eraf
           ADD  A, #30h      ;30 hex optellen voor ascii
           MOV  SBUF, A      ;versturen (tientallen)
txwait4:   JNB  TI, txwait4  ;wachten tot versturen klaar is
           CLR  TI           ;flag clearen
           MOV  A, R2        ;minuten laden
           ANL  A, #0Fh      ;msn eraf 
           ADD  A, #30h      ;30 hex optellen voor ascii 
           MOV  SBUF, A      ;versturen (eenheden)  
txwait5:   JNB  TI, txwait5  ;wachten tot versturen klaar is
           CLR  TI           ;flag clearen
 
;- - - - - - dubbelpunt
 
           MOV  A, #03Ah     ;dubbelpunt laden
           MOV  SBUF, A      ;versturen (tientallen)
txwait6:   JNB  TI, txwait6  ;wachten tot versturen klaar is
           CLR  TI           ;flag clearen
 
;- - - - - - seconden
 
           MOV  A, R1        ;seconden laden
           SWAP A            ;nibbles omruilen
           ANL  A, #0Fh      ;msn eraf
           ADD  A, #30h      ;30 hex optellen voor ascii
           MOV  SBUF, A      ;versturen (tientallen)
txwait7:   JNB  TI, txwait7  ;wachten tot versturen klaar is
           CLR  TI           ;flag clearen
           MOV  A, R1        ;seconden laden
           ANL  A, #0Fh      ;msn eraf 
           ADD  A, #30h      ;30 hex optellen voor ascii 
           MOV  SBUF, A      ;versturen (eenheden)  
txwait8:   JNB  TI, txwait8  ;wachten tot versturen klaar is
           CLR  TI           ;flag clearen

           MOV P1,R1         ;seconden worden weergegeven op poort0
           MOV P2,R2         ;minuten worden weergegeven op poort1
           MOV P3,R3         ;uren worden weergegeven op poort2

           RET
Arco

Special Member

Heb je dat in Edsim51 geprobeerd? (hier werkt dat goed)
't Is wel een draak van een programma (traag, onlogisch en te kleine windows), maar 'it does the job'... ;)

Als je timer 1 reload op #3Ah zet, dan loopt de boel redelijk gelijk...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Heb even edsim gedownload en de code getest, het doet wat hij moet doen!
Hoe bedoel je timer1 reload op #3Ah?

In verband met een draak van een programma inderdaad, een grote en lelijke draak.
Hoe had ik het via interupts kunnen doen? (en nu verwacht ik geen hele code hoor)

Arco

Special Member

TH0 en TL0 niet op #37h, maar op #3Ah... (interrupts zal ik straks eens naar kijken)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Oke, ik was even in de war, ik dacht dat je Th1 en TL1 bedoelde, maar dat is voor de baudrate in te stellen daarmee dat ik niet snapte wat je bedoelde.

Arco

Special Member

Omdat de serieele poort op P3.0 en P3.1 zit, kun je niet zonder meer de uren data op poort 3 zetten. (pin 0 en 1 zijn al gebruikt door de UART)
Wil je toch beiden gebruiken, dan kun je de displaydata 2 plaatsen naar links schuiven. (uren zijn toch nooit meer als 6 bits, dus geen probleem)
Simpelste gaat het met optellen (4x optellen is zelfde als 2 shifts). Displaydata verschuift dan van bit [5...0] naar [7...2]

Was:

code:


           MOV P1,R1         ;seconden worden weergegeven op poort0
           MOV P2,R2         ;minuten worden weergegeven op poort1
           MOV P3,R3         ;uren worden weergegeven op poort2

Wordt:

code:


           MOV P1,R1         ;seconden worden weergegeven op poort1
           MOV P2,R2         ;minuten worden weergegeven op poort2
           MOV A,R3          ;uren worden weergegeven op poort3
           ADD A,R3          ;Shift naar links
           ADD A,R3          ;
           ADD A,R3          ;
           MOV P3,A          ;
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Wat ik niet snap is dat het met een uitgerekende waarde niet gelijk loopt.

Als ik het goed begrijp is de timer er 1 die altijd omhoog loopt en een periode van 200microseconde krijg je door hem op -56 te starten. Dan kan het nog eentje schelen omdat ie wel-of-niet de 0 meeneemt of een klok nodig heeft om de nieuwe waarde te laden.

Maar #3Ah is 58 en m.i. zeker 1 te ver van wat het moet zijn.

Oh! Wacht! Nu snap ik het. Hij is een tijd doof voor de timer tijdens het versturen van de tijd over de seriele poort!

Dit kan je verbeteren door interrupts te gebruiken. Je laat de timer een interrupt genereren en doet daar het: "hoog de tel-tot-5000 teller op". Als die teller op 5000 is aangekomen zet je een vlaggetje en je hoofdprogramma weet dat ie de seconden (en minuten, uren etc) op moet
hogen. Nu mag de "verstuur de data" bijna een seconde duren, de timer blijft netjes doorlopen!

Nog mooier is om ook voor de seriele output een interrupt te gebruiken. Je doet een print_tijd, die een buffer vult en de "serieeele buffer is leeg" inteerrupt aanzet. Die interrupt haalt dan 1 karakter uit de buffer en verstuurt die. Totdat de buffer leeg is en de interrupt weer uitgezet kan worden.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Voor de opgave dienen de waarden van seconden,minuten en uren toch niet afgelezen te worden op de poorten? Dus in principe kan ik onderstaande code weglaten toch? Enig idee hoe ik het programma laat doorlopen tot als ik een uurtje heb?

code:

MOV P1,R1         ;seconden worden weergegeven op poort0
MOV P2,R2         ;minuten worden weergegeven op poort1
MOV P3,R3         ;uren worden weergegeven op poort2
Arco

Special Member

Als het niet gebruikt wordt kun je het weglaten, ja.
Je kunt de simulator vooruit zetten. Druk op 'run' zodat het programma start. Druk dan op 'pause'
Hierna kun je de gewenste waardes voor R1, R2, en R3 invullen op het linkse schermpje (in Hex). Dan weer op 'run' en de zaak gaat verder...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Rew, In verband met de interrupts voor 5000 heb ik volgend codetje bedacht, heb hem nog niet uitgeprobeerd want ben bezig met mn verslag te typen. Waardoor ik ook even niet al te veel tijd wil verliezen met die interrupts

In principe blijven de instellingen voor de timer gelijk, het enige wat ik nog moet doen is de interrupt aanzetten toch?

SETB EA
SETB ETO

Mijn timer is een auto reload 8bit, dat houdt in dat mn dat ik mijn waarden niet elke keer opnieuw moet instellen bij elke interrupt toch?

Dus dan heb ik qua interrupt routine enkel dit, kan dat ?

code:

t0isr: 
CLR ET0 ; interrupt op timer0 disablen
PUSH PSW ; PSW register op stack zetten
PUSH ACC ; ACC op stack zetten
INC R4 CJNE #100,optel_ret
MOV R4, #0
INC R5
CJNE R5,#50,optel_ret
POP ACC
POP PSW
RETI

Op 20 augustus 2016 17:48:47 schreef Thomas993:
want ben bezig met mn verslag te typen.

Ga je Circuits Online vermelden in je verslag ?

Ik weet niet of dat zo'n goed idee is, ik zou het eerder vermelden als 'Ik heb gebruik gemaakt van het internet om informatie op te zoeken en hulp te vragen waardoor ik de opgave tot een goed einde kon brengen.'

Ik denk het ook dat je CO best niet vermeld, want dan ziet je leraar meteen dat je niet veel geoefend hebt tijdens het schooljaar.

Edit: en dan verwijs ik even naar je vorige post
http://www.circuitsonline.net/forum/view/133293

Succes met je examen alvast.

[Bericht gewijzigd door kohen op zaterdag 20 augustus 2016 18:12:27 (26%)

Arco

Special Member

Voor de interrupt kun je beter timer 2 gebruiken, da's een 16 bit timer; ook auto-reload. (kun je veel langere tijden gebruiken)
Je gebruikt dacht ik de AT89C5131? Houd er dan qua timing rekening mee dat het een enhanced 8051 core is.
Die gebruikt maar 6 clockpulsen per instruction cycle. (de originele 8051 gebruikt er 12). De boel loopt dus 2x zo snel.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

In de opgave wordt wel gezegd dat "De tijdbasis wordt gevormd door timer0 die als 8-bit auto-reload timer geconfigureerd wordt, en die om de 200µs een interrupt genereert."

rob040

Golden Member

Hoi Thomas, mijn laatste vraag in het gesloten topic van S-man was een algemene vraag (weliswaar gevoed door de -non- inzet van TS).
Het forum is er juist om kennis op te doen en hulp te vragen, daar maak ook ik gebruik van. Echter bij examens leek het mij zinvol om het kennisniveau van de kandidaat te toetsen en dat wordt lastig als je vooraf hulp krijgt. Maar ik begrijp nu van collegae posters dat dit tegenwoordig niet vreemd meer is.

Rest mij je veel succes te wensen!

Arco

Special Member

Als je echt iets wilt leren is een beetje hulp nooit weg. Als je iets niet helemaal weet of begrijpt, en niemand wil het je vertellen, dan kom je er ook nooit achter...
Met de mentaliteit van S-man kom je natuurlijk nergens. Beter een cursus 'kreatief met kurk' gaan volgen... ;)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Op 20 augustus 2016 17:48:47 schreef Thomas993:
het enige wat ik nog moet doen is de interrupt aanzetten toch?

SETB EA
SETB ETO

Ik heb pak-'m-beet 30 jaar (*) geen 8051 assembly meer geschreven. Dus wat deze bitjes doen dat weet ik niet meer uit m'n hoofd.

Wat ik wel nog weet is dat ik me toen een ongeluk heb gezocht omdat er diverse bitjes waren die de interrupts tegen hielden. Dus ergens in de timer moet je het aanzetten, maar ergens moet je ook globaal interrupt aanzetten.

(*) Zomer '88, dus 28 jaar. Vergeef me. :-)

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/