Frekvenčni generator z mikrokontrolerjem

Avtor: mag. Vladimir Mitrović

Po­glej­mo si naj­prej, kaj lah­ko do­se­že­mo s “stan­dar­dni­mi” za to na­me­nje­ni­mi Ba­scom ru­ti­na­mi. Gre za ukaz So­und, o ka­te­rem v Hel­pu pi­še na­sled­nje:

SO­UND pin, du­ra­ti­on, frequency
pin Ka­teri koli V/I pin, npr. P1.0
du­ra­ti­on Šte­vilo pul­zov, 1 - 32768
frequency Tra­ja­nje stanja 0” ali “1” na 
 iz­bra­nem pi­nu

Iz­bra­ni pin se za­dr­ži v sta­nju “0” ali “1” frequency mi­kro­se­kund. Zan­ka se iz­vr­ši du­ra­ti­on-krat.

To­da ni vse ta­ko, kot pi­še! Ana­li­zi­ra­li smo So­und ukaz ena­ko, kot to tu­di si­cer poč­ne­mo, ko ne­kaj “zaš­kri­pa”: pred in za uka­zom vpi­še­mo kak­šnih de­set “nop” uka­zov,

nop
...
nop
So­und P3.5 , 32000 , 1
nop
nop

na­kar dob­lje­no hek­sa ko­do pre­ve­de­mo in di­sa­sem­bli­ra­mo… re­zul­tat je pri­ka­zan v Ta­be­li 1.
Ta­be­la 1 pri­ka­zu­je sa­mo naj­po­mem­bnej­ši del ru­ti­ne; pre­sko­či­li smo uvo­dni del, v ka­te­rem se da­ni pa­ra­me­tri pre­ne­se­jo v re­gis­tre R6, R7 (du­ra­ti­on, šte­vi­lo im­pul­zov) ozi­ro­ma R2 (frequency, tra­ja­nje po­sa­mez­ne­ga sta­nja). Prav ta­ko ni pri­ka­zan pod­pro­gram na na­slo­vu 002E, v ka­te­rem pa­ra­me­ter du­ra­ti­on zma­njša­mo za 1. Po­glej­mo si po­dro­bne­je na­sled­nji seg­ment:

MOV R0,R2
SETB P3.5
DJNZ R0,*-0

Tu­kaj se naj­prej že­le­no tra­ja­nje iz re­gis­tra R2 pre­ko­pi­ra v R0 in po­sta­vi pin P3.5 v sta­nje “1”, na­to pa se vse­bi­na re­gis­tra R0 zma­njšu­je za 1 (DJNZ), vse do­kler ne po­sta­ne ena­ka 0. Iz te­ga lah­ko ta­koj opa­zi­mo bis­tvo pro­ble­ma: ker iz­ved­ba DJNZ uka­za tra­ja 2 tak­ta, je tra­ja­nje sta­nja “1” dva­krat da­ljše kot pi­še v Help-u! Če te­mu priš­te­je­mo še en takt, ki ga po­tre­bu­je­mo za iz­vr­ši­tev uka­za SETB, po­sta­ne na­pa­ka še ve­čja – če bi, kot smo to na­re­di­li v na­šem pri­me­ru, na­sta­vi­li pa­ra­me­ter frequency na 1, bi na­me­sto pri­ča­ko­va­ne 1µs sta­nje “1” tra­ja­lo ce­le 2 x 1 + 1 = 3 µs.

Na­da­ljuj­mo z ana­li­zo ko­de iz ta­be­le 1. Sle­di po­do­ben seg­ment, v ka­te­rem Ba­scom ge­ne­ri­ra “0”:

CLR P3.5
MOV R0,R2
DJNZ R0,*-0

Pro­blem je po­do­ben, le da se je tu­kaj po­ja­vil tu­di ukaz MOV, ki pov­zro­ča do­dat­no po­da­ljša­nje ome­nje­ne pol­pe­ri­o­de za 2 tak­ta. Ven­dar to še ni vse! Za uka­zom DJNZ sle­di še skok na za­če­tek zan­ke in kli­ca­nje pod­pro­gra­ma na na­slo­vu 2EH, v ka­te­rem se pre­ver­ja, ali je zan­ka iz­vr­še­na du­ra­ti­on-krat (ker gre za 16-bit­no šte­vi­lo, ne mo­re­mo upo­ra­bi­ti eno­stav­ne­ga DJNZ uka­za). To k tra­ja­nju pol­pe­ri­o­de pri­ne­se še do­dat­ne tak­te… v krat­kem: sta­nje “0” tra­ja dva­krat dlje + 16 µs, kar je ve­li­ko več, kot smo pri­ča­ko­va­li. Ker svo­ji ana­li­zi eno­stav­no ni­smo mo­gli ver­je­ti, smo ukaz So­und vpi­sa­li v zan­ko

Do
 So­und P3.5 , 32000 , 1
Lo­op

in opa­zo­va­li dob­lje­ni sig­nal z osci­lo­sko­pom. Na­me­sto pri­ča­ko­va­ne­ga sig­na­la fre­kven­ce 500 kHz, je osci­lo­skop po­ka­zal sig­nal fre­kven­ce oko­li 48 kHz (!), kot na sli­ki 1: sta­nje “1” je tra­ja­lo 3 µs, sta­nje “0” pa ce­lih 18 µs, toč­no ta­ko, kot je po­ka­za­la ana­li­za. Mo­ra­mo pa po­ve­da­ti, da gre za naj­slab­ši mož­ni pri­mer – če bi fre­kven­co zma­njše­va­li, bi bi­la asi­me­tri­ja sig­na­la vse ma­njša in ma­njša (ven­dar bi še na­prej ob­sta­ja­la raz­li­ka med tra­ja­njem “1” in “0”), fre­kven­ca pa bi po­sta­la ena­ka pri­bliž­no po­lo­vi­ci za­da­ne. Ukaz So­und to­rej pro­iz­va­ja ne­kak­šen sig­nal, na či­gar fre­kven­co lah­ko vpli­va­mo z nje­ni­mi pa­ra­me­tri, ven­dar pa ne na na­čin, ki je do­ku­men­ti­ran.

Ali smo lah­ko na­tan­čnej­ši?

Ali lah­ko sa­mi na­pi­še­mo na­tan­čnej­šo So­und ru­ti­no? Vse­ka­kor! Za to sta nam na vo­ljo dve mož­no­sti: pro­gra­mi­ra­nje v asem­bler­ju ali upo­ra­ba ti­mer­jev mi­kro­kon­tro­ler­ja. Oba pri­sto­pa ima­ta ta­ko svo­je pre­dno­sti kot tu­di po­manj­klji­vo­sti. Naj­prej bo­mo vi­de­li, kaj lah­ko sto­ri­mo s či­stim pro­gra­mi­ra­njem; po­glej­mo si ru­ti­no To­ne (ta­be­la 2).

Ru­ti­na To­ne je ze­lo po­do­bna ko­di, ki jo ge­ne­ri­ra ukaz So­und, le da smo tu­kaj več po­zor­no­sti na­me­ni­li pra­vil­ne­mu ti­min­gu. Tu­di tu­kaj je tra­ja­nje ene­ga sta­nja (“0” ali “1”) do­lo­če­no z maj­hno zan­ko, v ka­te­ri se de­kre­men­ti­ra vse­bi­na re­gis­tra R0; ukaz DJNZ R0 se po­nav­lja vse do­kler vse­bi­na re­gis­tra R0 ni ena­ka 0. V na­šem pri­me­ru bo eno sta­nje tra­ja­lo 248 (za­čet­na vre­dnost v R0) x 2 (tra­ja­nje ene­ga DJNZ uka­za) = 496 µs. K te­mu je tre­ba do­da­ti še 4 µs, ko­li­kor sku­pno po­tre­bu­je­jo osta­li uka­zi v “ve­li­ki” zan­ki (TO­NE1: … DJNZ R1), za­to bo sku­pno tra­ja­nje ene pol­pe­ri­o­de v na­šem pri­me­ru zna­ša­lo 500 µs. Z dru­gi­mi be­se­da­mi, ge­ne­ri­ra­li bo­mo ton fre­kven­ce toč­no 1 kHz, sig­nal pa bo po­pol­no­ma pra­vi­len, ker se obe pol­pe­ri­o­di ge­ne­ri­ra­ta zno­traj iste zan­ke. Šte­vi­lo im­pul­zov, ki jih ge­ne­ri­ra­mo, do­lo­ča za­čet­na vre­dnost re­gis­tra R1 in bo v na­šem pri­me­ru 100 (po­lo­vi­ca vpi­sa­ne vre­dno­sti).

Ge­ne­ri­ra­li smo to­rej ton fre­kven­ce 1 kHz v tra­ja­nju toč­no 100 mi­li­se­kund! To je do­sti bolj na­tan­čno od ti­ste­ga, kar lah­ko do­se­že­mo z uka­zom So­und… Po­glej­mo, ka­ko iz­ra­ču­na­mo po­tre­bne pa­ra­me­tre:
v R1 vpi­še­mo šte­vi­lo dva­krat ve­čje od šte­vi­la im­pul­zov, ki jih že­li­mo ge­ne­ri­ra­ti;
v R0 vpi­še­mo vre­dnost, ki jo iz­ra­ču­na­mo na na­sled­nji na­čin: od tra­ja­nja ene pol­pe­ri­o­de v mi­kro­se­kun­di od­šte­je­mo 4 in dob­lje­no vre­dnost de­li­mo z 2.

Ali:
R1 = šte­vi­lo_im­pul­zov x 2
R0 = (tra­ja­nje_ene_pol­pe­ri­o­de_v_µs – 4) / 2

Kak­šne so ome­ji­tve ru­ti­ne To­ne?
a)ru­ti­na je na­pi­sa­na za osnov­ni takt fre­kven­ce 12 MHz (kot tu­di vse osta­le ča­sov­ne ru­ti­ne Ba­sco­ma); če upo­rab­lja­mo kvarc dru­ge fre­kven­ce, bo­do dob­lje­ne vre­dno­sti so­ra­zmer­no od­sto­pa­le od pri­ča­ko­va­nih;
b)pre­ki­ni­tve ka­te­re­ga ko­li iz­vo­ra (Ti­mer0 ali 1, Int0 ali 1, Se­ri­al) “kra­de­jo” pro­ce­sor­ske ci­kle in s tem vpli­va­jo na toč­nost ge­ne­ri­ra­ne fre­kven­ce;
c) mak­si­mal­na vre­dnost, ki jo lah­ko vpi­še­mo v R0 in R1 je 255 (toč­ne­je 0; 0 = 256); ta do­lo­ča mi­ni­mal­no fre­kven­co, ki jo lah­ko ge­ne­ri­ra­mo (R0 = 0: fmin ~ 969 Hz, R0 = 1: fmax ~ 83 kHz) ter mak­si­mal­no tra­ja­nje (R1 = 0: 128 im­pul­zov);
d) ce­lo ti­stih fre­kvenc, ki se na­ha­ja­jo zno­traj “do­vo­lje­ne­ga” ob­se­ga, ne mo­re­mo ve­dno na­tan­čno do­lo­či­ti; npr. za f = 20 kHz je tra­ja­nje ene pol­pe­ri­o­de 25 µs, za­to bi v R0 mo­ra­li vpi­sa­ti (25 – 4) / 2 = 10,5; po­tre­bno se je odlo­či­ti ali za R0 = 10 (f = 20833 Hz) ali pa za R0 = 11 (f = 19230 Hz);
e)na­čin vpi­sa pa­ra­me­trov je pre­cej ne­ro­den, ra­zen v pri­me­ru, ko že­li­mo ge­ne­ri­ra­ti ma­njše šte­vi­lo vna­prej de­fi­ni­ra­nih to­nov.

Na ome­ji­tve pod a) in d) ne mo­re­mo vpli­va­ti, ker so po­go­je­ne z na­či­nom de­lo­va­nja mi­kro­kon­tro­ler­ja. Ome­ji­tvam pod b) se lah­ko izog­ne­mo, če med iz­va­ja­njem ru­ti­ne To­ne one­mo­go­či­mo pre­ki­ni­tve. S pre­o­sta­li­ma dve­ma pri­pom­ba­ma pa se lah­ko spo­pri­me­mo: ve­čji raz­pon fre­kvenc in tra­ja­nja lah­ko do­se­že­mo, če na­me­sto re­gis­trov za vpis pa­ra­me­trov upo­ra­bi­mo spre­men­ljiv­ke ti­pa word, na­čin vpi­sa pa­ra­me­trov pa lah­ko pri­bli­ža­mo stan­dar­dne­mu Ba­scom na­či­nu de­lo­va­nja (ne pa tu­di po­pol­no­ma ize­na­či­mo s stan­dar­dni­mi Ba­scom uka­zi).
To­ne ali So­und?
Iz­bo­ljša­na To­ne ru­ti­na je za­pi­sa­na v da­to­te­ki TO­NE$SUB.BAS in jo naj­de­te na pri­lo­že­nem CD-ju. De­lo­ma je pro­gra­mi­ra­na v asem­bler­ju, de­lo­ma pa v Ba­sco­mu. Tu­kaj je ne bo­mo po­dro­bno ana­li­zi­ra­li; po­vej­mo le, da je za­sno­va­na na opi­sa­nih prin­ci­pih, osnov­na raz­li­ka pa je v tem, da so pa­ra­me­tri 16-bit­ni (word), kar jim omo­go­ča ve­li­ko šir­ši na­sta­vi­tve­ni raz­pon. Prav ta­ko je pred­vi­den uvo­dni del za iz­ra­čun vre­dno­sti pa­ra­me­trov, ta­ko da se jih lah­ko vna­ša v na­rav­ni obli­ki (ni več po­tre­bno “roč­no” ra­ču­na­nje).

TO­NE tra­ja­nje , šte­vi­lo_im­pul­zov
tra­ja­nje tra­ja­nje ene­ga impul­za v us,
36 – 65535
(byte ali word kon­stan­ ta ali spre­men­ljiv­ka)
šte­vi­lo_im­pul­zov
šte­vi­lo im­pul­zov (0-65535)
(byte ali word kon­stan­ta ali spre­men­ljiv­ka)

Opom­be:
fre­kven­ca osci­la­tor­ja = 12 MHz
če je tra­ja­nje šte­vi­lo de­lji­vo s 4, bo dob­lje­ni sig­nal pra­vi­len
če je tra­ja­nje so­do šte­vi­lo, ki ni dje­lji­vo s 4, se bo tra­ja­nje “1” in “0” raz­li­ko­va­lo za 2 µs
če je tra­ja­nje li­ho šte­vi­lo, ga bo ru­ti­na pre­ra­ču­na­la v pr­vo ma­njše so­do šte­vi­lo
šte­vi­lo_im­pul­zov = 0 po­me­ni, da se bo ru­ti­na iz­va­ja­la v ne­skon­čnost
Že­lje­no fre­kven­co lah­ko pre­ra­ču­na­te v im­pul­zni čas (tra­ja­nje ene­ga im­pul­za) po for­mu­li

na­kar dob­lje­no vre­dnost za­o­kro­ži­te na naj­bli­žje ce­lo so­do šte­vi­lo. Če že­li­te, da na­me­sto vas to opra­vi Ba­scom, na­me­sto ru­ti­ne To­ne po­kli­či­te ru­ti­no Frek:

FREQ fre­kven­ca , šte­vi­lo_im­pul­zov
fre­kven­ca fre­kven­ca v Hz, 16 – 25000
byte ali word kon­stan­ta ali
spre­men­ljiv­ka)
šte­vi­lo_im­pul­zov
šte­vi­lo im­pul­zov (0-65535)
byte ali word kon­stan­ta ali
spre­men­ljiv­ka)

Opom­be:
ru­ti­na Frek pre­ra­ču­na za­da­no fre­kven­co v im­pul­zni čas ter na­to po­kli­če ru­ti­no To­ne
vseh fre­kvenc ni mož­no “okro­glo” pre­ra­ču­na­ti v čas, za­to so mož­na tu­di ma­njša od­sto­pa­nja med za­da­no in ge­ne­ri­ra­no fre­kven­co
če ge­ne­ri­ra­na fre­kven­ca od­sto­pa od za­da­ne, se po­sta­vi Err bit
ve­lja­jo vse opom­be iz opi­sa ru­ti­ne To­ne

Sez­nam ne­ka­te­rih fre­kvenc, ki se jih da na­tan­čno ge­ne­ri­ra­ti: 16 Hz, 20 Hz, 25 Hz, 32 Hz, 40 Hz, 50 Hz, 80 Hz, 100 Hz, 200 Hz, 400 Hz, 500 Hz, 1 kHz, 2 kHz, 4 kHz, 5 kHz, 10 kHz, 20 kHz, 25 kHz, …

To­ne in Frek lah­ko šte­je­mo za no­va Ba­scom uka­za… pa ven­dar­le, ker ni­sta se­stav­ni del Ba­sco­ma, se je za nji­ho­vo upo­ra­bo po­tre­bno us­trez­no pri­pra­vi­ti:
na za­čet­ku pro­gra­ma vpi­ši­te uka­ze

Dim To­ne$us As Word , To­ne$cy As Word
To­ne$pin Ali­as Px.y
De­cla­re Sub To­ne(to­ne$us , To­ne$cy)
De­cla­re Sub Freq(to­ne$us , To­ne$cy) 
(Px.y je pin V/I vrat, na ka­te­rih že­li­te ge­ne­ri­ra­ti sig­nal, npr. P3.5)

na kon­cu pro­gra­ma (za uka­zom End) do­daj­te vse­bi­no da­to­te­ke To­ne$sub.bas (mo­ra bi­ti v isti ma­pi/di­rek­to­ri­ju, v ka­te­rem se na­ha­ja glav­ni pro­gram)

$in­clu­de To­ne$sub.bas

Se­daj lah­ko uka­za To­ne in Frek upo­rab­lja­te ta­ko, kot je zgo­raj opi­sa­no. Sle­di ne­kaj pri­me­rov:

To­ne 60 , 1000 ' 1000 im­pul­zov,
 ' T = 60us, f = 16667Hz
' ...
To­ne$pin = 0 ' če že­li­mo, da se niz 
 zač­ne z “1”,
 ' pred kli­ca­njem To­ne/Frek 
 po­sta­vi­mo
 ' To­ne$pin na “0” in obrat­no
Freq ff , us ' ff, us: byte/word 
 spre­men­ljiv­ki
If Err = 1 Then ' če f ni = ff, ... 
' ...
Freq 1000 , 0 ' f = 1 kHz, stal­no

Zad­nji pri­mer mo­ram še ma­lo raz­lo­ži­ti… Kot že re­če­no, če je pa­ra­me­ter šte­vi­lo_im­pul­zov = 0, se bo traj­no ge­ne­ri­ral sig­nal že­lje­ne fre­kven­ce. To nam lah­ko pri­de prav, ka­dar s po­mo­čjo mi­kro­kon­tro­ler­ja že­li­mo na­re­di­ti fre­kven­čni ge­ne­ra­tor ali kaj po­do­bne­ga. Ven­dar s tem pro­gram spra­vi­mo v ne­skon­čno zan­ko, iz ka­te­re se lah­ko ‘re­ši’ sa­mo z re­se­tom. To pa s pro­gram­ske­ga sta­li­šča ni naj­bolj po­sre­če­na re­ši­tev! Za­to smo v ru­ti­ni To­ne in Freq do­da­li še en maj­hen do­da­tek: če tra­ja­nje sig­na­la ni ča­sov­no ome­je­no, lah­ko iz­va­ja­nje ru­ti­ne pre­ki­ne­mo ta­ko, da iz­ho­dni pin (To­ne$pin) krat­ko­traj­no ve­že­mo na ma­so; obe ru­ti­ni pri­ča­ku­je­ta ta do­go­dek in ko ga od­kri­je­ta, pre­ki­ne­ta svo­je iz­va­ja­nje ter vr­ne­ta kon­tro­lo glav­ne­mu pro­gra­mu… se­daj lah­ko spre­me­ni­mo fre­kven­co ali na­re­di­mo kar­ko­li dru­ge­ga, pač od­vi­sno od te­ga, kam nas lo­gi­ka pro­gra­ma za­ne­se.

Sli­ka 2 pri­ka­zu­je idej­no re­ši­tev fre­kven­čne­ga ge­ne­ra­tor­ja, ki upo­rab­lja opi­sa­no mož­nost. Re­set tip­ka pre­ki­ne iz­va­ja­nje pro­gra­ma in po­vr­ne kon­tro­lo glav­ne­mu pro­gra­mu… Po­glej­mo, ka­ko je to re­a­li­zi­ra­no pro­gram­sko v ru­ti­ni To­ne:

TO­NE:
 ...
 SETB TO­NE$PIN
 ...
 JB TO­NE$PIN,.TO­NE
RE­TURN

Eno­stav­no, mar ne? Na­me­sto uka­za DJNZ, ki smo ga upo­rab­lja­li za šte­tje, ko smo ho­te­li pro­iz­ve­sti sa­mo do­lo­če­no šte­vi­lo im­pul­zov, smo tu­kaj upo­ra­bi­li ukaz JB, ki nas vra­ča na za­če­tek zan­ke vse do­kler je To­ne$pin = 1. Se­ve­da se te­sti­ra­nje po­go­ja do­ga­ja v tre­nut­ku, ko bi To­ne$pin mo­ral bi­ti “1”; če ni, po­me­ni, da je pin od zu­naj krat­ko skle­njen na ma­so, za­to se na­me­sto vr­ni­tve na za­če­tek zan­ke iz­ve­de na­sled­nji ukaz – Re­turn.

Ti­mer in So­und
Ka­ko lah­ko s po­mo­čjo ti­mer­ja ge­ne­ri­ra­mo zvoč­ni sig­nal? Po­glej­mo si eno­sta­ven pri­mer:

To­ne$bit Ali­as P3.5
To­ne$stop Ali­as P3.0
Con­fig Ti­mer0 = Ti­mer , Ga­te = In­ter­nal , 
 Mo­de = 2
On Ti­mer0 Tim0 No­sa­ve
Ena­ble Ti­mer0
Ena­ble In­ter­rupts
 ...
Lo­ad Ti­mer0 , 100
Start Ti­mer0
Pet­lja:
 jb to­ne$stop,.zan­ka
 Stop Ti­mer0
 ...
Tim0:
 To­ne$bit = Not To­ne$bit
Re­turn

Tu­kaj upo­rab­lja­mo Ti­mer0 v na­či­nu 2, v ka­te­rem se za­čet­na vre­dnost (=100) sa­mo­dej­no obno­vi vsa­kič, ko ti­mer preš­te­je za­da­no šte­vi­lo pro­ce­sor­skih ci­klov (to de­lo se oprav­lja na har­dver­skem ni­vo­ju). Isto­ča­sno se iz­va­ja pre­ki­ni­tve­na ru­ti­na Tim0, zno­traj ka­te­re in­ver­ti­ra­mo sta­nje iz­ho­dne­ga pi­na To­ne$bit. V na­šem pri­me­ru se bo to zgo­di­lo vsa­kih 100 µs, kar po­me­ni, da bo ge­ne­ri­ran sig­nal fre­kven­ce 5 kHz.

Opa­zi­mo, da se vse to iz­va­ja zno­traj zan­ke, v ka­te­ro pro­gram vsto­pi po de­fi­ni­ra­nju za­čet­ne vre­dno­sti (Lo­ad Ti­mer0) in za­go­nu ti­mer­ja (Start Ti­mer0). Zan­ka je se­stav­lje­na iz ene­ga sa­me­ga asem­bler­ske­ga uka­za (jb to­ne$stop,.zan­ka), ki se bo iz­va­jal, vse do­kler ne bo­mo spo­ji­li pin To­ne$stop na ma­so.

Ka­te­re so pre­dno­sti ali po­manj­klji­vo­sti ta­ke re­ši­tve? Člo­vek bi pri­ča­ko­val, da je har­dver­ska re­ši­tev ve­dno bo­ljša in hi­trej­ša od sof­tver­ske­ga ekvi­va­len­ta. To je res, saj se sta­nje ti­mer­ja spre­me­ni vsa­ko mi­kro­se­kun­do, to­rej dva­krat hi­tre­je kot je to bi­lo mož­no do­se­či s po­mo­čjo uka­za djnz v ru­ti­nah So­und ali To­ne. Ven­dar s tem še ni­smo re­ši­li na­še­ga pro­ble­ma: ker pro­gram ča­ka na pre­ki­ni­tev v zan­ki, kjer je tra­ja­nje jb, ka­kor tu­di vseh dru­gih uka­zov za skok 2 µs, nam pri tem ne mo­re­ta po­ma­ga­ti ni­ti Ba­scom ni­ti asem­bler! To­rej ni­smo do­se­gli prak­tič­no no­be­ne iz­bo­ljša­ve – toč­nost je še na­prej na ni­vo­ju dveh mi­kro­se­kund. Ne­ka­te­re stva­ri so ce­lo ne­ko­li­ko ušle nad­zo­ru, ker se bo, ne gle­de na to, ali se je pre­ki­ni­tev zgo­di­la v pr­vi ali dru­gi mi­kro­se­kun­di iz­ved­be uka­za za skok, pri­dru­že­na pre­ki­ni­tve­na ru­ti­na iz­vr­ši­la še­le, ko se bo ukaz za skok kon­čal. To lah­ko pri do­lo­če­nih fre­kven­cah pov­zro­či ra­hlo ne­si­me­tri­jo ge­ne­ri­ra­ne­ga sig­na­la.

Iz­bo­ljša­nja se mo­ra­mo to­rej lo­ti­ti na drug na­čin. Po­glej­mo si na­sled­njo ide­jo:

Zan­ka:
 Idle
 jb to­ne$stop,.zan­ka
 Stop Ti­mer0

Od pr­ve­ga pri­me­ra se raz­li­ku­je le po uka­zu Idle, ki je tu­kaj do­dan zno­traj zan­ke. Bis­tvo spre­mem­be je v tem, da se­daj pro­gram ne bo ča­kal v zan­ki (ki se iz­ve­de vsa­ki 2 µs) tem­več bo “za­spal” pri uka­zu Idle. Ker lah­ko pre­ki­ni­tev pre­ki­ne Idle vsa­ko mi­kro­se­kun­do, smo s tem do­se­gli dva­krat ve­čjo na­tan­čnost na­sta­vi­tve fre­kven­ce! Am­pak lah­ko opa­zi­mo, da tu­di uka­za Idle in jb tra­ja­ta ne­kaj ča­sa (k če­mur je po­tre­bno do­da­ti še skok v pre­ki­ni­tve­no ru­ti­no Tim0, nje­no iz­va­ja­nje in vr­ni­tev; sku­pno 9 µs); ven­dar ne po­za­bi­mo, da se ti pro­gram­ski ko­ra­ki iz­va­ja­jo pa­ra­lel­no z de­lom ti­mer­ja. Edi­ni pred­po­goj je, da je za­čet­na vre­dnost ti­mer­ja (Lo­ad Ti­mer0) vsaj 9 ali več, da bi se teh ne­kaj in­struk­cij uteg­ni­lo iz­vr­ši­ti; če vne­se­mo vre­dnost med 1 in 8, ne bo­mo do­se­gli pri­ča­ko­va­ne­ga tra­ja­nja. (Za­ni­mi­vo je, da je tu­di pri Lo­ad Ti­mer0, 10, ge­ne­ra­tor ne­raz­lo­žlji­vo ka­zal ob­ča­sno ne­sta­bil­nost v de­lo­va­nju.)

Naj­ve­čja vre­dnost, ki jo lah­ko vpi­še­mo v au­to­re­lo­ad na­či­nu (mo­de 2), zna­ša 255 (prav­za­prav, 256: 256 = 0). Ta ome­ji­tev iz­ha­ja iz ar­hi­tek­tu­re mi­kro­kon­tro­ler­ja in ne iz Ba­sco­ma. Za­to ima­mo na vo­ljo so­ra­zmer­no maj­hno šte­vi­lo fre­kvenc, ki jih lah­ko ge­ne­ri­ra­mo. Ali pa tu­di ne?

Po­sku­si­mo si­mu­li­ra­ti au­to­re­lo­ad s ti­mer­jem po­stav­lje­nim v na­čin 1. Po­tre­bo­va­li bo­mo eno spre­men­ljiv­ko ti­pa word, v ka­te­ro bo­mo shra­ni­li za­čet­no sta­nje ti­mer­ja, ki jo bo­mo v pre­ki­ni­tve­ni ru­ti­ni po­nov­no vpi­so­va­li v re­gi­ster ti­mer­ja. Po­glej­mo si, ka­ko bi naj to iz­gle­da­lo.

Dim Tra­ja­nje As Word
To­ne$stop Ali­as P3.0
To­ne$bit Ali­as P3.7
Con­fig Ti­mer1 = Ti­mer , Ga­te = In­ter­nal, 
 Mo­de = 1
On Ti­mer1 Tim1 No­sa­ve
Ena­ble Ti­mer1
Ena­ble In­ter­rupts
Tra­ja­nje = 10000 ' = Lo­ad Ti­mer1,
 10000
Tra­ja­nje = 12 - Tra­ja­nje ' raz­la­ga v tek­stu
Go­sub Tim1
Zan­ka:
 Idle
 jb to­ne$stop,.zan­ka
Stop Ti­mer1
 ...
 ...
Tim1:
 To­ne$bit = Not To­ne$bit
 Co­un­ter1 = Tra­ja­nje ' prog. si­mu­la­ci­ja
 Start Ti­mer1 ' na­či­na 2
Re­turn

Pri­mer je ze­lo po­do­ben prej­šnje­mu; tu­kaj smo upo­ra­bi­li Ti­mer1 (kar ni­ti ni to­li­ko po­mem­bno), ki je po­stav­ljen v na­čin 1, na­čin 2 pa je si­mu­li­ran pro­gram­sko. Naj­prej smo v spre­men­ljiv­ko Tra­ja­nje na­lo­ži­li že­le­no za­čet­no vre­dnost in na­to ma­lo ra­ču­na­li. Ta iz­ra­čun je po­tre­ben za­to, ker ti­mer ve­dno šte­je nav­zgor; za­to je na­me­sto 10000, kot v na­šem pri­me­ru, po­tre­bno vpi­sa­ti 65536 – 10000 = 55536 (ta iz­ra­čun pri na­či­nu 2 ne­o­paz­no opra­vi na­me­sto nas ukaz Lo­ad). 65536 je za 1 pre­ve­li­ko šte­vi­lo za spre­men­ljiv­ko ti­pa word, ven­dar lah­ko Ba­scom tu­di ma­lo pre­va­ra­mo. Ta­ko lah­ko že­le­ni iz­ra­čun do­se­že­mo z uka­zo­ma:

Tra­ja­nje = 10000
Tra­ja­nje = 0 – Tra­ja­nje

Pri tem 0 uspe­šno za­me­nja 65536. Ven­dar za­kaj smo v pri­me­ru ra­ču­na­li z 12? Za raz­la­go po­glej­mo, kaj se do­ga­ja v ru­ti­ni Tim1. Po in­ver­ti­ra­nju pi­na To­ne$bit, za­ra­di če­sar smo v ru­ti­no tu­di pri­šli, mo­ra­mo “roč­no” na­pol­ni­ti re­gi­ster ti­mer­ja in ga na­to po­nov­no zag­na­ti. V na­či­nu 2 se je vse to do­ga­ja­lo na har­dver­skem ni­vo­ju, ven­dar smo bi­li ome­je­ni na raz­pon 1-256. V tre­nut­ku, ko po­nov­no za­že­ne­mo ti­mer, je le-ta že preš­tel 12 ci­klov – za­to smo mo­ra­li za­čet­no vre­dnost ko­ri­gi­ra­ti na ome­nje­ni na­čin. Da gre rav­no za 12, lah­ko ugo­to­vi­mo z na­tan­čno ana­li­zo ge­ne­ri­ra­ne ali z me­ri­tvi­jo.

Opi­sa­ni po­sto­pek tra­ja do­lo­če­no šte­vi­lo ci­klov, za­to bo pra­vil­no de­lo­val sa­mo, če bo za­čet­na vre­dnost spre­men­ljiv­ke Tra­ja­nje 17 ali več (pri pr­vi re­ši­tvi je bi­la 9). No, to nas ne sme pre­več mo­ti­ti: “na­tan­čnost” je tu­di tu­kaj 1 µs, mož­no pa je ce­lo uspe­šno kom­bi­ni­ra­ti oba po­stop­ka ter z ma­lo pro­gra­mer­ske spret­no­sti tu­di upo­rab­lja­ti isti ti­mer v obeh pri­me­rih. Ta­ko bo­mo lah­ko re­a­li­zi­ra­li fre­kven­ce v raz­po­nu med 7,63 Hz (65536 µs) in 55,55 kHz (9 µs). “Nav­zgor” se lah­ko pre­mi­ka­mo na dva na­či­na: s po­ve­ča­njem fre­kven­ce kvar­ca na 24 MHz ali z zan­ka­mi, ven­dar lah­ko na ta na­čin re­a­li­zi­ra­mo le ne­kaj “okro­glih” fre­kvenc. “Nav­zdol” se lah­ko pre­mi­ka­mo z zma­njša­njem fre­kven­ce kvar­ca (kar isto­ča­sno upo­čas­nju­je ce­lo­ten od­ziv), z zu­na­njim de­lil­ni­kom, ven­dar tu­di s spret­no upo­ra­bo sa­me­ga mi­kro­kon­tro­ler­ja. Pre­i­šči­mo po­dro­bne­je to zad­njo mož­nost.

Kon­fi­gu­ri­raj­mo Ti­mer0 ta­ko, da bo v na­či­nu 2 štel mi­kro­pro­ce­sor­ske ci­kle in v pre­ki­ni­tve­ni ru­ti­ni vsa­kih, re­ci­mo 50 ci­klov, in­ver­ti­ral sta­nje pi­na P3.5.

Con­fig Ti­mer0 = Ti­mer , Ga­te = In­ter­nal , 
 Mo­de = 2
On Ti­mer0 Tim0 No­sa­ve
Priority Set Ti­mer0
Ena­ble Ti­mer0
Ena­ble In­ter­rupts
 ...
 ...
Lo­ad Ti­mer0 , 50
Start Ti­mer0
 ...
 ...
Tim0:
 P3.5 = Not P3.5
Re­turn

S tem smo na pi­nu P3.5 do­bi­li sig­nal fre­kven­ce, ki je 100-krat ni­žja od fre­kven­ce in­ter­ne­ga tak­ta (1 MHz). De­lje­nja s fak­tor­jem ma­njšim od 9 ne mo­re­mo re­a­li­zi­ra­ti (o tem smo že pi­sa­li), po­tre­bno pa je bi­ti paz­ljiv tu­di s fak­tor­ji ma­njši­mi od 20 (ker je te­daj mi­kro­pro­ce­sor več ča­sa v pre­ki­ni­tve­ni ru­ti­ni kot pa v glav­nem pro­gra­mu). To zma­njša­no fre­kven­co lah­ko se­daj upo­ra­bi­mo kot vhod v Ti­mer1, če ga kon­fi­gu­ri­ra­mo ta­ko, da de­lu­je kot šte­vec (vhod je rav­no pin P3.5):

Con­fig Ti­mer1 = Co­un­ter , Ga­te = In­ter­nal , Mo­de = 1
On Ti­mer1 Tim1 No­sa­ve

Ti­mer1 bo­mo upo­ra­bi­li na že opi­san na­čin, s pri­mer­no iz­bi­ro fak­tor­ja de­lje­nja pa lah­ko pre­cej zni­ža­mo spod­njo mej­no fre­kven­co. Ve­li­ko sem ek­spe­ri­men­ti­ral s ti­mer­ji, ta­ko da vem, da ta ide­ja za­go­to­vo de­lu­je – po­tre­bno jo je sa­mo ne­ko­li­ko pri­la­go­di­ti kon­kret­ni upo­ra­bi, ven­dar to pre­pu­ščam vam.

Fre­kven­čni ge­ne­ra­tor

Kon­čno smo pri­šli do ci­lja! Ob upo­ra­bi prej opi­sa­nih prin­ci­pov in z nji­ho­vim uvr­šča­njem v us­trez­ni pro­gram bo­mo na­re­di­li na­tan­čni fre­kven­čni ge­ne­ra­tor. Prav­za­prav gre za dva pro­gra­ma – G_FREK_24.BAS in G_FREK_18.BAS – ki se na­ha­ja­ta na pri­lo­že­nem CD-ju in ju upo­ra­bi­te v ori­gi­na­lu ali pa kot osno­vo za mo­di­fi­ka­ci­je gle­de na la­stne po­tre­be. Tu­kaj se ne bo­mo spu­šča­li v po­dro­bno opi­so­va­nje pro­gram­ske ko­de, ker smo vse osnov­ne prin­ci­pe že pre­a­na­li­zi­ra­li, tem­več bo­mo ne­kaj pro­sto­ra na­me­ni­li pro­gram­ski za­sno­vi in na­či­nu upo­ra­be. Po­vej­mo le, da sta oba pro­gra­ma re­še­na na prin­ci­pu šte­tja, to­rej brez upo­ra­be ti­mer­ja. Za to smo se odlo­či­li, ko nam je uspe­lo se­sta­vi­ti ze­lo eno­sta­ven pro­gram­ski trik, s ka­te­rim se na­tan­čnost ge­ne­ri­ra­nja fre­kven­ce z dveh po­pra­vi na en ci­kel mi­kro­kon­tro­ler­ja in s tem ize­na­či z mož­nos­tmi, ki nam jih omo­go­ča­jo ti­mer­ji; za­in­te­re­si­ra­ne bral­ce va­bim, da sa­mi ana­li­zi­ra­jo ru­ti­ni Frek_1 in Frek_2 pro­gra­ma F_gen_24.bas.

Pred­vi­de­no je, da ge­ne­ra­tor pro­iz­va­ja do­lo­če­no šte­vi­lo fik­sno za­da­nih fre­kvenc (oko­li 50 fre­kvenc) v po­dro­čju med 1 Hz in 500 kHz. Pro­gram je in­te­rak­ti­ven in za ko­mu­ni­ka­ci­jo z upo­ra­bni­kom upo­rab­lja al­fa­nu­me­rič­ni pri­ka­zo­val­nik (16*1) ter vr­sto na­vi­ga­cij­skih tipk, kot je na­zor­no pri­ka­za­no na sli­ki 3. S tip­ka­ma “gor” in “dol” se po­mi­ka­mo po ni­vo­jih me­ni­ja:

… 7 <-> 1 <-> 2 <-> 3 <-> 4 <-> 5 <-> 6 <-> 7 <-> 1 …

Po­sa­mez­ni ni­vo­ji omo­go­ča­jo na­sled­njo iz­bi­ro fre­kvenc:
1. ni­vo: ra­ster 1 : 2 : 5
pri­kaz na pri­ka­zo­val­ni­ku: 1-2-5 1 kHz
ge­ne­ri­ra­ne fre­kven­ce: 1 – 2 – 5 – 10 – 20 – 50 – 100 – 200 – 500 Hz, 1 – 2 – 5 – 10 – 20 – 50 – 100 – 200 – 500 kHz
2. ni­vo: ok­tav­ni ra­ster 0,5 : 1 : 2
pri­kaz na pri­ka­zo­val­ni­ku: 0,5-1-2 1 kHz
ge­ne­ri­ra­ne fre­kven­ce: 15,63 – 31,25 – 62,5 – 125 – 250 – 500 Hz – 1 – 2 – 4 – 8 – 16 kHz
3. ni­vo: de­ka­dni ra­ster 1 : 10
– pri­kaz na pri­ka­zo­val­ni­ku: 1-10-100 1 kHz
– ge­ne­ri­ra­ne fre­kven­ce: 1 – 10 – 100 Hz – 1 – 10 – 100 kHz
4. ni­vo: de­ka­dni ra­ster 2 : 20
pri­kaz na pri­ka­zo­val­ni­ku: 2-20-200 2 kHz
ge­ne­ri­ra­ne fre­kven­ce: 2 – 20 – 200 Hz – 2 – 20 – 200 kHz
5. ni­vo: de­ka­dni ra­ster 5 : 50
pri­kaz na pri­ka­zo­val­ni­ku: 5-50-500 5 kHz
ge­ne­ri­ra­ne fre­kven­ce: 5 – 50 – 500 Hz – 5 – 50 – 500 kHz
6. ni­vo: fi­ni ra­ster
pri­kaz na pri­ka­zo­val­ni­ku: 1-2-3-4 1 kHz
ge­ne­ri­ra­ne fre­kven­ce: 1 – 1,5 – 2 – 3 – 4 – 5 – 6 – 8 – 10 – 15 – 20 – 30 – 40 – 50 – 60 – 80 – 100 – 150 – 200 – 300 – 400- 500 – 600 – 800 Hz – 1 – 1,5 – 2 – 3 – 4 – 5 – 6 – 8 – 10 – 15 – 20 – 30 – 40 – 50 – 60 – 80 – 100 – 150 – 200 – 300 – 400 500 kHz
7. ni­vo: pro­sto iz­bi­ra­nje fre­kven­ce
pri­kaz na pri­ka­zo­val­ni­ku: frek = 00000 Hz
fre­kven­čni raz­pon: 1 Hz – 80 kHz

Na vsa­kem ni­vo­ju s tip­ka­ma “le­vo” in “de­sno” iz­bi­ra­mo eno od po­nu­je­nih fre­kvenc. S pri­ti­skom na tip­ko “OK” za­že­ne­mo, s tip­ko “STOP” pa pre­ki­ne­mo ge­ne­ri­ra­nje sig­na­la.

Iz­je­ma je sed­mi ni­vo (pro­sto iz­bi­ra­nje fre­kven­ce). S pr­vim pri­ti­skom na tip­ko “OK” do­bi­mo mož­nost vpi­sa pet­me­stne­ga šte­vi­la, ki pred­stav­lja že­le­no fre­kven­co: s tip­ka­ma “le­vo” in “de­sno” se pre­mi­ka­mo po nje­go­vih ci­frah, s tip­ka­ma “gor” in “dol” pa ko­ri­gi­ra­mo vre­dnost tre­nut­no iz­bra­ne ci­fre. S po­nov­nim pri­ti­skom na tip­ko “OK” se za­če­nja ge­ne­ri­ra­nje iz­bra­ne fre­kven­ce. S pri­ti­skom na tip­ko “STOP” pre­ki­ne­mo ge­ne­ri­ra­nje sig­na­la in omo­go­či­mo spre­mem­bo ni­vo­ja (tip­ki “gor” in “dol” po­nov­no do­bi­ta svo­jo sta­ro fun­kci­jo spre­ha­ja­nja po ni­vo­jih).

Lah­ko opa­zi­mo, da gre na ni­vo­jih 1-6 za na­bor ena­kih fre­kvenc, ki so gru­pi­ra­ne na raz­lič­ne na­či­ne. Ta­ko so na ni­vo­ju 1 fre­kven­ce raz­vr­šče­ne s ko­ra­kom 1 : 2 : 5, na ni­vo­ju 2 s ko­ra­kom 0,5 : 1 : 2 (ok­tav­no), na ni­vo­jih 3 – 5 z de­ka­dnim ko­ra­kom 1 : 10 : 100 itn. To nam omo­go­ča hi­tro in eno­stav­no iz­bi­ra­nje že­le­ne fre­kven­ce in nje­no spre­mi­nja­nje, pač od­vi­sno od te­ga, kaj že­li­mo do­se­či. Naj vas spom­nim, da so gle­de na “di­gi­tal­ni” na­čin ge­ne­ri­ra­nja (tra­ja­nje ene pe­ri­o­de je mno­go­krat­nik tra­ja­nja ene­ga mi­kro­pro­ce­sor­ske­ga ci­kla) fre­kven­ce vseh ge­ne­ri­ra­nih sig­na­lov ze­lo na­tan­čne (na­tan­čnost je od­vi­sna od na­tan­čno­sti kvar­čne­ga kri­sta­la).

To je isto­ča­sno tu­di raz­log, za­ra­di ka­te­re­ga ni mož­no ge­ne­ri­ra­ti vsa­ke že­le­ne fre­kven­ce na ni­vo­ju 7. Pri­bliž­no do fre­kven­ce 1 kHz je mož­no iz­bra­ti vsa­ko fre­kven­co (ko­rak 1 Hz), pri če­mer bo od­sto­pa­nje med za­da­no in de­jan­sko fre­kven­co ma­njše od 0,1 %. Pri fre­kven­cah vi­šjih od 1 kHz se ko­rak po­sto­po­ma po­ve­ču­je, med­tem ko pri fre­kven­cah nad 10 kHz ra­ste hi­tro in do­se­že ne­kaj kHz. V pro­gram je vgra­je­na ru­ti­na za pre­ver­ja­nje na­tan­čno­sti, ki skr­bi za na­sta­lo od­sto­pa­nje. Če npr. iz­be­re­mo fre­kven­co 3000 Hz, je naj­bli­žja toč­na fre­kven­ca, ki jo lah­ko ge­ne­ri­ra­mo, 3003,003 Hz. Ko s tip­ko “OK” spro­ži­mo de­lo­va­nje ge­ne­ra­tor­ja, bo pro­gram iz­pi­sal, da ge­ne­ri­ra­mo 3003 Hz in ne že­le­nih 3000 Hz.

Ta pro­blem je sa­mo na sed­mem ni­vo­ju, na ka­te­rem pro­sto iz­bi­ra­mo fre­kven­co. Na vseh osta­lih ni­vo­jih smo pri­si­lje­ni iz­bi­ra­ti med ome­je­nim šte­vi­lom raz­po­lo­žlji­vih fre­kvenc, ven­dar so za­to vse fre­kven­ce ze­lo na­tan­čne. Da bi to do­se­gli, smo upo­ra­bi­li dva tri­ka:

  • za ne­ka­te­re fre­kven­ce (16 kHz, 80 kHz, 500 kHz…) je na­pi­sa­na po­se­bna ru­ti­na; ge­ne­ri­ra­ni sig­nal je ne­ko­li­ko “ne­si­me­tri­čen” (tra­ja­nje “1” in “0” se raz­li­ku­je za 1 – 3 µs), ven­dar je fre­kven­ca toč­na;
    mi­kro­kon­tro­ler de­lu­je na dveh fre­kven­cah: 24 in 18 MHz; de­lo­va­nje na 18 MHz omo­go­ča na­tan­čno ge­ne­ri­ra­nje fre­kvenc 15 Hz, 30 Hz, 60 Hz in nji­ho­vih de­ka­dnih mno­go­krat­ni­kov, med­tem ko lah­ko vse osta­le fre­kven­ce re­a­li­zi­ra­mo s 24 MHz kvar­com.

Vez­je je ze­lo eno­stav­no, prav­za­prav mi­ni­ma­li­stič­no (sli­ka 4) – po­leg dveh mi­kro­kon­tro­ler­jev so upo­rab­lje­ni sa­mo še sta­bi­li­za­tor na­pe­to­sti, al­fa­nu­me­rič­ni pri­ka­zo­val­nik in šest na­vi­ga­cij­skih tipk. Vse po­tre­bne fun­kci­je se iz­va­ja­jo zno­traj sa­mih mi­kro­kon­tro­ler­jev. Lah­ko bi vse sku­paj re­a­li­zi­ra­li tu­di s sa­mo enim mi­kro­kon­tro­ler­jem, ven­dar se je, ko se je po­ja­vi­la po­tre­ba po dveh de­lov­nih fre­kven­cah, po­ja­vil tu­di pro­blem pre­kla­plja­nja dveh kvar­čnih kri­sta­lov. Po več po­sku­sih sem ugo­to­vil, da je naj­e­no­stav­nej­ša re­ši­tev upo­ra­ba dru­ge­ga mi­kro­kon­tro­ler­ja. S tem smo do­bi­li tu­di ne­kaj do­dat­ne­ga pro­gram­ske­ga pro­sto­ra, za­ra­di če­sar je lah­ko pro­gram ele­gan­tnej­ši za upo­ra­bo ter na­tan­čnej­ši. Mi­mo­gre­de naj ome­nim, da so Ba­scom ru­ti­ne za de­lo z long spre­men­ljiv­ka­mi pre­cej ‘za­prav­lji­ve’, ta­ko da je sku­pna pro­gram­ska ko­da ve­čja od 4 kB. Mi­kro­kon­tro­ler, ki de­lu­je s 24 MHz, oprav­lja ve­či­no de­la: uprav­lja z na­vi­ga­cij­ski­mi tip­ka­mi in pri­ka­zo­val­ni­kom, ge­ne­ri­ra ve­či­no fre­kvenc, uprav­lja z de­lom dru­ge­ga mi­kro­kon­tro­ler­ja. Dru­gi, po­mož­ni mi­kro­kon­tro­ler pro­iz­va­ja sa­mo kak­šnih 15 kri­tič­nih fre­kvenc. Ko­mu­ni­ka­ci­ja med mi­kro­kon­tro­ler­ji je stan­dar­dna se­rij­ska, za kar ima­mo v Ba­scom vgra­je­ne po­tre­bne ru­ti­ne. Gle­de na ve­li­kost pro­gra­ma mo­ra­mo kot glav­ni mi­kro­kon­tro­ler (IC2) upo­ra­bi­ti AT89C4051, kot po­mož­ni (IC3) pa bo za­do­sto­val tu­di AT89C1051 ali AT89C2051.

Ge­ne­ri­ra­ni sig­nal je pra­vo­kot­ne obli­ke, si­me­tri­čen, am­pli­tu­de 5 Vpp. Pull-up upor R1 po­spe­šu­je pre­hod iz sta­nja “0” v sta­nje “1”. Tak­šen sig­nal je ta­ko TTL kot tu­di CMOS kom­pa­ti­bi­len ter se ga lah­ko di­rek­tno upo­ra­bi v raz­lič­nih di­gi­tal­nih vez­jih. Se­ve­da je mož­na nje­go­va upo­ra­ba tu­di v ana­log­nih vez­jih, ko­li­kor to do­pu­šča pra­vo­kot­na obli­ka sig­na­la. Ta­krat bi mo­ra­li pred­vi­de­ti tu­di us­trez­ni re­gu­la­tor am­pli­tu­de. Pre­o­bli­ko­va­nje pra­vo­kot­ne­ga sig­na­la v si­nu­sni ni rav­no eno­stav­no. Če gre za eno ali le ne­kaj fre­kvenc, lah­ko to do­se­že­mo s paz­lji­vim fil­tri­ra­njem. Spe­ci­al­na ana­log­na in­te­gri­ra­na vez­ja – fun­kcij­ski ge­ne­ra­tor­ji –, kot so ICL8038, XR2206 ali v zad­njem ča­su ze­lo po­pu­lar­ni MAX038, re­šu­je­jo ta pro­blem na dru­ga­čen na­čin: pri njih pra­vo­kot­ni sig­nal ni osnov­na va­lov­na obli­ka, tem­več je to tri­kot­na, ki se jo po­tem s tran­zi­stor­sko-upo­rov­nim li­mi­ter­jem pre­o­bli­ku­je v sig­nal si­nu­sne va­lov­ne obli­ke. Naš ge­ne­ra­tor te­ga ne zmo­re, ven­dar za­to pro­iz­va­ja sig­nal ze­lo na­tan­čne fre­kven­ce. Lah­ko ga upo­rab­lja­mo npr. za ka­li­bri­ra­nje ne­ke­ga ana­log­ne­ga ge­ne­ra­tor­ja ali osci­lo­sko­pa ali za mer­je­nja na raz­lič­nih na­pra­vah.

Raz­lo­ži­ti mo­ra­mo še vlo­go po­sa­mez­nih kom­po­nent, raz­po­re­je­nih oko­li kvar­čnih kri­sta­lov X1 in X2. Kot sem že raz­lo­žil, sem se odlo­čil za dve de­lov­ni fre­kven­ci: 24 in 18 MHz. Ven­dar ko sem pr­vič po­sku­sil de­lo­va­nje na 24 MHz, se stva­ri ni­so od­vi­ja­le ta­ko, kot sem pri­ča­ko­val: na­me­sto s 24, je mi­kro­kon­tro­ler za­o­sci­li­ral z 8 MHz. Ra­di­o­a­ma­ter­ji in vsi osta­li, ki so se ukvar­ja­li z VF osci­la­tor­ji, za­go­to­vo poz­na­jo raz­log: kvar­čne kri­sta­le za vi­šje fre­kven­ce vča­sih ob­de­lu­je­jo ta­ko, da ne de­lu­je­jo na osnov­ni fre­kven­ci, am­pak na ne­kem izmed har­mo­ni­kov. Ti over­ton­ski kri­sta­li so ve­li­ko ce­nej­ši, za­to je mož­nost, da bo­ste na njih na­le­te­li v tr­go­vi­ni, tu­di to­li­ko bolj ver­jet­na. Tak­šen kvarc bo to­rej osci­li­ral na osnov­ni fre­kven­ci (8 MHz), na tre­tjem har­mo­ni­ku (24 MHz) in mor­da še pri ka­te­ri fre­kven­ci, pač od­vi­sno od te­ga, ka­ko ga bo­mo vzbu­ja­li. Re­ši­tev pro­ble­ma sem na­šel na Ba­sco­mo­vi med­mrež­ni sku­pi­ni: sve­to­va­li so mi, da spo­jim pa­ra­lel­no kvar­cu upor in us­trez­no na­sta­vim vre­dno­sti kon­den­za­tor­jev v kro­gu osci­la­tor­ja. Po ne­kaj po­sku­sih je moj kvarc ve­se­lo za­ni­hal na že­le­ni fre­kven­ci. Ker ni­sem imel pri ro­ki ori­gi­na­la, mi je ce­lo uspe­lo pri­si­li­ti “na­va­dni” 6 MHz kvarc, da je za­o­sci­li­ral na dru­gi za­me za­ni­mi­vi fre­kven­ci -18 MHz. Mož­no je, da bo za nek drug kvarc po­tre­bno ne­ko­li­ko pri­la­go­di­ti vre­dno­sti R3, R4, C6 in C8. Po mo­jih iz­kuš­njah bo naj­bo­lje, če v tem pri­me­ru C5 in C7 iz­pu­sti­te. Če vam uspe na­ba­vi­ti kri­sta­le, ki ima­ta osnov­ni fre­kven­ci 18 MHz in 24 MHz, ce­lot­na opi­sa­na zgod­ba od­pa­de, kri­sta­le pa bo­ste ve­za­li na “kla­si­čen” na­čin s C5 ozi­ro­ma C7 in brez R3 in R4. V tem pri­me­ru bo­ste lah­ko z ra­hlo ko­rek­ci­jo vre­dno­sti kon­den­za­tor­jev C5 – C8 “do­se­gli” de­lov­no fre­kven­co toč­no že­le­ne vre­dno­sti – za to po­tre­bu­je­mo ka­ko­vo­sten me­ril­nik fre­kvenc. Ven­dar je tu­di brez ugla­še­va­nja na­tan­čnost za ama­ter­ske po­tre­be več kot za­do­vo­lji­va. Pri over­ton­skih kri­sta­lih pov­zro­ča­ta R3 in R4 ma­njša od­sto­pa­nja de­lov­ne fre­kven­ce od že­le­ne vre­dno­sti, sam osci­la­tor pa je ne­ko­li­ko kri­tič­nej­ši – v tem pri­me­ru s kon­den­za­tor­ji ne mo­re­mo ve­dno do­se­či toč­ne fre­kven­ce. Pa ven­dar­le od­sto­pa­nja ni­ti v tem pri­me­ru ne pre­se­ga­jo 0,1 %.

Na­čr­t ti­ska­nega ve­zja je pri­ka­za­n na sli­ki 5. Ce­lo­ten fre­kven­čni ge­ne­ra­tor je na­me­ščen na enem ti­ska­nem vez­ju. Ti­ska­no vez­ji je pro­jek­ti­ra­no za mi­ni­a­tur­ne im­pul­zne tip­ke, za­to bo­ste, če bo­ste ho­te­li upo­ra­bi­ti tip­ke dru­gač­nih iz­vedb. Ali pa eno­stav­no na­me­sti­te tip­ke na uni­ver­zal­no ti­ska­no vez­je v že­le­nem raz­po­re­du in jih po­ve­ži­te s ko­ščki ži­ce. Ra­zen kvar­čnih kri­sta­lov, o ka­te­rih smo že go­vo­ri­li, osta­le kom­po­nen­te ni­so kri­tič­ne; vsi ve­čji kon­den­za­tor­ji (C2 – C4, C9) so lah­ko z dvoj­nim (RM5) ali troj­nim (RM7,5) ra­zma­kom pri­ključ­kov.

Opom­ba: F_gen_24 in F_gen_18 sta na­pi­sa­na za Ba­scomLT, za­to v Ba­scom-8051 ne bo­sta do­bro de­lo­va­la. Raz­li­ka je prav­za­prav v na­či­nu, ka­ko ta dva pro­gra­ma shra­nju­je­ta spre­men­ljiv­ke ti­pa long v pom­nil­nik mi­kro­kon­tro­ler­ja. Ker po­sa­mez­ne byte long spre­men­ljivk upo­rab­lja­mo ne­po­sre­dno iz asem­bler­ja, smo se pač mo­ral odlo­či­ti za eno izmed ver­zij pro­gra­ma.