Het maken van een uurwerk via het programma MCU 8051 IDE

Dit topic is gesloten


Ik zie het al voor me dat iemand jou uitlegt hoe een wasmachine werkt.

Barmhartige helper: als ik jou was zou ik eerst eens uitzoeken waar het wasmiddel in moet
S-man: Ik heb hier al een fles wasmiddel staan. Ik heb het wolwasprogramma geselecteerd maar hij marcheert niet.
Barmhartige helper: Kijk, zo doe je het zeepbakje open. Bedenk nu zelf eens wat de volgende stap is.
S-man: Ik heb nu alles geprobeerd maar mijn kleren zijn nog niet schoon.
Barmhartige helper: Wacht nou even, doe het eens stap voor stap
Barmhartige helper 2: Hij gaat sowieso niks doen nu want de stekker zit er niet eens in
S-man: De stekker? Ik heb het wolwasprogramma toch geselecteerd? En ik heb nu ook de fles in de opening gegooid. Zal ik de deur dicht doen?

If you want to succeed, double your failure rate.

Bij mij op school kon je een testbord kopen. Hierop stond een microcontroller, leds, schakelaars, een MAX232 enzo.
Hiermee kon je ook thuis aan de slag. Heb ik veel aan gehad.
Voor dit jaar is het te laat S-man, maar volgend jaar zeker aanschaffen die handel.

Bied de leraar in Gent ook zo'n testprinten aan ? Met welke microcontrollers werken ze eigenlijk tegenwoordig daar ?

Optellen() en weergave() is 'dode code'; het wordt nooit uitgevoerd...

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

@Arco: zou hij het nu wel lezen?

Op 17 augustus 2016 18:58:03 schreef kohen:
Bij mij op school kon je een testbord kopen.
[...] Voor dit jaar is het te laat S-man, maar volgend jaar zeker aanschaffen die handel.

Nou is een simulator niet zo waardevol als een echte opstelling, dus ik sluit me volledig aan bij kohen. Ik vraag me echter wel af of het met zo'n test-opstelling dan wel goed gaat komen, als je het meest elementaire zelfs nog niet in een simulator aan de gang krijgt.

Voor dit specifieke voorbeeld had ik al in het vorige topic even zitten stoeien met EdSim51 om te controleren of het programma van Davidoff wel werkte als je die stack-overflow er uit haalde (2 mnemonics veranderen). Daarna werkte het (even afgezien van de missende functionaliteit van de seriële poort) uitstekend en dat kon ik keurig zien op de uitgangen. Ik had nog nooit met het programma gewerkt en nog nooit op een 8051 in assembly geschreven.

If you want to succeed, double your failure rate.

Ik heb die Edsim ook eens gedownload, maar er is niks zinnigs mee te beginnen. Er zit niks in die zipfile wat executable is... :(

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

Op 17 augustus 2016 18:59:47 schreef Arco:
Optellen() en weergave() is 'dode code'; het wordt nooit uitgevoerd...

moet ik die interrupt dan toegeven in mijn interrupt van de klok na JZ even en na JNZ oneven?

Je gebruikt geen interrupts in je programma, dus iets 'toegeven' kan ook niet. Gewoon beide in main() zetten achter de call naar klok()

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

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 R1,#000H ;seconden op 0 (hoef je maar 1x uit te voeren
MOV R2,#000H ;minuten op 0
MOV R3,#000H ;uren op 0
MOV P0,#00000001B ;P0 op 1 zetten, Po wordt gebruikt voor het looplicht

MAIN: LCALL KLOK
CALL optellen
CALL weergaveSeconden
CALL weergaveMinuten
CALL weergaveUren
LJMP MAIN

KLOK: CLR TR0 ; de timer0 wordt eerst gewist voor de programma begint
CLR TF0 ; wissen van de overflow vlag van timer0
MOV TH0,#0FFh ; startwaarde voor 200µs( 65535 - 200 = 65335 = FF37) FF bij de hoogste waarde
MOV TL0,#37h ; startwaarde voor 200µs( 65535 - 200 = 65335 = FF37) 37 bij de laagste waarde
SETB TR0 ; timer0 starten
JNB TF0,$ ;als TF0=0, spring naar klok
CLR TF0
MOV A,R1
ANL A,#00000001B
JZ EVEN ;als bit0=0, dan is het een even getal, spring dan naar routine EVEN
JNZ ONEVEN ;anders spring naar ONEVEN
RET

EVEN: MOV A,P0
RL A
MOV P0,A
RET

ONEVEN: MOV A,P0
RR A
MOV P0,A
RET

optellen:
INC R1
CJNE R1,#60d,weergaveSeconden ; maximumwaarde = 60 seconden
MOV R1,#0
INC R2 ; verhogen van de minuten
CJNE R2,#60d,weergaveMinuten ; maximumwaarde = 60 minuten
MOV R2,#0
INC R3 ; verhogen van de uren
CJNE R3,#24d,weergaveUren ; maximumwaarde = 24 uren
MOV R3,#0
RET
weergaveSeconden:
MOV P1,R1; seconden worden weergegeven op poort0

weergaveMinuten:
MOV P2,R2; minuten worden weergegeven op poort1

weergaveUren:
MOV P3,R3; uren worden weergegeven op poort2
RET
END; einde van het progamma

heb dit nu, maar mijn probleem is dat hij altijd bij de seconden blijft en niet naar de minuten en de uren. Hoe moet ik dat oplossen?

code:


CALL weergaveSeconden
CALL weergaveMinuten
CALL weergaveUren

Heeft weinig nut; weergaveMinuten/Uren zijn labels binnen weergaveSeconden. Je voert nu steeds weergaveMinuten 2x uit, en weergaveUren 3x...

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

Moet ik ze dan eruit halen? Of moet ik ze behouden en andere regels aan toevoegen?

Ik heb het onnodige spul gesnoeid/commentaar kloppend gemaakt en de code maar weer eens geindenteerd (kwartje wil maar niet erg vallen... :( )

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 R1,#000H          ;seconden op 0 (hoef je maar 1x uit te voeren
           MOV R2,#000H          ;minuten op 0
           MOV R3,#000H          ;uren op 0
           MOV P0,#00000001B     ;P0 op 1 zetten, Po wordt gebruikt voor het looplicht 

MAIN:      CALL KLOK
           CALL optellen
           CALL weergave
           LJMP MAIN

KLOK:      CLR TR0               ;de timer0 wordt eerst gewist voor de programma begint
           CLR TF0               ;wissen van de overflow vlag van timer0
           MOV TH0,#0FFh         ;startwaarde voor 200µs( 65535 - 200 = 65335 = FF37) FF bij de hoogste waarde
           MOV TL0,#37h          ;startwaarde voor 200µs( 65535 - 200 = 65335 = FF37) 37 bij de laagste waarde
           SETB TR0              ;timer0 starten
           JNB TF0,$             ;als TF0=0, spring naar klok
           CLR TF0
           MOV A,R1
           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 R1
           CJNE R1,#60d,optel_ret ;max.waarde = 59 seconden
           MOV R1,#0
           INC R2                 ;verhogen van de minuten
           CJNE R2,#60d,optel_ret ;max.waarde = 59 minuten
           MOV R2,#0
           INC R3                 ;verhogen van de uren
           CJNE R3,#24d,optel_ret ;maximumwaarde = 23 uren
           MOV R3,#0
optel_ret: RET

weergave:
          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
       
          END                   
Arco - "Simplicity is a prerequisite for reliability" - hard en software ontwikkeling: www.arcovox.com

Tja ik heb dit allemaal een beetje gevolgd. Iets dat je moet leren door een paar maanden lessen te volgen en oefeningen te maken leer je nu eenmaal niet in drie dagen. Ik ben begonnen op een zx81 bij een vriendje toen ik op de mavo zat. Ik was 16 ofzo. Later, 'ik was toen 17' op een ZX spectrum kwam ik niet uit de voeten met basic en heb ik mijn eerste stappen gezet met assembly.

Internet was er niet. Alleen een boek uit de bieb en wat electuurs en radiobulletins. Ook geen leraar die in de les verteld wat een interrupt is. Daarmee maakt ik toch mijn eerste looplicht (nightrider natuurlijk) onder interrupt. Later ook een een soort seriele poort met bitbanging. Alles zonder echte assembler. Gewoon een kartonnen kaartje met de opcodes en de vertaling naar HEX getallen. Met de hand en potlood en gum coderen. Ook mijn lego auto bestuurde ik ermee. Mindstorms was er nog niet.

Onze TS weet waarschijnlijk niet dat de meeste mensen hier op deze manier bezig geweest zijn en dat dat veel moeite koste. Even naar de bekende weg vragen op internet kon niet. Alleen vind geen van deze mensen het een moeilijk vak. Het is namelijk geheel niet moeilijk. Het is een logische puzzel die zichzelf oplost door er stap voor stap door heen te gaan. Het vak analoge elektronica is veel en veel lastiger. Helemaal als je iets goeds wil ontwerpen dat lange tijd goed moet blijven werken.

En met de moderne tools is het helemaal makkelijk gemaakt. Voor elke cpu is er wel ergens een handige compiler, assembler of wat dan ook te vinden die allerlei lastige kwesties met een paar simpele vragen voor je oplost.

De TS heeft natuurlijk niets aan dit verhaal maar je zult de code pas begrijpen als je het zelf kunt maken. Stelen van internet en paar pleisters hier en daar om het voor de specifieke schoolvraag werkend te krijgen heeft geen educatieve waarde. Als jouw docent mondeling vragen gaat stellen over het programma val je bij de eerste vraag al door de mand.

Als ik de ts was zou ik in elk geval uitzoeken hoe een interrupt werkt. Waarschijnlijk heeft de ts daar allang geleden een oefening voor gekregen. Die oefening zou ik nog maar eens even doen en goed doornemen.

Over het algemeen is een programma opgebouwd uit een paar delen.

Je begint met een stuk initialisatie. Je stelt daar alle bits, registers, poorten enz in. Geeft alle tellers hun begin waarde. In een hogere programmeertaal declareer je daar alles. In assembly kan dat niet. Daar heb je alleen een hele berg genummerde vakjes. En je getalletje zet je in een van die vakjes. Het nummer (of adress) van dat vakje kun je dan als een soort van variabele gebruiken.

Daarna komt de main routine. De cpu doet daar het gewone dagelijkse werk. Vaak is dat helemaal niets. Hij staat te wachten.

Dan heb je de z.g. interrupt service routine. Daarin worden de interrupts afgehandeld en verwerkt.

Er worden het liefst geen wacht lussen gebruikt. Directe sprongen worden ook vermeden. Liever dingen als jump subroutine gebruiken. Nooit uit een subroutine springen. Dan gaat je stack in de war. In sommige gevallen moet je misschien zelfs een interrupt blokkeren of zelfs in de wacht zetten.

Ik weet niet of je je opdracht mondeling moet verdedigen. Daar was dacht ik wel sprake van bij die andere knul. Maar een vraag van de docent hierover? En je valt keihard door de mand als je niet exact weet hoe dit werkt.

Desondanks hoop ik wel dat je haalt en er zoveel van leert dat je je vakken serieuzer gaat volgen. Want ik vermoed dat je nog een paar vakken hebt met een probleem. Het programmeren van een cpu in assembly is echt geen rocketscience, maar heel goed te doen als je gewoon je opdrachtjes maakt en een beetje oefent in het aan het examen voorafgaande semester.

Het programmeren in assembly kan heel erg leuk zijn en in sommige gevallen een must. Je zit echt met de basisbouwstenen van de digitale technologie te knutselen. In bepaalde gevallen vervaagt de grens tussen analoog en digitaal dan zelfs.

Ikzelf ben altijd bij die vage grens tussen analoge en digitale techniek gebleven. Een grens waar niet heel mensen op bezig zijn en die door het toenemen van de rekenkracht alleen maar vager gaat worden. Een moderne sdr radio zit toch heel anders in elkaar dan een conventionele radio. Er zijn dingen mogelijk geworden die eerder gewoon echt niet konden. En het zou me niets verbazen dat er ooit weer een omslag van digitaal naar analoog gaat komen. Beide technieken zullen dan naast elkaar blijven bestaan.

suc6 met je examen

Ik ben ooit begonnen met de 8048. Ik had toen geen assembler; mijn eerste programma's heb ik direct als hex code ingeklopt.
Ook niet moeilijk, alleen veel opzoeken (welke hexcode hoort er bij welke instructie...). Relatieve jumps was wel een heel gereken steeds... ;)

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

Op 17 augustus 2016 22:24:53 schreef S-man:
Moet ik ze dan eruit halen? Of moet ik ze behouden en andere regels aan toevoegen?

Je moet begrijpen hoe die overflow bij 60 in die weergave-lus werkt, dan is je vraag overbodig. Maar jij bent niet degene die de code heeft bedacht, en je hebt te weinig kennis in de lessen opgedaan. De combinatie maakt dat je niet ziet wat de bedoeling is in die regels code.

Schrijf desnoods zelf die weergave-routine, dan wordt hij misschien minder efficiënt en misschien voor ons onlogischer, maar dan heb je het tenminste zelf bedacht en snap je wat de code doet.

If you want to succeed, double your failure rate.

@Ex-fietser, klinkt heel bekend, zelf met een MPF-1 via school gewerkt, direct assembly invoeren. Daarnaast zelf de adressen berekenen voor de sprong instructies, heel wat uren aan besteed.

https://en.wikipedia.org/wiki/Micro-Professor_MPF-I

It's the rule that you live by and die for It's the one thing you can't deny Even though you don't know what the price is. It is justified.

als ik het uittest, dan komt deze melding

Simulator warning:

UART: Frame discarded (according to MCS-51 manuel)
PC: 0x62
Line: 26
File: Suys Sören klok.asm

als ik die $ vervangt met KLOK, dan blijft hij in eeuwige lus bewegen. Wat moet ik dan aanpassen?

En ook mijn looplicht marcheert maar half, alles gebeurt op 1 lamp

[Bericht gewijzigd door S-man op 18 augustus 2016 11:09:23 (12%)]

Op 17 augustus 2016 21:50:24 schreef Arco:

code:


CALL weergaveSeconden
CALL weergaveMinuten
CALL weergaveUren

Heeft weinig nut; weergaveMinuten/Uren zijn labels binnen weergaveSeconden. Je voert nu steeds weergaveMinuten 2x uit, en weergaveUren 3x...

terwijl deze code COMPLEET chinees is voor mij, heb ik zelf direct begrepen wat arco hier zegt.

pic asm code:


optellen:
        INC R1
        CJNE R1,#60d,weergaveSeconden ; maximumwaarde = 60 seconden 
        MOV R1,#0

        INC R2 ; verhogen van de minuten
        CJNE R2,#60d,weergaveMinuten ; maximumwaarde = 60 minuten
        MOV R2,#0

        INC R3 ; verhogen van de uren
        CJNE R3,#24d,weergaveUren ; maximumwaarde = 24 uren
        MOV R3,#0

        RET
weergaveSeconden: 
 	MOV P1,R1; seconden worden weergegeven op poort0

weergaveMinuten:
 	MOV P2,R2; minuten worden weergegeven op poort1 

 weergaveUren:
 	MOV P3,R3; uren worden weergegeven op poort2 
 	RET
        END; einde van het progamma

zeg eens stap voor stap wat er gebeurd als je weergaveSeconden oproept.

ik hou van werken ..., ik kan er uren naar kijken

@fcapri
Dit is wel een vreemde construktie, maar werkt wel. Deze construktie is tamelijk gebruikelijk in assembly al is dat hier niet van toepassing.

Maar dit is niet de reden dat het niet werkt. Het systeem blijft hangen in KLOK. Daar komt hij als uit als TF0 hoog wordt, maar de timer wordt elkens opnieuw gestart, dus dan kun je lang wachten.

Op 18 augustus 2016 09:20:17 schreef S-man:
als ik het uittest, dan komt deze melding

Simulator warning:

UART: Frame discarded (according to MCS-51 manuel)
PC: 0x62
Line: 26
File: Suys Sören klok.asm

als ik die $ vervangt met KLOK, dan blijft hij in eeuwige lus bewegen. Wat moet ik dan aanpassen?

En ook mijn looplicht marcheert maar half, alles gebeurt op 1 lamp. Hoe lost ik dat op? Moet ik een extra code aan toevoegen of iets anders?

En ook mijn looplicht marcheert maar half, alles gebeurt op 1 lamp

Dat klopt toch ook? Je stuurt maar 1 lamp aan (die links/rechts gaat...)

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

In mijn oefening staat bij even minuten een linkslopend licht en bij oneven minuten rechtslopend licht. Ik dacht dat ik alle lichten moest gebruiken om deze beweging te maken. Zou ik dan 1 lamp gebruiken of allemaal? En welke code moet ik dan gebruiken om ze allemaal te laten lopen?

Wat bedoel je met 'ze allemaal laten lopen?' (ze lopen ook allemaal, maar wel 1 tegelijk)

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

Timer 0 configureer je als mode 2 (auto reload), wat goed is.

Echter, wat jij doet in routine klok is
1. je stopt, steeds keer op keer, de timer0 met het commando CLR TR0, wat niet logisch is. TR0 staat voor 'timer run'
2. je overschrijft steeds de TL0 en TH0 registers waardoor je in een eeuwige lus blijft.
3. logischerwijs zijn TL0 en TH0 gelijk aan elkaar (hoef je maar 1 keer te configureren)

Zie bijlage hoe een (atmel) auto reload timer werkt.

Bron: http://www.atmel.com/images/doc4316.pdf

ik heb mijn waarden van TL0 en TH0 gelijkgesteld aan 37h. Maar ik had echt gedacht dat mijn looplicht bij even minuten gedurende die minuut altijd naar links zou bewegen en bij oneven minuten altijd naar rechts beweegt gedurende die minuut.

Zo dacht ik hoe de programma zou moeten werken.

Op 18 augustus 2016 14:45:13 schreef kohen:
Timer 0 configureer je als mode 2 (auto reload), wat goed is.

Echter, wat jij doet in routine klok is
1. je stopt, steeds keer op keer, de timer0 met het commando CLR TR0, wat niet logisch is. TR0 staat voor 'timer run'
2. je overschrijft steeds de TL0 en TH0 registers waardoor je in een eeuwige lus blijft.
3. ten derde moet TL0 en TH0 gelijk aan elkaar zijn (hoef je maar 1 keer te configureren)

Zie bijlage hoe een (atmel) auto reload timer werkt.

Bron: http://www.atmel.com/images/doc4316.pdf

In principe maakt het toch niet uit dat hij in een eeuwige lus blijft? Het is toch een klok? Maakt niet zoveel uit dan toch? IK zit met hetzelfde herexamen, dus ik probeer hier wat op te steken.
In verband met het looplicht moet er toch nog een lus met een timer inkomen niet? nu schuift hij maar elk minuutje 1 bit op, en dat wordt dan terug gecleard. waardoor alleen bit P0.0 en P0.7 verwisselen en je geen looplicht hebt.
In verband met het routine klok:
1) Bedoel je dan dat timer0 dan noiit gestopt moet worden aangezien hij 'n autoreload is?
2) die bits kunnen geset worden bij start, juist?
3) Is dat noodzakelijk dat deze aan elkaar gelijk zijn? En hou maak je deze dan gelijk? In verband met de configuratie mag die dan ook al bij start gebeuren?
Groeten en alvast bedankt voor alle hulp,
T

Dit topic is gesloten