PIC One Second algoritma iz rimskega Black

B

BlackOps

Guest
Pozdravljeni, mislim večina od vas verjetno videl to spletno stran:
http://romanblack.com/one_sec.htm

je o tem, kako bi točno 1 sekundo zamudo na PIC uporabo interrupts.

ampak moja naloga je, absolutno jaz dont razumeti bistvo tega algoritma.
Tukaj je delček kode:

izjavlja, tri spremenljivke, in jim dodeli vrednosti:
(v decimalni) bres_hi = 15, bres_mid = 66 1, bres_lo = 64to je narejeno v setup rutinsko, ki traja le enkrat:
Code:movlw 0x0F

movwf bres_himovlw 0x42 1

movwf bres_midmovlw 0x40

movwf bres_lo

 
Sumim, ki jih uporablja za pridobivanje 0 timer interrupts.Timer 0 je binarni števec, z ali brez prescaler.Brez prescaler korakih je vsako navodilo, cikel, ki je na 1 / 4 frekvence oscilatorja.Zdi se, kot da se ne naložijo TMR0 s čimerkoli.
Tako boste dobili prekinitev vsakih 256 navodila ciklov.Glede na dejanske frekvence oscilatorja lahko to pomeni različnih časovnih intervalih.Torej morate Zmanjšanje ustrezno izbrana za dosego konstantno 1 sekundo.

Na primer, lets 'prevzeti oscilatorja je 4MHz.To pomeni, TMR0 ura je 1MHz, ali pa vsak 1 povečanji nas.Nato je preplavljena in ustvarja prekinitev vsakih 256 us.Nato, za pridobitev 1 sekunde, morate videti 1s / 256us = 3906,25 TMR0 prekinitve.Nato na 4MHz, da bi se vaš stalen, 3096.
Ampak, če oscilatorja teče na, recimo, 3,6864 MHz, potem morate stalno ustrezno prilagoditi.

Osebno, ko rabim kaj takega, sem pre-obremenitev TMR0 z nekaj več, tako da dobite lepo okrogla številka, torej prekinitev vsakih 250us.Potem vaš konstanta je krog 4000.Tudi če to ni tako lepo število, vsaj boste morda lahko za odpravo ali zmanjšanje delno del.Upoštevajte, da original konstanta je 3.096,25.Ti dejansko izgubili, če ,25 konstanta je 3096, kar pomeni, ne boste dobili točno 1s, kot ste zahtevek.

Za 4MHz primeru, da bi morali pred obremenitev TMR0 s 6, ker ga želite odstraniti 6 šteje od nje (se spomnite, da s povečanji in povzroči prekinitev, ko je prevrne 255-00, to je 256 točk, tako da boste želeli izgubiti 6 in tako pre-load counter with 6).
Vendar pa TMR0 ne povečuje za dva cikla, ko pišete na to in ker je pre-loading to pomeni, da je pisanje, vam bo "korist" dodatna 2 šteje.Zato bi morali pr obremenitev z 8 in ne 6.
V additon, ker ste prednaložil časovnik prekine v rutinskih, bo izgubil nekaj časa, dokler ne prideš do dejanske TMR0 movwf navodil (ozadje varčevanje, itd), tako da število je treba prilagoditi zaradi upoštevanja teh navodil .

Če uporabljate vnaprej Scaler, ki jih lahko uporabil bodisi TMR0 ali WDT, potem izračun spremembe, ki temeljijo na pred-Scaler delilnika razmerja, ki jih lahko izberete v S / W.

Običajno uporabljam samo naravnost binarne številke za konstante, saj lahko šele raba decfsz navodila Zmanjšanje konstantna.In če potrebujete več kot 1s, potem bo stalno večji.

Jaz upanje to pomoč.

 
VVV mimo ur delovno mesto pomočnik mi malo.... in da je program res ne 1 sec.ok, vendar pa problem ni to.

hočem storiti ročno EXACT eno sekundo zamude PIC16F88 program na čipu.z uporabo TMR0 prilagajajo.

i pisal kodo.šele to doesnt dela pravilno.Tu je moj izračun:Delay = (4 * 2 * 100 * 100 * 50) / 4 000 000 = 1,000 000 drugo
1 second

tako u vidite tukaj moram zaslužiti EXACT
1 sekundo

tako da zdaj vidite, jaz iz Prescaler na 1:2, bi TMR0 count vsakih 100-krat.in ustvarjanje dveh spremenljivk, count = 100, in count2 = 50
Zdaj mora dobim 1 sekundo ....VENDAR, moj code doesnt dela dobro, in jaz zaslužiti: 0.076510 sekund
To ni pravi ...moči kdorkoli reči mi, zakaj delati jaz zaslužiti to vrednost?če je moja napaka?
kako je i svoj remake kodo za 1 sec?

No, in tukaj je moja koda, ki daje napačen rezultat

Code:;************************************************* **********************************

;

;

;

;

;************************************************* **********************************# include <p16F88.inc>__CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_ON & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO
RESET_ADDR EQU 0x00

ISR_ADDR EQU 0x04

COMRAM_ADDR EQU 0x70CBLOCK COMRAM_ADDR

status_temp

w_temp

count; prvi count spremenljivka

count2; drugi count spremenljivka

ENDCORG RESET_ADDRSTART

goto SETUP

ORG ISR_ADDR;************************************************* **********************************

; ZAČETKA prekine SERVIS REDNO

;************************************************* **********************************

Prekinitev
movwf w_temp

swapf STATUS, w

movwf status_temp;
movf count, w, premaknite štej do w

xorlw b'00000000 '; XOR dobesedno s wbtfss STATUS, 2, če je število iz nič, potem preskočite naslednjo pouk

decfsz count, f, Zmanjšanje števila, izstop ISR če število iz nič

goto count2dec

goto INTEXITcount2dec:

movf count, w, premaknite štej do w

xorlw b'00000000 '; XOR dobesedno s wbtfsc STATUS, 2; preskočite naslednjo navodil, če število ni 0

decfsz count2, f, Zmanjšanje count2, Turn On / Off LED, če nič

goto INTEXIT
movlw b'10000000 "

xorwf PORTB, fmovlw ,100

movwf count

movlw ,50

movwf count2movlw ,158; TMR0 mora računati 100-krat, zato mora imeti na začetku 156

movwf TMR0; pa lahko traja 2 ciklov, navodilo za pisanje na TMR0, zato sem dal tam 158INTEXIT

BCF STATUS, 2; obračun Z bit v STATUS, mislim, da mora delati to?

BCF INTCON, TMR0IFswapf status_temp, w

movwf STATUS

swapf w_temp, f

swapf w_temp, w
retfie

;************************************************* **********************************

; KONEC prekine SERVIS REDNO

;************************************************* **********************************;************************************************* **********************************

; ZAČETKA SETUP REDNO (traja le enkrat)

;************************************************* **********************************

SETUP

banksel OPTION_REG

; Movlw 0xc7

movlw 0xC0; prescaler je 1:2

movwf OPTION_REGbanksel TRISB

movlw b'00000000 "

movwf TRISBbanksel PORTB

clrf PORTBbanksel OSCCON

movlw b'01100000 "je; biti 4 MHz

movwf OSCCONbanksel INTCON

clrf INTCONmovlw ,100

movwf count

movlw ,50

movwf count2movlw 0xe0

movwf INTCONmovlw ,158; TMR0 mora računati 100-krat, zato mora imeti na začetku 156

movwf TMR0; pa lahko traja 2 ciklov, navodilo za pisanje na TMR0, zato sem dal tam 158;************************************************* **********************************

; KONEC SETUP REDNO

;************************************************* **********************************;################################################# ##################################

; GLAVNI PROGRAM START

;################################################# ##################################

MAINLOOP

nop

nop

nop

goto MAINLOOP

;################################################# ##################################

; GLAVNI PROGRAM END

;################################################# ##################################END
 
Najprej 4MHz INTOSC ni ravno 4MHz.To ni dobro za uro realnem času, ampak je dovolj dober za serijsko komunikacijo.
To je 1% umerjen 23c pri sobni temperaturi in se bo spremenila svoje hitrosti, odvisno od temperature.

Potrebovali boste kristalno dobiti kjerkoli v bližini ure natančnost.

Prav tako preuči, ali z uporabo TMR2 CCP1 posebne prekiniti, ker so veliko bolj prilagodljiv kot TMR0

 
Najprej, če boste morali test register, če je nič, vi šele potreba uganjati movf reg, f in nato preskus Z zastavo, vam ni treba, da xor z w.Ampak zakaj se to sploh, Ince decfsz ne za vas?

Mislim, da problem s kodo je, da ne boste ponovno naložite števec 1, ko doseže nič.To je, kako bi jaz naredil:
Code:decfsz count, f

goto intexitmovlw xxxx; reload count tukaj

movwf count

decfsz count2, f

goto intexitmovlw xxxx; reload count2 tukaj

movwf count2, in tukaj si osvežite TMR0, stori, kar morate storiti, itd, ker 1 sec je pretekel.

 
: i was measuring time in MPLAB SIM.

blueroomelectronics:
i je merjenje časa v MPLAB SIM.ampak mimo za nasvet bom vzeti v razpisu za prihodnje modele.
: well that was much more helpful!

VVV:
dobro, da je bilo veliko bolj koristno!hvala!ampak jaz še vedno so nekatere manjše težave.
imam remaked ISR code fragment, kot si rekel (mimogrede, v moji rutinsko sem imel 100 50, ne 100 * 50 formulo ...).In potem sem tudi invalidi obračun registra INTCON pri rutinskih SETUP ...ker se s tem kosom kode sem imel vedno 0 v TMR0.

Torej ... nekako, zdaj jaz zaslužiti več 1.279999 sekund ...Še vedno ni 1,000 000 sekund.

zdaj so moje štetje in count2 spremenljivk OK ...potem ...?kaj je mogoče drugega problem?

morda kaj narobe s TMR0 pisanje?(kot u glej delam močjo 158, cuz izgube 2 ciklov med pišite na TMR0 ... kot je dejal v Midrange priročnik)

preverite, če delam pravilno?in je normalno, da jasno TMR0IF bit v kodo INTEXIT?

Tu je polno kodo:
Code:;************************************************* **********************************

;

;

;

;

;************************************************* **********************************# include <p16F88.inc>__CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_ON & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO
RESET_ADDR EQU 0x00

ISR_ADDR EQU 0x04

COMRAM_ADDR EQU 0x70CBLOCK COMRAM_ADDR

status_temp

w_temp

count; prvi count spremenljivka

count2; drugi count spremenljivka

ENDCORG RESET_ADDRSTART

goto SETUP

ORG ISR_ADDR;************************************************* **********************************

; ZAČETKA prekine SERVIS REDNO

;************************************************* **********************************

Prekinitevmovwf w_temp

swapf STATUS, w

movwf status_temp;decfsz count, f, Zmanjšanje števila, izstop ISR če število iz nič

goto INTEXITmovlw ,100

movwf countdecfsz count2, f, Zmanjšanje count2, Turn On / Off LED, če nič

goto INTEXITmovlw ,50

movwf count2movlw ,158; TMR0 mora računati 100-krat, zato mora imeti na začetku 156

movwf TMR0; pa lahko traja 2 ciklov, navodilo za pisanje na TMR0, zato sem dal tam 158movlw b'10000000 "

xorwf PORTB, fINTEXITBCF INTCON, TMR0IFswapf status_temp, w

movwf STATUS

swapf w_temp, f

swapf w_temp, wretfie

;************************************************* **********************************

; KONEC prekine SERVIS REDNO

;************************************************* **********************************;************************************************* **********************************

; ZAČETKA SETUP REDNO (traja le enkrat)

;************************************************* **********************************

SETUP

banksel OPTION_REG

; Movlw 0xc7

movlw 0xC0; prescaler je 1:2

movwf OPTION_REGbanksel TRISB

movlw b'00000000 "

movwf TRISBbanksel PORTB

clrf PORTBbanksel OSCCON

movlw b'01100000 "je; biti 4 MHz

movwf OSCCON; Banksel INTCON

; Clrf INTCONmovlw ,100

movwf count

movlw ,50

movwf count2movlw 0xe0

movwf INTCONmovlw ,158; TMR0 mora računati 100-krat, zato mora imeti na začetku 156

movwf TMR0; pa lahko traja 2 ciklov, navodilo za pisanje na TMR0, zato sem dal tam 158;************************************************* **********************************

; KONEC SETUP REDNO

;************************************************* **********************************;################################################# ##################################

; GLAVNI PROGRAM START

;################################################# ##################################

MAINLOOP

nop

nop

nop

goto MAINLOOP

;################################################# ##################################

; GLAVNI PROGRAM END

;################################################# ##################################END

 
Nisem prepričan, zakaj, ampak problem v simulatorju zdi, da je neuspeh pri pisanju od 158 do notranjosti TMR0 prekinitve storitev rutinsko.

s spoštovanjem

 
narccizzo ... NO, lahko MPLAB SIM ročaj prekinjajo, ampak v načinu izvajanja, ki niso v debug načinu, in jaz vidim RBx rezultatov s čipom na diagramu ..jaz tudi preizkušen to v PROTEUS.enak rezultat.

tako da problem je nekje v TMR0 ponovnega nakladanja ...ampak kaj točno je narobe ...?

 
Vidim problem z TMR0: morate, preden boste reload Zmanjšanje števci, sicer bo samo še štetje, prevrnitvi za nič, itd le še enkrat naložen vsakič pulti doseže nič, kar ni, kaj si hoteti.

Zdaj stvar je, da sem se potrudil teče kodo v simulatorju, vendar iz neznanega razloga TMR0 ne dobi naložen in ga incrments vsako navodilo cikel, namesto da bi vsak drugi.Mislim, da je to samo problem simulatorja.Če premaknete TMR0 pretovarjanje kodo tik pred decrementing števce, bi bilo delo.

In ja, morate jasno TMR0IF preden zaprete ISR, ali pa boste takoj začeti znova, saj le mikro testov zastave in ustrezno ukrepa.

Ena stvar, da preverijo: kot se spomnim, TMR0 ne zaslužiti poveča za 2 ciklov navodil samo, če je prescaler nastavljena na 1 ali dodeljeni WDT.Mislim, da izjava nanaša na celotni 16-bitni števec, TMR0 prescaler, tako da vam ni potrebno reload TMR0 z 158, ampak 157, ker je vaša prescaler je 1:2, tako izgubili dve navodila ciklov pomeni 1 izgubil šteje v TMR0.

 
,thanks for reply again.

VVV,
hvala za odgovor še enkrat.vendar to še doesnt opus ...

kaj sem storil je, jaz premakne ta del kode:
movlw ,157
movwf TMR0

pred decrementing count spremenljivka v ISR.

in jaz tudi dodeljena ,157 za TMR0 v rutinskih SETUP ...

zanimiva stvar je, rezultat je bil isti 1.279999 sekund ...to didnt zadevo did i obremenitve ,157 ali ,158 v TMR0 tako v SETUP in ISR ...ali sem obremenitve oba z ,157, rezultat je bil enak 1,279999 ZAKAJ?svoj zelo čudno ...in moj stil code doesnt delo, jaz vekanje zaslužiti eno sekundo.

rečeš i mora obremenitev TMR0 z 1 .. Nne N 2, ampak v srednji segment priročnika Microchip, v oddelku za Timer0 pravijo, da je jaz obremenitev z N 2 ...

Ampak kot sem povedal že prej, to didnt zadevo sem vstavite tako, da n 1 n 2 ali sem imel enak rezultat narobe ...hmm ... čudno, any ideas?

ps sem bil merjenja časa, tako v PROTEUS in MPLAB SIM.dve stvari ne moremo biti narobe

<img src="http://www.edaboard.com/images/smiles/icon_smile.gif" alt="Nasmeh" border="0" />

Dodano po 1 ur 22 minut:dobro dobro ...

Zdaj sem opazil zanimive stvari.in front of every operation with TMR0.

imam dal banksel TMR0
pred vsako operacijo z TMR0.
in sem storil obremenitev TMR0 z ,156 tako v ISR in SETUP.

Rezultat je bil: 1,055 000 sekundPotem sem se odločila, da bo povratni izračun in ugotoviti, katero število ne TMR0 za štetje.1,055 000 = (4 * 2 * X * 5000) / 4 000 000 ===> X = 105,5Sprašujem se, zakaj jaz didnt zaslužiti celo število številko?
tako da ... TMR0 je štetje za 105,5 ...potem to pomeni, jaz sem izgubila 5,5 ciklov ..
potem to pomeni, da mora i reload TMR0 z 156 5,5?zdi tako, vendar ni možno.
torej si se potrudil, da osvežite TMR0 z 156 6, 162 ali ...

ter sem storil zaslužiti rezultat: 0.995000 sekund.OK, vse zamisli zdaj?

<img src="http://www.edaboard.com/images/smiles/icon_biggrin.gif" alt="Very Happy" border="0" />
 
Bom razložil v kratkem članku teorije in metode za 4 do natančnosti RTC uporabo PIC in zunanji oscilator.Prav tako vključen zero-sum/zero Roman Black kumulativna napaka metode ..., ki deluje zelo dobro.

4 Metode Za Precision PIC RTC uporabo Mečarica Basic

4 Metode Za Precision PIC RTC uporabo mikroBasic

 
OK, šele zdaj sem obvestilo, da si ne delajo nič, v banki v glavni zanki
Kakorkoli že, moja napaka: dodamo clrf STATUS, takoj po varčevanju kontekstu.To vas bo pripeljala do bank 0.

Kot je za polnjenje TMR0, morate upoštevati zamude prekine (2 ciklov mislim), plus varčevanje okvir (3 cikli), plus clrf STATUS, plus reload TMR0 navodila (2 ciklov), plus odlašanja začne TMR0 na prirast (2 ciklov).
To je skupaj 10 ciklov.I natovorjen TMR0 s 166 in prekinjajo pojavi na 100us.

Stvar s 0,5 ciklov, se lahko reši z dodajanjem nop pred ponovnega TMR0.Ker ste uporabili 1:2 prescaler, dodatni pouk bo štela kot 1 / 2 cikla.V tem primeru clrf STATUS did delo.

Code:prekinitevmovwf w_temp

swapf STATUS, w

movwf status_temp;clrf STATUS

movlw ,166; TMR0 mora računati 100-krat, zato mora imeti na začetku 156

movwf TMR0; pa lahko traja 2 ciklov, navodilo za pisanje na TMR0, zato sem dal tam 158decfsz count, f, Zmanjšanje števila, izstop ISR če število iz nič

goto INTEXITmovlw ,100

movwf countdecfsz count2, f, Zmanjšanje count2, Turn On / Off LED, če nič

goto INTEXITmovlw ,50

movwf count2
movlw b'10000000 "

xorwf PORTB, fINTEXITBCF INTCON, TMR0IFswapf status_temp, w

movwf STATUS

swapf w_temp, f

swapf w_temp, wretfie

 
Uporaba prescaler bo zagotovo povzročilo napake natančnost in čas.Morate vzdrževati 1:1 timer delovanje za doseganje RTC natančnost.

 
, thank you, every your reply helps.

VVV,
hvala, vsak vaš odgovor pomaga.pa še jaz didnt zaslužiti 1.000.000 sekund ur novo kodo tako ...
delam zaslužiti 0,955 sekunde!tudi jaz ne svoboden 45000us, kje in zakaj?

i prednapetost TMR0 z ,176 v rutinskih SETUP in ISR je kot u mi je pokazala ...in sem dobil zamude 0,955 sekunde!Še vedno je nekaj narobe!

vendar to doesnt zadevo zdaj kaj naredim preload TMR0 v rutinskih SETUP z ...isto 955000us zamude ...kje sem svoboden 45000us?

prosim pomoč miDodano po 2 uri 4 minute:No dobro ..
V zadnjem sem storil to.pustiti mi prvi post moj končno kodo, ki omogoča točno eno sekundo, v skladu z MPLAB SIM.Tukaj je:DELOVNI KODEKS EXACT 1 DRUGEGA DELAY USING Timer0 MODULE IN prednapete OF TMR0Code:;************************************************* **********************************

; Program:

; Avtor:

; Processor: PIC16F88

; Opis:

, To je program za predstavitev točno eno sekundo zamude z

, Prekine in Timer0 module.
Splošna formula za izračun zamudo, je:

; ************************************************* **************************

; * Delay = (4 * Prescaler * (256 - TMR0) * count * count2) / Crystal Freq.
*

; ************************************************* **************************

; V našem primeru smo preload TMR z vrednostjo, ki omogoča štetje do 100.

; Izberite prescaler 1:2

, In določite vrednosti 100 in 50 za štetje in count2 oziroma

, Potem smo natanko eno sekundo:

; 1 sekunda = (4 * 2 * (256-156) * 100 * 50) / 4 000 000

;************************************************* **********************************
# include <p16F88.inc>__CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_ON & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO
RESET_ADDR EQU 0x00

ISR_ADDR EQU 0x04

COMRAM_ADDR EQU 0x70CBLOCK COMRAM_ADDR

status_temp

w_temp

count; prvi count spremenljivka

count2; drugi count spremenljivka

ENDCORG RESET_ADDRSTART

goto SETUP

ORG ISR_ADDR;************************************************* **********************************

; ZAČETKA prekine SERVIS REDNO

;************************************************* **********************************Prekinitevmovwf w_temp; Saving kontekstu

swapf STATUS, w

movwf status_temp;nop, ampak jih uporabljamo za odpadke 0,005 sekunde, drugače bomo dobili zamudo 0,995 sekunde

banksel TMR0

movlw ,162; TMR0 mora računati 100-krat, zato mora imeti na začetku 156

movwf TMR0, vendar imamo tudi drugi cikli, ki izgubimo zato moramo dodati, da tudi TMR0

; Teh ciklov so:

; Kontekst varčevanja - 3

; TMR0 obremenitve - 2

; Banksel zapoved - 1decfsz count, f, Zmanjšanje števila, izstop ISR če število ni nič

goto INTEXIT, če število ni nič skip INTEXIT, in ponovno z ,100 spet

movlw ,100

movwf countdecfsz count2, f, nato Zmanjšanje count2, izstop ISR če count2 ni nič

goto INTEXIT, če count2 nič, preskočite INTEXIT in osvežite z ,50 spet

movlw ,50

movwf count2movlw b'10000000 '; stikalo pin PORTB

xorwf PORTB, fINTEXITBCF INTCON, TMR0IF; Clearing TMR0IF po izstopu iz ISRswapf status_temp, w; Obnavljanje kontekstu

movwf STATUS

swapf w_temp, f

swapf w_temp, wretfie

;************************************************* **********************************

; KONEC prekine SERVIS REDNO

;************************************************* **********************************
;************************************************* **********************************

; ZAČETKA SETUP REDNO (traja le enkrat)

;************************************************* **********************************SETUP

banksel OPTION_REG

movlw 0xC0; Prescaler je 1:2

movwf OPTION_REGbanksel TRISB; PORTB je vse nastavljeno na Output

movlw b'00000000 "

movwf TRISBbanksel PORTB; obračun PORTB

clrf PORTBbanksel OSCCON

movlw b'01100000 '; 4MHz oscilator frekvence izberite

movwf OSCCONmovlw ,100; assing vrednosti za štetje spremenljivk

movwf count

movlw ,50

movwf count2movlw 0xe0; GIE = 1, PEIE = 1, TMR0IE = 1

movwf INTCONbanksel TMR0; sprva jasno TMR0, čeprav se njegova ni potrebno

clrf TMR0;************************************************* **********************************

; KONEC SETUP REDNO

;************************************************* **********************************;################################################# ##################################

; GLAVNI PROGRAM START

;################################################# ##################################MAINLOOP

nop

nop

nop

goto MAINLOOP;################################################# ##################################

; GLAVNI PROGRAM END

;################################################# ##################################END

 
in še ena stvar!VVV si imel prav!Roman Black ni dobil TOČNO ene sekunde!i meri njegove zamude z MPLAB SIM, in to mi je pokazala zamude 1.000192 sekund!dont vedeti, če je nekdo drug naredil isto?Potem sem končno meri svoj program in ga ni dala 1.000.000 zamudo.

 
in eno vprašanje o moji končni program, kot veste, jaz dont zaslužiti zamudo 1.000.000 sekund v MPLAB SIM.ampak v PROTEUS, z uporabo orodja COUNTER delam zaslužiti zamude 1.005.000 sekund, ZAKAJ?

Vendar pa, če jaz premestitev NOP iz ISR pred TMR0 prednapete, delam zaslužiti 1.000.000 drugega zamudo pri PROTEUS, potem pa delam zaslužiti 0.995.000 sekund v MPLAB SIM.heh ...zakaj je tako?poljuben umislek?

 
Možno je, da MPLAB ne simulirati 2-cikel zamudo, potrebnih za podružnice Pobeg Vektor.Nisem 100% prepričan o tem, četudi.
Ko se vam bodo dejansko vezje, boste lahko izmerili zamude na pin.Konec koncev, končni cilj je priti ob pravem času v resničnem svetu.Če ne exaclty kaj ste pričakovali, vsaj veš, kaj storiti za odpravo težave.

 
Ko timer prescaler nastavljen na nekaj drugega kot 1:1 vas bo uvedel nekaj napak, ki ga ne more nadomestiti, tudi z uporabo metode Roman Black's.

have a 1:1 Timer to Tosc ratio to build an accurate time base.

Imeti
morate 1:1 Timer v razmerju do Tosc za izgradnjo natančne časovne baze.

 
Problem pri pisanju "trdo" vrednost za TMR0 register je, da lahko pride do 1 cikel "trepetanju ', ki vstopajo v ISR, ko overflow Timer 0' prekiniti pride med ciklom 1 ali 2 cikla pouk v vašem MAIN program.

your 'reload' value to TMR0.

Boljša rešitev bi bila, da dodate
"reload" vrednost za TMR0.

Drugo opozorilo je, da bo pisno TMR0 jasno prescaler nered, ki bi lahko svoj čas, tako da boste verjetno želeli ohraniti v razmerju 1:1 nastavitev prescaler.To omejuje, da ne prekinejo kratkih časovnih presledkih, vendar sem prepričan, da lahko še vedno prišli do izvedljivo rešitev.

Če bi jaz moral uporabiti Timer 0 za RTC "srčni utrip", namesto Timer 2, bi jaz naredil kaj takega (nepreverjeno code);

Vso srečo pri vašem projektu.Mike

Code:

;************************************************* *****************org 0x0004

;

; Shranite glavni program kontekstu

;

ISR_Proc

movwf W_ISR, razen W-reg | B?

swapf STATUS, W; ne spreminja STATUS bits | B?

movwf S_ISR; shranite STATUS reg | B?

clrf STATUS; banke 0 | B0

movf PCLATH, W; zaslužiti PCLATH | B0

movwf P_ISR; shranite PCLATH | B0

clrf PCLATH; ISR je v banki 0 | B0

;

; Prep TMR0 prekinitve za naslednji cikel in Čvoruga 1 sekundo counters

;

movlw-d "250", 2, vrednost za 250-usec interrupts | B0

addwf TMR0, F; reload TMR0 za naslednjo prekinitev | B0

decfsz RTCL, F; counter lo 0?
ja, skip, drugi | B0

goto ISR_Exit; izstopa ISR | B0

decfsz RTCH, F; hi counter 0?
ja, skip, drugi | B0

goto ISR_Exit; izstopa ISR | B0

;

; Reload 1 sekundo counters

;

movlw nizka (d'4000 '); osvežite naše 1-drugi števci | B0

movwf RTCL; | B0

movlw visoka (d'4000 ') 1; | B0

movwf RTCH; | B0

;

; Opravljajo naši enkrat na sekundo rutino tukaj

;

nop; | B0

;

; Ponovno glavni program kontekstu

;

ISR_Exit

BCF INTCON, TMR0IF; jasno TMR0 prekinitev zastava bit | B0

movf P_ISR, W; | B0

movwf PCLATH; obnoviti PCLATH | B0

swapf S_ISR, W; | B0

movwf STATUS; obnoviti STATUS | B0

swapf W_ISR, f; ne screw up STATUS | B0

swapf W_ISR, W, obnoviti W-reg | B0

retfie; vrnitvi iz prekinitev | B0;************************************************* *****************
 
Tukaj je nekaj, kar sem napisal nekaj časa nazaj za mikroBasic za forume PIC.To je koda pokazati, kako doseči natančnost baze PIC čas.

Interrupts so potrebne za točno program RTC.Interrupts bi bilo mogoče ustvariti natančno časovno bazo s skoraj unnoticable učinke na program kot celoto.

The issue with interrupts is the code overhead of saving important registers before getting to the programmer's interrupt code, such as reloading the timer and preparing for the next interrupt cycle. Timers rollover to zero which creates the interrupt but then continue running for several cycles before the programmer gets a chance to reload it. Often it is difficult to predict the length of time that the timer has continued to run before reloading it with a fixed time value. That value must be adjusted somehow. The examples below are intended to show how to compensate for this "lost" time with some clever software techniqes and methods.

About the methods. The first 2 programs utilize the Zero-Sum, or Zero Cumulative Error, method for maintaining accurate time. It's essentially a method of reloading a timer and automatically compensating for ISR code overhead by adding
to the existing timer value. Remember that timers increment, count up, to rollover, or 0. If you add to their value you are actually shortening their trip to 0. So we can compensate for cycles unaccounted for by adding to the timer's value. It's too much to explain further here but is well explained by ROMAN BLACK on his webpage:

http://www.romanblack.com/one_sec.htmThe last 2 are period based free running timer methods using PR2 with Timer2 and Special Event Feature of Timer1 and the CCP1 module. Both methods automatically reset the timer when the values in PR2 and CCPR1 registers match their respective timer.

Each program was tested on a 18F452 @ 8MHz. The programs can also be used with PIC16's with a few changes. All source-code will compile with the free demo version of the compiler. I have added code to each program method to demonstrate a 24 Hour Time Clock output on a 2 line LCD.

TIMER1 - Zero-Sum with Timer Stop Method

Code:

program RTC_Timer1_18F452

' 24 Hour Real Time Clock - Zero-Sum Timer Stop Method
' mikroBasic 5.02 ... 18F452 @ 8MHz Default Configuration
' Uses Timer1; No Prescaler; 2 counts per microsecond
' Add 6 cycles for Timer1 stop, reload, and restart in ISR dim T1 as word absolute $FCE              ' Timer1 Low and High
dim T1_Period as word                     ' Timer1 reload value fudge factor
dim int_count as byte                     ' interrupt counter
dim update as boolean                     ' update output
dim secs, mins, hrs as byte               ' tally variables
dim clk as string[9] absolute $20         ' output string for LCD
dim hstr as string[3] absolute $20
dim mstr as string[3] absolute $23
dim sstr as string[3] absolute $26

sub procedure interrupt
T1CON.TMR1ON = 0                       ' stop Timer1
T1 = T1 T1_Period                    ' reload Timer1 zero-sum error
T1CON.TMR1ON = 1                       ' start Timer1
If inc(int_count) = 40 Then            ' 40 counts x 25000us = 1sec
int_count = 0                       ' restart interrupt counter
update = true                       ' advance seconds & update output
End If
PIR1.TMR1IF = 0                        ' clear interrupt flag
end sub

sub procedure Clock24
If inc(secs) = 60 Then                ' check each for rollover
secs = 0
If inc(mins) = 60 Then
mins = 0
If inc(hrs) = 24 Then hrs = 0 End If
End If
End If

bytetostr(hrs, hstr)                  ' create clock output string for LCD
If hstr[1] = 32 Then hstr[1] = 48 End If
bytetostr(mins, mstr)
mstr[0] = ":"
If mstr[1] = 32 Then mstr[1] = 48 End If
bytetostr(secs, sstr)
sstr[0] = ":"
If sstr[1] = 32 Then sstr[1] = 48 End If
LCD_CMD(130)
LCD_OUT_CP("24-HOUR CLOCK")
LCD_CMD(195)
LCD_OUT_CP(clk)
update = false
end sub

sub procedure Initialize
ADCON1 = 15
int_count = 0
secs = 255
mins = 0
hrs = 0
update = true
LCD_INIT(PORTB)
LCD_CMD(LCD_CURSOR_OFF)
INTCON.GIE = 1                         ' enable GIE
INTCON.PEIE = 1                        ' enable PEIE
T1_Period = -50000 6                 ' 25000us interrupt 6 cycles Timer1 reload
T1CON = 0                              ' no prescaler and Timer1 is Off
T1 = T1_Period                         ' load Timer1
PIE1.TMR1IE = 1                        ' interrupt enabled
PIR1.TMR1IF = 0                        ' interrupt flag cleared
T1CON.TMR1ON = 1                       ' start Timer1
end sub

main:
InitializeWhile true                             ' loop forever
If update <> false Then             ' advance seconds?
Clock24                          ' yes...then output
End If
Wend

konec.
 

Welcome to EDABoard.com

Sponsor

Back
Top