# PIC mikrokontrolleri >  PIC programmēšana push-button un LED

## jamtnt

Esmu iesācis PIC mikrokontorlieru programēšanu izmantoju Proteus un CCS C compileru.
Esmu saskāries ar tādu progrāmēšanas šķērsli: kad ar veinu push-button ieslēdz un izlēdz un ieslēdz un izlēdz LED - ka var ieslēgt ar push-button LED izmantojot to kā slēdzi.
Vai kāds var palīdzēt! Kā tādu lietu uzprogramēt?

----------


## mm

http://creativeelectron.net/blog/2009/0 ... n-proteus/

while(1) ciklā ierakstām push button aptauju (pressed / not pressed) un uz priekšu.

----------


## next

Gan jau tur veel kaadi periodiski darbi ir .
Ieviest paartraukumu no TMR0 un tajaa paarbaudiit kas atbilstoshaa ieejaa notiek.
Debouncingu taisiit ieteiktu peec taadas formulas - poga skaitaas nospiesta ja ieejaa redzams atbilstoshs logjiskais liimenis, poga atlaista ja taimauta laikaa nav konstateeta nospieshana.
Katru reizi konstateejot jaunu nospieshanu mainiit led izeju.

----------


## jamtnt

> http://creativeelectron.net/blog/2009/09/picintroduction-to-pic-by-simulation-in-proteus/
> 
> while(1) ciklā ierakstām push button aptauju (pressed / not pressed) un uz priekšu.


 īsti nesapratu tavu variantu varbūt vari kaut vai piemēra pēc kādu kodu forumā ielikt. Apskatījos tavu linku ko atsūtīji forša lapa tikai neko neatradu par ko jautāju. Cerams ka nejauc ar parastu slēdzi push-button! 

Respekt par atbildi!

----------


## jamtnt

> Gan jau tur veel kaadi periodiski darbi ir .
> Ieviest paartraukumu no TMR0 un tajaa paarbaudiit kas atbilstoshaa ieejaa notiek.
> Debouncingu taisiit ieteiktu peec taadas formulas - poga skaitaas nospiesta ja ieejaa redzams atbilstoshs logjiskais liimenis, poga atlaista ja taimauta laikaa nav konstateeta nospieshana.
> Katru reizi konstateejot jaunu nospieshanu mainiit led izeju.


 Paldies par to ka pieminēji debouncing esmu vismaz virzienu atradis kurā rakst savādāk kā pa tumsu bija ... cik nu paspēju šodien par debouncing paskatīt izskatās ka ir pat piemēri atrodami, tieši tam ko man vajag, rīt pa testēšu kādu no kodiem.

Paldies ka atbildēji!

----------


## jamtnt

#include <16F877A.H>
#fuses XT, NOPROTECT, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)

#define BUTTON  PIN_C3
#define LED     PIN_C4

#define ON      0
#define OFF     1

void main()
{
  int8  LedStatus = OFF;

   while (TRUE)
   {   
      if ((input(BUTTON) == 1) && (LedStatus == OFF))
      {
         output_high(LED);
         LedStatus = ON;
      }
      else if (input(BUTTON) == 1 && (LedStatus == ON))
      {
         output_low(LED);
         LedStatus = OFF;
      }
     delay_ms(200);
   } 
}

// Šis kods strādā pārbaudīju arī var šitā tikai ja tur nospiestu push-buttonu viņš turpina ciklu un lampa mirgo, bet vajag lai nospiežot
// pogu vai turot to vai atlaižot viņš izdara tikai vienu darbību ieslēdz vai arī izslēdz kāda nu ir tajā brīdī pie pogas nospiešanas.

Shēma Proteus ar kādu veicu testu kodam:

----------


## jeecha

Personigi uz PIC12/PIC16 nekad kodu ieksh pseido C neesmu rakstiijis, vienmeer tikai asambleraa. Bet peec analogjijas:



```
// Bufereeta polloshana galvenajaa ciklaa (vai arii uz Timer interrupta ja jaadara arii citas lietas)
output_low(LED);
int8 buttonOld= input(BUTTON);
int8 buttonNew; 
while(TRUE) {
	buttonNew= input(BUTTON); // Nolasam jauno pogas staavokli
	if (buttonOld!=ButtonNew&&buttonNew==1) { // Poga nomainiija staavokli no atlaista uz nospiestu
		if (input(LED)==0) output_high(LED) // Nomainam LED uz preteejo
		else output_low(LED);
	}
	buttonOld= buttonNew; // Atceramies kaads bija pogas staavoklis
	delay_ms(200);
}

// Pavisam vienkaarshana polloshana galvenajaa ciklaa
while(TRUE) {
	while(input(BUTTON)==0) delay_ms(200); // Gaidam kameer poga tiks nospiesta
	output_high(LED);
	while(input(BUTTON)==1) delay_ms(200); // Gaidam kameer poga tiks atlaista
	while(input(BUTTON)==0) delay_ms(200); // Gaidam kameer pogu atkal nospiediis
	output_low(LED);
	while(input(BUTTON)==1) delay_ms(200); // Gaidam kameer pogu atkal atlaidiis
}
```

 Starp citu - neaizmirsti ka atstaat ciparu mikrenes ieejas karaajoties gaisaa ir konkreeta uzprasiishanaas uz probleemaam. Tavaa sheemaa pins pie kura ir sleedzis karaajas gaisaa kad poga nav nospiesta. Vai nu iesleedz PICa pinam "weak pull-up" un sleedzi liec uz zemi nevis baroshanu, vai arii piesleedz pinam pretestiibu (piemeeram 10Komu) uz baroshanu vai zemi un tad sleedzi uz preteejo. Bez shaadas lietas sheema praksee visdriizaak gljukos (ja rodas jautaajums kaadeelj taa - google pull-up pull-down un lasi).

Starp citu - 200ms pogas polloshanai vareetu buut par daudz.  Parasti mazajiem pogu sleedzhiem kontakti tirinaas dazhas milisekundes.

----------


## next

> Starp citu - 200ms pogas polloshanai vareetu buut par daudz.  Parasti mazajiem pogu sleedzhiem kontakti tirinaas dazhas milisekundes.


 Pogas ir dazhaadas, normaalai mazaak par 50 ms taisiit nav veerts (ja cilveeks taas pogas spaida).
Izljurkaatai padomjlaika PKN-111 arii pussekunde nebija par daudz.

PS.Veelreiz gribu ieteikt - taimauts prieksh kontaktu drebelja vajadziigs tikai pie pogas atlaishanas.

----------


## jamtnt

> Personigi uz PIC12/PIC16 nekad kodu ieksh pseido C neesmu rakstiijis, vienmeer tikai asambleraa. Bet peec analogjijas:
> 
> 
> 
> ```
> // Bufereeta polloshana galvenajaa ciklaa (vai arii uz Timer interrupta ja jaadara arii citas lietas)
> output_low(LED);
> int8 buttonOld= input(BUTTON);
> int8 buttonNew; 
> ...


 
Ilgi apsvēru domu kāda valodā sākt programēt pa cik biju iepriekš strādājis C++ tad sāku arī programmēt C PIC arī.
Assembleri valodu varbūt vēlāk paprovēšu kad bilde paliks skaidrāka un saskaršos ar lietām ko nevar izdarīt ar C valodu.

Bufereeta polloshana man neaizgāja!
Bet vienkāršais variants ar while strādā ideāli - paldies par kodu.

Rezultās pie kāda CCS C compilātors strādā ir:



```
#include <16F877A.H>
#fuses XT, NOPROTECT, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)

#define BUTTON  PIN_C3
#define LED     PIN_C4

void main()
{
   while(TRUE){
      
      while(input(BUTTON)==0)
      delay_ms(100);            // Gaidam kameer poga tiks nospiesta
      output_high(LED);
      
      while(input(BUTTON)==1) 
      delay_ms(100);            // Gaidam kameer poga tiks atlaista
      
      while(input(BUTTON)==0) 
      delay_ms(100);            // Gaidam kameer pogu atkal nospiediis
      output_low(LED);
      
      while(input(BUTTON)==1) 
      delay_ms(100);            // Gaidam kameer pogu atkal atlaidiis
   }
}
```

 Vis darbojās kā gribēju. Esmu saņēmis atbildi uz jautājumu !

Tikai jārok tālāk jo nāks vēl papildus visādas darbības kas izpildās pie izslēgtas lampas un ieslēgtas - būtībā tas ieslēdz iekārtai divas funkcijas 1. ja lampa nedega un 2. ja lampa deg lai lietotājs redzētu kādā funkcijā strādā iekārta.

Paldies kas pieskāries arī elektroniskai pusei ņemšu vērā tavus ieteikumus pie plates izstrādes. Tikai kad pamainīju zemi ar barošanu vietām nekas nenotika un arī kad ieliku pretestību kā teici pie barošanas kaut kādi gļuki sākās mirgoja vai vispār nekas nedarbojās īsti vēl neiedziļinājos kāpēc tā. 
Jo patreiz strādāju pie pāšas programas izstrādes. 
Palasīšu par pullup un pulldown iespējams arī sapratīšu.

----------


## jamtnt

> Starp citu - 200ms pogas polloshanai vareetu buut par daudz.  Parasti mazajiem pogu sleedzhiem kontakti tirinaas dazhas milisekundes.
> 
> 
>  Pogas ir dazhaadas, normaalai mazaak par 50 ms taisiit nav veerts (ja cilveeks taas pogas spaida).
> Izljurkaatai padomjlaika PKN-111 arii pussekunde nebija par daudz.
> 
> PS.Veelreiz gribu ieteikt - taimauts prieksh kontaktu drebelja vajadziigs tikai pie pogas atlaishanas.


 Tās pogas spaidīs cilvēki un pārsvarā melodarbu darītāju cilvēki tad nu te ir jānodrošinās pret pilnīgi visu.

----------


## habitbraker

Nu šitais tik vienkāršai lietai, kā led pārslēgšanai strādā, bet kā var šito uzprogrammēt? :

pildās funkcija1()
piespiežot P-b, pāriet uz funkciju2() utt.
Tai pāriešanai uz 2. funkciju jānotiek arī funkcijas1() izpildes laikā.


Vai piemēram izpildās funkcija1(a), kas izmanto mainīgo a. 
Piespiežot P-b katreiz pie a pieskaitās 1, ko tālāk izmanto funkcija1(a)
Tam arī jānotiek f() izpiles laikā.

Citiem vārdiem sakot tajā brīdī, kad tiek nospiests P-b, nevis, tad kad, piemēram, while ciklā nonāk pie ieejas nolasīšanas
Ceru sapratāt.

----------


## next

Prieksh tam jau paartraukumi domaati lai katrs sev vajadziigo prioritaates hierarhiju taisiitu.

----------


## habitbraker

Varbūt mazliet sīkāk vari pastāstīt?

----------


## jamtnt

> Prieksh tam jau paartraukumi domaati lai katrs sev vajadziigo prioritaates hierarhiju taisiitu.


 
Vot arī esmu sapratis ka ar pārtraukumiem var izdarīt darbības pārselēgšanu kodā vai nu kādas daļas izlaišanu.
Vai kāds varētu kādu vienkāršu piemēru ielikt forumā, kā izmanto pārtraukšanu (interrupt)  C kodā būtu forši !

----------


## jamtnt

> Nu šitais tik vienkāršai lietai, kā led pārslēgšanai strādā, bet kā var šito uzprogrammēt? :
> 
> pildās funkcija1()
> piespiežot P-b, pāriet uz funkciju2() utt.
> Tai pāriešanai uz 2. funkciju jānotiek arī funkcijas1() izpildes laikā.
> 
> 
> Vai piemēram izpildās funkcija1(a), kas izmanto mainīgo a. 
> Piespiežot P-b katreiz pie a pieskaitās 1, ko tālāk izmanto funkcija1(a)
> ...


 Īsti nevaru saprastu kā tu domāji, bet saprotu ka kaut kā nepareizi kods uzrakstīt!

Vari kādu piemēru uzrakstīt un ielikt forumā vai pārlabotu esošo?

----------


## habitbraker

Nē tas nebij kods, bet gan vairāk vienkāršs apraksts. Sīkāk - interesē, lai piespiežot PB, pašreizējā funkcija (vienalga kāda,piemēram, delay_ms()) pārtraucas un tiek pārlekts uz citu funkciju, vai tai pašai funkcijai tiek nodots cits arguments un viss turpinātos. Ideja ir, lietas notiktu tieši PB piespiešanas mirklī (vai vismaz 1/2 s laikā). 

Tavā while ciklā tā button ieeja tiek pārbaudīta tikai noteiktos brīžos, kas nav izmantojams , ja jaizpilda kautkas garāks nekā tikai led ieslēgšana/izslēgsana



Varbūt kāds sīkāk par to interupt programmēšanu var paskaidrot?

----------


## next

C valodu kontrolieru lietaam neizmantoju.
Lai staasta tie kas zina kaa tas notiek.

----------


## JDat

Nez kā to dara lieli onkuļi, bet es savā djerevnas ASM variantā darītu tā:


```
JMP Inicializācija
JMP Pārtraukums

Timer pārtraukums:
 ja aktivējamdbounce=1 tad pārpilde=pārpilde+1

daram kaut ko citu ar regulāru laika intervālu

Return no pārtraukuma

Inicializācija:
Uzstādam PB4 kā ieeju
Uzstādam lai taimerim pārpildodies tiktu uzsaukts interrupts
Uzstādam lai taimeris pārpildās uz 1024 kvarca tikšķiem (Kvarca Freq dalīts ar 4 un vēlreiz dalīts ar 256), var arī citu, atkarīgs no kvarca un dzīves situācijas

Galvenais cikls:

ja PB4=0
       aktivējamdebounce=1
END IF

ja aktivējamdebounce=1 un pārpilde=200 tad
      ja PB4=0 tad
            poganospiesta=1
      citādi
           poganospiesta=0
     END IF
citādi
    pārpilde=0
END IF

Daram kaut ko regulāru un svarīgu cikla ietvaros

ja poganospiesta=1 tad 
        daram kaut ko pogas sakarā
        ja LED=1 tad led=0 citādi led=1
END IF

Goto Galvenais cikls
```

 Tas ir kaut kas no manām atmiņām par debounce. varbūt ātrumā kaut ko neizdomāju līdz galam, bet nu idejai:

taimeris skaita kaut kādu laika intervālu ar samērā lielu precizitāti.
Galvenais cikls dara kaut ko, kam nav vajadzīga augsta precizitāte, jo timer interrupt regulāri čakarē galvenā cikla izpildes ilgumu.

Galvenais cikls pārbauda vai poga nav nospiesta.
Ja poga ir nospiesta aktivizējam debounce procedūru un skaitam timer pārpildi.
Ja debounce procedūra aktīva un timer ir pārpildījies vajadzīgās (piemērā 200) reizes, tad pārbaudam vai poga koprojām ir nospiesta.
Ja poga joprojām ir nospiesta, tad aktivizējam pogas nospiešanas porcedūru.

Kā vienmēr neaizmirstam izslēgt visu, kas ir lieks (nomest pārpildes un vajadzīgos mainīgos).

Šitādā veidā sanāk pirmitīvs multitasking.

Katrs "lielais IF" ir savs uzdevumiņš, kurš aktivizējas tikai tad kad ir atļauts.
Svarīgi lai timer interrupt ir maksimāli īss.

Tādā veidā var samudrīt da jeb ko uz vecā labā PIC16F84A.
Protams tādā kodā var arī viegli apmaldīties ja nelirto koemntārus un nedomā līdzi.
Atvainojos par terminoloģijas kļūdām un primitīvo izklāstu.
Ceru ka ideja skaidra.

Parakšos pa cieto disku lai atrastu kādu piemēru no dzīves.

Kāpēc es tādā ķimiskā veidā daru? Vienkārši mani besī tāda lietā kā delay(0.1sec) vai kaut kas tml kur procesors ilgu laiku maļ LOOP un nedara ne ko citu kamēr LOOP nav pabeigts.

----------


## habitbraker

Paldies par atbildi, neko daudz nesapratu  :: 
Laikam jāsāk ar pamatiem. Kā notiek tas timer interupts? Par interuptu man ir tāds priekšstats - procis mierīgi pilda savu darbu un tā vietā, lai nepārtraukti pārbaudītu vai ieejā ir īstais signāls, gaida, kad dzelži paši viņam to pateiks.
Kas ar to timer pārpildi? Kā tas ir - pārpildījies vajadzīgās reizes? sorry nekad tādus taimerus un interuptus nesmu lietojis. 

Macos ASM tagad

----------


## JDat

Konkrēti par Timer interrupt.
Ja timer ir pareizi uzkonfogurēts, tad uz katru CPU clock timer pieskaita vienu (CPU clock=Crystall clock/4).
Tātad taimeris skaita uz priekšu. Bet cik tad ilgi taimeris var skaitīt uz priekšu? Ja jau timer ir 8 biti, tad skaitīs līdz 255. Kas tālāk? A ne kas. pēc 255 buus atkal 0, tad 1 utt. Bet... tiklīdz timer pārlec no 255 uz nulle, tā bits Timer overflow pārmetās no 0 uz 1... Tā tēkt lai tava programma zinātu ka taimeris ir pārpildījies. Kur to var izmantot?



```
JMP Init
kaut kas nezin kas
Init:
Uzliekam IN Out setitngus un citu drazu.

Main Loop:

Ja timer overflow uzstādīts tad
           Noresetojam timer overflow
           Tagad zinam ka ir pagājis noteikts laiks (Crystal CLK/1024)
           Daram kaut ko kas mūs interesē attiecībā uz laika intervālu
END IF

Daram vēl sazin ko
JMP Main Loop
```

 Var tā kodēt, bet...
Var arī savādāk.
Ja uzliekam ka mums uz timer overflow izsauksies interrupt...
Tad tā daļa "ja timer overflow tad..."
 izsauksies pati un mums main Loop daļā tas nav jāraksta.

Kods sanāk tāds:


```
JMP Init
JMP Interrupt
kaut kas nezin kas

Interrupt:
           Noresetojam timer overflow
           Tagad zinam ka ir pagājis noteikts laiks (Crystal CLK/1024)
           Daram kaut ko kas mūs interesē attiecībā uz laika intervālu
Return from interrupt 

Init:
Uzliekam IN Out setitngus un citu drazu.

Main Loop

Daram vēl sazin ko

JMP Main Loop
```

 Kaut ko saprati par timer un interrupt?

----------


## habitbraker

Nu sapratu sapratu principu . Paldies.
Karoch taimers skaitās paralēli/neatkarīgi no proča darbībām. Pārpildi sapratu. 

Nu piemēram. Pildās funkcija (kautkāds cikls). Kad taimerim pārpilde (ar 4mhz clock ik pēc 256 us)interupts iejaucas pa vidu. Tajā brīdī pārbaudīt vai tas PB ir nospiests? Tas neiespaidos funkcijas/cikla darbību? Un tas pirmais piemērs - pārbaudīt ciklā visu laiku pārpildes bitu nav tā pat kā visu laiku pārbaudīt to ieeju?

----------


## JDat

Ļoti apmēram tā arī ir. Lai saprastu kā ir patiesībā un niansēs patstāvīgi jāeksperimentē.

Patiesībā ir tā: ja 4 MHz kvarcs, tad  CPU tikšķis ir 1 000 000 reizes sekundē. overflow attiecīgi 256 reizes lēnāk, tik un tā tas ir pārāk daudz lai lasītu pogu un taisītu debounce. Tur vajag vēl lēnāk. Tāpēc arī bija to pārpilžu skaitīšana. Sanāk 256*4*200 pārpildes= 455 KHz kvarcs.  priekš +/- optimāla debounce, aj nemaldos

----------


## next

Lai tiktu galaa ar vairaak ka 2 procesiem (prieksh 2 pietiek vienu ielikt fonaa, otru paartraukumos) parasti izmanto operaacijsisteemas (kooperatiivaas, jo PIC kontrolieros steks programistam nav pieejams).
Tas gan vairaak aiz slinkuma - gribas vienreiz uztaisiit un peec tam vairs galvu nelauziit.

Pavisam vienkaarshoti daudzuzdevumu struktuuru var aprakstiit taa:
Fona cikla saakumaa atrodas procesu dispechers kas peec uzstaadiitajiem karogiem izveelas procesu ar visaugstaako prioritaati un nodod tam vadiibu.
Peec izpildes sanjem atpakalj.
Ja process ir ilgstoshs vai nepaartraukts tas jaasadala faazees, tekoshaa informaacija par taam ir jaasaglabaa pirms vadiibas atgrieshanas procesu dispecheram.
Shai gadiijumaa katra procesa saakumaa vajadziigs faazu dispechers kas nodod vadiibu naakoshajai faazei.

Nu un protams paartraukumi kas operatiivi reagjee un aarpasaules notikumiem, sanjem un atstaaj karogus un datus buferos sadarbiibai ar fona procesiem.

PS. Reku te var sho to no OSiem sagramstiit: http://picosa.narod.ru/

----------


## Texx

Taimera skaitītaja frekvenci var regulēt ar speciāliem bitiem. Tā var būt gan vienāda ar takts frekvenci, gan dalīta ar 2, 4 vai 8 u.t.t. atkarīgs no konkrēta mikrokontrollera. Tāpat taimeri ir gan 8 bitu, gan 16 bitu. Ir arī speciāls taimera pārtraukums uz noteiktu taimera skaitītaja vērtību, kuru var uzstādīt pēc vajadzības. Galvenais saprast principu, tad jau var piedzīt tos intervālus pēc savām vajadzībām,. Mana pieredze gan ir tikai ar Atmel, bet citiem ražotājiem jābūt arī līdzīgi.

----------


## JDat

Viss jau ir forši par multitasking, bet tam laikam vajag atsevišķu tematu uztaisīt. Nedaudz vēlāk pamēģināšu pilsonim uzbliest samērā smaluku pseidokodu, jo uzrakstīt ASM pārāk liels slinkums, bet C vispār nezinu. Kas attiecas uz timer dalītājiem, ir tāda lieta kā prescaler. Vajadzības gadījumā arī tos cilvēki lieto.

----------


## abergs

> Vai kāds varētu kādu vienkāršu piemēru ielikt forumā, kā izmanto pārtraukšanu (interrupt) C kodā būtu forši !


 Fragments  no topoša projekta pagaidām palaists PROTEUSā:
Definīcija:


```
#define setB PIN_B2			// set button (saglabā iestādījumus)
#define selectB PIN_B3			// select button (staigā pa iestādījumiem)
#define key PIN_B0				// button interrupt source
```

 Interrupts RB0:


```
#INT_EXT
void EXT_isr()
	{
	clear_interrupt(int_ext);
//	delay_ms(1);
	if (!input(key)){
		if (input_state(setB) ^ input_state(selectB)){	//fix one button
			flag.set = !input_state(setB);
			flag.select += !input_state(selectB);
			if (flag.select > 4){
				flag.select = 0;
				}	
			}
		}
	return;
	}
```

 Pogu aptauja main() funkcijā:


```
void check_but(void){
	PORT_B_PULLUPS( 0xC1 );
	clear_interrupt(int_ext);
	ENABLE_INTERRUPTS(INT_EXT );
	enable_interrupts(GLOBAL);
		delay_ms(1);
	output_low( PIN_B2 );		// set = low
	output_high( PIN_B2 );		// set = high
		delay_ms(1);
	output_low( PIN_B3 );		// select = low	
	output_high( PIN_B3 );		// select = high
	clear_interrupt(INT_RB );
	disable_INTERRUPTS(INT_EXT );
	}
```

 Kompilators CCS C ver.4.108. RB2 un RB3 tiek izmantotas arī LCD vadīšanai.Virknē ar pogām diodes atsaistīšanai.

----------


## jamtnt

> Vai kāds varētu kādu vienkāršu piemēru ielikt forumā, kā izmanto pārtraukšanu (interrupt) C kodā būtu forši !
> 
> 
>  Fragments  no topoša projekta pagaidām palaists PROTEUSā:
> Definīcija:
> 
> 
> ```
> #define setB PIN_B2			// set button (saglabā iestādījumus)
> ...


 Paldies abergs par to ka padalies ar visiem mums ar informāciju vēl pie tam no reāla projekta pie kura strādā.

Kodu paņemšu papētīšu patestēšu un ielikšu kādu proteus shēmiņu iekšā ar interrupt funkciju.

Pirmais jau ko pamanīju ka flag.set, flag.select tādas funkcijas itegrētas kompilātorā kas man ir nav nezinu kas man ir par versiju bet noteikti nav CCS C 4.108 man ir kāda vecāka biki, ja nav noslēpums un foruma noteikumi atļauj var būt vari kādu linku ielikt kur var novilkt šo kompilatora versiju. Vai arī uz e-pastu: jamtnt@inbox.lv

----------


## abergs

> kur var novilkt šo kompilatora versiju


 Pats ņēmu no šejienes:
http://kazus.ru/forums/showthread.php?t=5168&page=67



> flag.set, flag.select


 tie ir struktūras elementi - vienā baitā salikti visi "flagi".
Diezgan daudz paraugu ir :
http://www.ccsinfo.com/forum/viewforum.php?f=2

----------


## JDat

> tie ir struktūras elementi - vienā baitā salikti visi "flagi".


 Jā, to pašu triku arī es izmantoju. Saliec karodziņus vienā baitā un priecājies. Ja zin kas tas ir un kā lietot, tad patīkams sīkums. Un, galvenais, darbojas arī, pie tam ļoti labi.

----------


## jamtnt

> tie ir struktūras elementi - vienā baitā salikti visi "flagi".
> 
> 
>  Jā, to pašu triku arī es izmantoju. Saliec karodziņus vienā baitā un priecājies. Ja zin kas tas ir un kā lietot, tad patīkams sīkums. Un, galvenais, darbojas arī, pie tam ļoti labi.


 Vari kādu piemēriņu ielikt iekšā izmeklējos visu internetu zem nosaukumiem flag.set un flag.select neko neatradu vart atklāt šo foršo triku forumā arī pārējiem?

----------


## JDat

Sorry, bet asm variants (no galvas rakstīju, tā ka noteikti ir daudz sintakses kļūdu).



```
flags eq 15      'RAM adrese kur ielikt astoņus karogus

poganospiesta eq flags.0          'pirmais karogs, glabājam vai poga ir nospiesta (pēc debounce porcedūtas)
taimerisparpildijies eq flags.1  'otrais karogs, izdomāju no galvas
LEDieslegts eq flags.2              'LED karogs, norāda vai jāieslēdz LED vai nē


org 0
resetvector:
goto init

init:
'uzstādam PORTB.4 kā in mūsu pogai.
'uzstādam PORTB.5 kā OUT uz mūzu gaismas diodi

mainloop:

'testējam PORTB.4 vai mūsu poga ir nospiesta
btfss portb.4          'ja uz PORTB.4 ir LOG1, tad poga ir atlaista (izlaižam nākošo instrukciju)
goto portb4on         'šo izpildam ja PORTB.4 or LOG0, tātad poga nospiesta, citādi izlaižam
bcf flags.poganospiesta           'ierakstam LOG0 karogā poganospiesta, jo poga atlaista
goto endportb4test                  'pārlecam iz beigām
portb4on:                                'izpildam ja poga nospiesta
bcf flags.poganospiesta           'ierakstam LOG1 karogā poganospiesta jo poga nospiesta
endportb4test:

btfss flags,poganospiesta 'ja poganospiesta=1 tad pārlecam
goto pogaatlaista           'šo izpildam ja poga nav nospiesta (LOG0)
bsf flags.LEDieslegts  'ierakstam LOG1 LED karogā   'šo izpildam ja poga IR nospiesta (LOG1)
goto pogastestubeigas
pogaatlaista:
bcf flags.LEDieslegts     'ierakstam LOG0 LED karogā
pogastestubeigas:         'Pabeicam pogas un LED piesaisti

'daram kaut ko citu

'ja LED jāieslēd, tad ieslēdam
btfsc flags.LEDieslegts         '' Ja LED off, tad izlaišam nākošo instrukciju
goto LEDieslegtsON
bcf PORTB.5                'PORTB.5 ierakstam LOG0, jo LED karogs ir izslegts (LOG0)
goto endLEDieslegts     'Izejam ārā no LED slēgšanas
LEDieslegtsON:
bsf PORTB.5               'PORTB.5 ierakstam LOG1, jo LED karogs ir ieslēgts (LOG1)
endLEDieslegts:          'pabeidzam LED slegšanu

'daram citas lietas
goto mainloop
```

 Apmēram tā.
Teorētisi tāds ir primitīvs un kroplīgs pseido multitasking manā izpratnē ar karogu (vai reizēm sauc arī par semaforiem) izmantošanu. Katrs IF (patiesībā btfss vai btfsc) ir nosacīts uzdevims kurš tiek izpildīts ja ir dota atļauja (piemēram attiecīgais karogs ir ieslēgts). Ceru ka nesajucu  loģikas "polaritāti". Šitādi triki daudz jādzenā uz simulatora lai pārliecinātos ka viss ir pareizi uzrakstīts. Čakars, bet īss un strādājoš kods. Piemērā debounce nav realizēts.

PS: bija gadījums ar PIC16F57, kuram nav timer interrupt, tāpēc nācās improvizēt ar karogiem.  ::

----------


## habitbraker

Paldies par kodu Jdat.
Biški pamācījos ASM tapēc nedaudz (varbūt) sapratu
Vaitad tas PORTB.4 netiks pārbaudīts un karogi uzstādīti tikai vienā un tajā pašā noteiktā mirklī?



```
btfss portb.4          'ja uz PORTB.4 ir LOG1, tad poga ir atlaista (izlaižam nākošo instrukciju)
goto portb4on         'šo izpildam ja PORTB.4 or LOG0, tātad poga nospiesta, citādi izlaižam
bcf flags.poganospiesta           'ierakstam LOG0 karogā poganospiesta, jo poga atlaista
goto endportb4test                  'pārlecam iz beigām
portb4on:                                'izpildam ja poga nospiesta
bcf flags.poganospiesta           'ierakstam LOG1 karogā poganospiesta jo poga nospiesta
```

 Ja nu piespiežu brīdī, kad piemēram darās tās  "citas lietas", kur piemēram ir izmantotas aiztures? Tad taču nekādi karogi neuzstādīsies

Kur ir tas multitasking?

----------


## JDat

Pilnīgi pareizi! Neuzstādīsies. Tāpēc jau es čortojos par cikliem kurus izmanto aizturēm. Līdz ar to ja man vajag aizturi, tad nelietoju ciklu, bet gan timer interrupt. Gadījumā ja nav interrupt, tad at tiem pašiem karogiem (timer owerflow karogu) organizēju pārbaudi vai timer ir pārpildījies. Ja ir pārpildījies, tad kaut ko pie kaut kā pieskaitu. Ja tas kaut kas ir saskaitījies līdz noteiktam daudzumam, tad arī uzlieku karogu kautkasirnoskaitījies=1, tālāk ciklā regulāri (cik bieži prasās) pārbaudu karogu kkasirnoskaitījies, tad konstatēju ka vajadzīgā aizture ir pagājusi (kautkasnoskaitījies=1) un daru citas lietas (debounce analīze pēc aiztures piemēram), paralēli varu darīt citas lietas, piemēram mižināt LED ar dažiem simtiem HZ, kamēr notiek debounce aiztures skaitīšana. Tālēc to arī saucu par kretīnisku un primitīvu multitasking. Sarežģīti un visu laiku jāseko lai pareizie karogi pareizajā brīdi tiek pareizi uzstādīti, bet rezultātā sanāk. Tā var realižet vairākus simtus virtuālu lēnu timeru, kuri ckloku sanjem no timer owerflow notikuma. Lai samazinātu pārbaužu skaitu un palielinātu kritisku notikumu apstrāžu reakcijas laikus, lietoju interrupt, tur kur vajag. Un kā prasa labais stils, interrupt rakstu maksimāli īsu, lai tas izdara savu darbu, bet minimāli kavē pamatciklu. Protams šī ir tikai globāla teorija, katrā projektā sava specifika. Tur tad arī izdomāju kas ir kritisks, kas svarīgs un kas var pagaidīt ilgāk.

----------

