Toon posts:

Programmeren 89C52 microcontroller

Pagina: 1
Acties:

Verwijderd

Topicstarter
Voor mijn eindwerk (industrieel ingenieur) heb ik een robot gemaakt die een traject volgt, dat getekend wordt met behulp van de computermuis. Het programma waarin dit gebeurt, zendt bytes door naar de microcontroller, die beslist welke motor(en) moeten gestart worden, en hoelang. Ik heb de tijd gedurende de motoren moeten draaien steeds bepaald met behulp van timers. Ik heb nu echter encoders geïnstalleerd, en daarvoor moet ik dus het aantal 1-0 overgangen die de encoders genereren kunnen tellen en vergelijken met een bepaalde waarde in het register. Ik heb daarvoor de volgende subroutine geschreven. Het probleem is dat de motoren blijven draaien. Ik weet zeker dat de encoders naar behoren werken, en de subroutine zou in theorie ook moeten werken, maar ervaring leert me dat theorie en praktijk niet altijd overeenstemmen.

Ik vraag me dus af als er mensen zijn die een betere manier weten om een counter te vergelijken met een registerwaarde, en hem te doen stoppen als deze waarde bereikt is.

De subroutine is de volgende:
De waarde die moet bereikt worden zit eerst in de accu, en vervolgens wordt die ingelezen in het register R0. Deze waarde is dus nooit langer dan 8 bits, dus ze moet enkel vergeleken worden met de laagste byte van de 16-bit counter.


Tel_Links: clr C
mov TL0,#00h
mov TH0,#00h
mov R0,A
Tel_Verder_1: clr C
mov A,R0
subb A,TL0
JNZ Tel_Verder_1
ret


P.S. Sorry voor de nogal lange uitleg, maar ik moet het toch een beetje situeren hé. Als het topic in het verkeerde forum staat, gelieve het dan te verplaatsen.

Verwijderd

hmmmz heb alleen ervaring met een 86000 en 68HC11 dus als je mischien iets meer info heb over die registers enzo... of beetje commentaar derbij :)

Verwijderd

Topicstarter
Op zondag 16 juni 2002 20:29 schreef FURY het volgende:
hmmmz heb alleen ervaring met een 86000 en 68HC11 dus als je mischien iets meer info heb over die registers enzo... of beetje commentaar derbij :)
A=Accu (wist je wel waarschijnlijk :) )
R0= kladblokregister
TL0=laagste 8 bits van het 16 bit register van counter0
TH0=hoogste 8 bits van hte 16 bit register van counter0
C=carry bit
JNZ jump als de accu niet gelijk is aan 0

De rest zijn labels.

  • CyberSnooP
  • Registratie: Augustus 2000
  • Laatst online: 31-03 16:47

CyberSnooP

^^^^ schrijft --->

Op zondag 16 juni 2002 20:08 schreef Herdore1 het volgende:
Ik vraag me dus af als er mensen zijn die een betere manier weten om een counter te vergelijken met een registerwaarde, en hem te doen stoppen als deze waarde bereikt is.
Aangezien ik jouw microcontroller niet ken doe ik maar een gok. Is het niet mogelijk om de counter in een aftellende modus te zetten die bij 0 een interrupt genereert? Of er andere manieren zijn kun je echt het beste in de handleiding van je mircocontroller opzoeken.

|_____vakje______|


  • Harrie
  • Registratie: November 2000
  • Laatst online: 05-09 23:05

Harrie

NederVlaming

volgens mij is die Tel_Verder_1 code niet goed. Eerst wordt R0 in de Accumulator gezet. Vervolgens trek je TL0 daarvan af. Als het resultaat positief is, begin je opnieuw bij Tel_Verder_1.

Dus hij schrijft de onverandere waarde van R0 waar in A, en doet weer precies hetzelfde, en het resultaat is weer hetzelfde natuurlijk, dus weer positief...

Of begrijp ik het verkeerd :?

  • CyberSnooP
  • Registratie: Augustus 2000
  • Laatst online: 31-03 16:47

CyberSnooP

^^^^ schrijft --->

Op zondag 16 juni 2002 21:00 schreef philippi14 het volgende:
Dus hij schrijft de onverandere waarde van R0 waar in A, en doet weer precies hetzelfde, en het resultaat is weer hetzelfde natuurlijk, dus weer positief...
Uhh.. volgens mij wordt TL0 van buitenaf veranderd ook tijdens het lopen van deze lus.

|_____vakje______|


Verwijderd

Topicstarter
Op zondag 16 juni 2002 21:00 schreef philippi14 het volgende:
volgens mij is die Tel_Verder_1 code niet goed. Eerst wordt R0 in de Accumulator gezet. Vervolgens trek je TL0 daarvan af. Als het resultaat positief is, begin je opnieuw bij Tel_Verder_1.

Dus hij schrijft de onverandere waarde van R0 waar in A, en doet weer precies hetzelfde, en het resultaat is weer hetzelfde natuurlijk, dus weer positief...

Of begrijp ik het verkeerd :?
Nee, want de inhoud van de counter wordt veranderd door een extern signaal.

Te laat :)

Verwijderd

hmm et id zou wel moete werke ja :)
kan ook niet zegge waar de fout zit, geen ervaring met de atmel intructieset...

Verwijderd

Topicstarter
Op zondag 16 juni 2002 21:26 schreef FURY het volgende:
hmm et id zou wel moete werke ja :)
kan ook niet zegge waar de fout zit, geen ervaring met de atmel intructieset...
Tja, ik weet het niet meer. Het is zo simpel dat het bijna belachelijk wordt. Ik denk dat ik ergens een conflict heb met twee interrupts, een soort race-probleem. Ik zal het moeten uitleggen aan de jury :'(

Toch bedankt allemaal.

Verwijderd

conflict met twee interrupts? zou je dan niet in je interruptroutine even de interrupts uitzetten?!

Verwijderd

Topicstarter
Op maandag 17 juni 2002 00:43 schreef zellufs het volgende:
conflict met twee interrupts? zou je dan niet in je interruptroutine even de interrupts uitzetten?!
heh? Waarom zou ik ze uitzetten? Als ik seriële communicatie wil, dan kan ik toch moeilijk mijn interrupt gaan uitzetten! Ik moet er gewoon softwarematig voor zorgen dat de twee interrupts (externe pin van timer 0 en de seriële poort) niet meer in elkaars vaarwater komen. Het probleem is dat dit nog heel wat denkwerk met zich mee zal brengen, en daar heb ik nu helaas de tijd niet meer voor.

Ik geef toe dat het woord conflict hier misschien verkeerd gekozen is. Ik zou eerder spreken over een ongelukkige wisselwerking tussen twee interrupts. Het zou namelijk kunnen dat tijdens, of net na, de afhandeling van de seriële interrupt (en dit is bijna continu) de test moet gebeuren als de counter de gevraagde waarde heeft bereikt. Ondertussen is de counter misschien weer met 1 verhoogd, zodat de test eigenlijk de gevraagde test niet meer is. Ik denk dat ik dus met een raceprobleem zit. Ik zou het allemaal eens moeten uitpluizen.

Verwijderd

Op maandag 17 juni 2002 02:14 schreef Herdore1 het volgende:

heh? Waarom zou ik ze uitzetten? Als ik seriële communicatie wil, dan kan ik toch moeilijk mijn interrupt gaan uitzetten! Ik moet er gewoon softwarematig voor zorgen dat de twee interrupts (externe pin van timer 0 en de seriële poort) niet meer in elkaars vaarwater komen. Het probleem is dat dit nog heel wat denkwerk met zich mee zal brengen, en daar heb ik nu helaas de tijd niet meer voor.
Dat denkwerk valt wel mee. Als je (zoals eerder genoemd) de interrupts uitzet aan het begin van de interrupt-routine en weer aan zet aan het eind van interrupt-routine kan er nooit een conflict ontstaan.

Stukje pseudo-code:
code:
1
2
3
4
5
Begin ISR: Zet interrupts tijdelijk uit

// Doe wat de ISR moet doen

Eind ISR: Zet interrupts weer aan

Of je moet je prioriteiten van je interrupts anders instellen.

Verwijderd

Twee puntjes:
  • Priority-niveau van de interrupts is aan te passen (zie registers IE, IP en IPH) en dus is het interrupt-niveau van de timer hoger te leggen.
  • Voor zover ik weet kan je de timers ook in een "terug-tel-mode" plaatsen. Hierdoor kun je hem laten reageren op een interrupt.
Dit zou heel het probleem volgens mij op moeten kunnen lossen :)

Verwijderd

Topicstarter
Op maandag 17 juni 2002 11:07 schreef bartm het volgende:
Twee puntjes:
  • Priority-niveau van de interrupts is aan te passen (zie registers IE, IP en IPH) en dus is het interrupt-niveau van de timer hoger te leggen.
  • Voor zover ik weet kan je de timers ook in een "terug-tel-mode" plaatsen. Hierdoor kun je hem laten reageren op een interrupt.
Dit zou heel het probleem volgens mij op moeten kunnen lossen :)
hmmm, ik zou het eens moeten bekijken, maar volgens mij voorziet de 8052 geen terugtelmode. Maar ik ben het niet zeker. Bedankt voor de tip

Verwijderd

Ik heb nog even in de datasheets gekeken en ik zie idd geen "terug-tel-mode" (dat zou er toch standaard in moeten zitten :?). Maar als je de priority-mode van timer 0 hoger maakt dan die van de uart zal dit verder ook geen probleem opleveren.
code:
1
2
3
// Interrupt priority T1 op hoogste niveau instellen.
IP |= 0x02;
IPH |= 0x02;

Probeer verder de ISR zo kort mogelijk te maken, maar dat is meestal niet zo'n groot probleem.
Pagina: 1