Goeiedag,
Ik heb tijdens de eerste semester dit jaar 8051 microcontrollers leren programmeren en de kennis ervan is ondertussen al wat weggezakt. En daarom ben ik nu van 0 begonnen met het herhalen en uitdiepen ervan.
Ik heb er al een aantal lichteffectjes opzitten (looplicht, volloper, leegloper, knightrider). Nu wou ik dit combineren met een volgende stap nl. interrupts.
De bedoeling is om een verkeerslicht te maken. Wanneer een voetganger op de knop drukt (P3.2) zal een interrupt gegeven worden en moet het licht van groen -> oranje naar rood gaan indien het op groen staat natuurlijk. Ik had toen al niet veel ervaring met externe interrupts en nu al helemaal niet meer.
Is er iemand die me kan helpen bij de eerste stappen? 
;*********************************************************************************;
; Oefening: verkeerslicht ;
; ;
;klokfrequentie = 12MHz ;
;*********************************************************************************;
org 0h
jmp start
org 100h
;Registernamen toekennen
IE0 equ 0003h
;Uitgangen en ingangen benoemen
groen equ P1.0 ;grote lichten
oranje equ P1.1
rood equ P1.2
rvoet equ P1.7 ;voetgangerslichten
gvoet equ P1.6
vdruk equ P3.2 ;drukknop voor voetgangers -> interrupt op programma die lichten op rood zet
start: mov P1,#0 ;alles uit
mov IE,#10000001b ;interrupts aanzetten
begin: setb rood
call rtijd ;tijd dat het licht op rood staat
mov P1,#0
setb groen
call gtijd
mov P1,#0
setb oranje
call otijd
mov P1,#0
jmp begin
rtijd: mov R0,#0
mov R1,#0
rt1: djnz R0,rt1
djnz R1,rt1
ret
gtijd: mov R0,#0
mov R1,#0
gt1: djnz R0,gt1
djnz R1,gt1
ret
otijd: mov R0,#0
mov R1,#0
ot1: djnz R0,ot1
djnz R1,ot1
ret
end
Ik zou met het interrupt een timer starten. Door deze timer bijvoorbeeld iedere 100ms een interrupt te laten genereren kan je een variabele ophogen.
Als de variabele 0 is staat het licht op groen. Is de variabele kleiner dan 50 (5 seconden) dan zet je het licht op oranje. Is de variabele groter dan 50 kleiner 200 dan rood, groter 200 weer groen en teller uit.
Preciese voorwaarden moet je even opstellen maar kan je volgens mij eenvoudig in asm oplossen.
Ik zou trouwens voor c kiezen, maar dat terzijde.
Maar dan kan ik het toch niet zo maken dat een voetganger op de knop drukt en de boel op rood gaat? Loopt het boeltje toch gewoon in lus?
Ik mis de vectoren naar je interrupt routines. Je enabled de int's wel maar niet waar ie naartoe moet springen in geval van een interrupt :
ORG 0x03 ; the ISV for the EXT 0 interrupt is 0x0003
EXT0INT: LJMP Int0Isr
ORG 0x0B ; the ISV for the TMR 0 interrupt is 0x000B
TMR0INT: LJMP Tmr0Isr
ORG 0x13 ; the ISV for the EXT 1 interrupt is 0x0013
EXT1INT: LJMP Int1Isr
ORG 0x1B ; the ISV for the TMR 1 interrupt is 0x001B
TMR1INT: LJMP Tmr1Isr
ORG 0x23 ; the ISV for the Serial Port interrupt is 0x0023
SERINT: LJMP SerIsr
Je hebt ze niet allemaal nodig maar indien je ze niet gebruikt zou ik om problemen te voorkomen een IRET geven.
Groeten, Bram
uZion
Even the smartest computer on earth would make a dog seems brilliant by comparison!
Als eerste mag ik weten welke 8051 je gaat gebruiken??
Je moet eerste precies schrijven in jou eigentaal wat je wilt en daarna kunt je dat vertalen naar een processor taal. Ten eerste over hoeveel stoplichten praten we hier twee een ???
bv.
1.) Alle lampjes moeten op rood staan en ook blijven.
2.) Als er een auto aan komt (knopje) dan moet de groene lamp na 2sec naar aan gaan. Zolang er auto's door groen rijden krijgt je pulsen van de drukknop. Deze pulsen die zorgen voor de interupt en ook voor een timer. Deze timer moet aangeven hoe lang deze auto door groen mogen rijden voordat een aanliggende auto ook voor een stoplicht staat.
Enz enz.
Ik verwijs je naar http://www.8052.com/tutint.phtml heel simpel uitgelegd. Andere uitleg http://www.mikroe.com/en/books/8051book/ch2/#ch2.8
Succes!!
mvgr uzion
Bedankt uzion maar die 8052.com gebruikte ik al lang. Op het moment gebruik ik een at89s4051.
Het is de bedoeling van te beginnen met lichten op rood -> lichten groen -> oranje. Op het moment een voetganger op de drukknop zou duwen = P3.2 (int0)zou hij naar de interrupt routine moeten springen en zou het verkeerslicht op oranje -> rood moeten springen.
Voor de voetgangers moet dan het licht op groen komen te staan. Op het moment dat het terug rood is voor voetgangers wordt er verder gegaan met groen voor de voertuigen.
groen equ P1.0 ;voertuiglichten
oranje equ P1.1
rood equ P1.2
rvoet equ P1.7 ;voetgangerslichten 'rvoet' = rood voetgangers
gvoet equ P1.6
vdruk equ P3.2 ;drukknop voor voetgangers(int0)zou hij naar de interrupt routine moeten springen
@Gitaarstudentje
Moet je wel je vector zetten anders springt ie niet (goed), zie mijn eerdere reply.
Groeten, Bram
Dus dat zou dan zoiets moeten zijn kan dat? Als ik simuleer en ik zet op een willekeurig ogenblik een 1 op men interruptpoort dan blijft men programma vastzitten op die regel?
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Misschien zou je er wat meer commentaar bij moeten zetten van wat je denkt dat er zou moeten gebeuren.
Het is nogal een ondoorzichtig geheel helaas...
De irq routine bv. test een output wat natuurlijk weinig zin heeft. (Je hebt die net zelf hoog of laag gezet dus je weet de status al...)
Beter om een 'state machine' te maken...
uZion
Even the smartest computer on earth would make a dog seems brilliant by comparison!
Op 30 mei 2008 14:59:51 schreef gitaarstudentje:
... en ik zet op een willekeurig ogenblik een 1 op men interruptpoort dan blijft men programma vastzitten op die regel?
bedoeld je echt een 1 of bedoeld je een 0. De int poorten reageren op een 0. Als je de zelfde tijd gebruikt voor rtijd gtijd dan kon je beter alleen een subroutine maken met de goeie delay time. Voor de otijd mag je wel een aparte tijd maken, die is normalite ook minder.
Verder is de tijd die je aangeeft (R0 en R1) te klein je ligt daar rond de 130msec tijd dacht ik, bij deze tijd gaat de lampjes knipperen.
Ik veronderstelt dat de IT0 is ook gezet. Wanneer je naar de int routine gaat zal ik als eerste de INT uitdoen ( clr EX0). Dan is het ook verstandig om een klein delay te maken voor de contact debouncer.
Verder zou ik in die INT routine alleen een flagje zetten. En bij het terugkeren uit de int. Een controle doen op die flag of het gezet is of niet. En waarom dit truck? Om een memory effect te creeren. Want in jou programma als de lampje niet groen is springt ie uit de int. En dan gebeurd er ook verder niets meer. De IT0 reageert op neergaande flank. Dus als de voetganger de knopje blijft drukken gebeurd er toch niets. En als de lampje bij de int groen was dan springt de programma naar oranje en valt weer in de normale loop van groen oranje rood. En springt nooit meer uit de INT (problemen). Wanneer die voetganger het knopje drukt dan moet de lampjes van de auto op rood en die van de voetganger op groen, ik ziet dit niet in de programma. Er zijn meer punten maar begint alvast die te bekijken. Bij het bedenken wordt je er slimmer van!!
mvgr uzion
Op 30 mei 2008 15:26:13 schreef bprosman:
Plaats de geassembleerde versie eens zodat we de adressen kunnen zien aub.
Geen idee wat je bedoelt? Als ik assembleer krijg ik toch hexfile... of bedoel je het bestand voor in het programma?
Op 30 mei 2008 16:26:27 schreef uZion:
[...]
Verder is de tijd die je aangeeft (R0 en R1) te klein je ligt daar rond de 130msec tijd dacht ik, bij deze tijd gaat de lampjes knipperen.
Wel met een 12MHz kristal is 1 macchinecyclus = 1µs, dus zou men lusje 256 x 256 x 3 = 196608µs duren dus zo'n 200ms. Inderdaad te kort. (mov= 1mc en djnz = 2mc)
Dus om dat nog is wat te verlengen naar een 20tal seconden zou dit moeten lukken:
rtijd: mov R0,#0
mov R1,#0
mov R2,#103d
rt1: djnz R0,rt1
djnz R1,rt1
djnz R2,rt1
ret256 x 256 x 102 x 3 = 20054016µs = 20 s
Of vergis ik me?
/edit: Kwestie van die tijd subroutines; het is de bedoeling voor elke lamp een andere tijd. Er moeten er nog bijkomen voor de andere bestuurders aan't kruispunt die dan mogen doorrijden als't voor de ene richting rood is. Zoals ze doen aan drukke straten, de drukste krijgt wat langer groen licht. -> wordt leuk speelgoed voor men zusje 
Oh ja waarom moet die IT0 enabled? Die is toch timer interrupt en niet extern?
uZion
Even the smartest computer on earth would make a dog seems brilliant by comparison!
Op 30 mei 2008 18:47:20 schreef gitaarstudentje:
Oh ja waarom moet die IT0 enabled? Die is toch timer interrupt en niet extern?
Look for TCON register bit0 http://www.ikalogic.com/tut_8051_4.php
mcs51mc
Never forget the KISS principle: Keep It Stupid Simple!!
Hierbij een aantal stukjes code die je verder zouden moeten helpen
1) Constante voor een delay van 10ms
;Constant = (Delay * Fosc) / 12
;Delay = Time in µs 10000 10000 10000
;Fosc = Osc frequency in MHz 12 22.1184 11.0592
;Constant = 10000 18432 9216
;+9 due to reload timer & latency
;
Time_0 equ 65535 - 10000 + 9 ;55544
2) Initialiseren en starten van Timer 0 in auto reload mode
mov TH0,#HIGH Time_0 ;initialize interrupts
mov TL0,#LOW Time_0
mov TMOD,#01H ;timer 0 mode 1
setb ET0 ;enable interrupt timer 0
setb EA
setb TR0 ;start timer 0
Deze code moet je dus slechts éénmaal doorlopen
3) Code bij de aanvang van je ISR
Timer_0: mov th0,#High Time_0 ;Restart timer
mov tl0,#Low Time_0
push acc ;Save registers used in ISR
push b
push dph
push dpl
push psw
4) Code juist voor het verlaten van je ISR. Zorg ervoor dat je ALTIJD langs deze code je ISR verlaat
;Einde ISR: reset registers
;
Timer_0_End: pop psw ;Restore registers
pop dpl
pop dph
pop b
pop acc
reti ;Einde ISR
Met deze opzet zal je code continu om de 10msec door de ISR van T0 gaan.
Aan jouw om daar tellerkes in te zetten die de lichten controleren.
Probeer eerst je probleem in een 'state machine' te vertalen.
State 1 = Hoofdbaan rood voor x * 10ms
State 2 = Hoofdbaan groen voor y * 10ms
State 3 = ... ...
Je kan dat best doen aan de hand van een uitgetekend tijddiagramma. Telkens er iets wijzigt heb je een nieuwe state nodig.
Als je in de ISR van T0 komt moet een bepaalde teller (x, y, ... ...) aangepast worden. Dewelke zal afhangen van de actuele state.
Dus als je in de ISR T0 komt:
1) Check welke state
2) Increment teller van die state en check naar eindwaarde
3) Eindwaarde bereikt?
3a) Ja: ga naar de volgende state
3b) Neen: niets doen
Als er een interrupt binnenkomt van de drukknop moet je de state machine in de juiste state zetten en de teller initialiseren.
De rest loopt dan terug vanzelf over de ISR T0.
[Bericht gewijzigd door mcs51mc op (23%)]