Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

TUTORIJAL: xc8 i pic16F1827

[es] :: Elektronika :: Mikrokontroleri :: TUTORIJAL: xc8 i pic16F1827
(TOP topic, by veselinovic)
Strane: 1 2

[ Pregleda: 13152 | Odgovora: 20 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon TUTORIJAL: xc8 i pic16F182728.12.2012. u 23:23 - pre 136 meseci
Sledeća dva linka vode vas na dve teme koje su jako bitne za praćenje ovog tutorijala.
U prvoj temi možete naći korisne informacije vezane za razvojni sitem koji će nam poslužiti kao osnova za izučavanje PIC mikrontrolera i njihovih mogućnosti, dok u drugoj možete saznati nešto više o samoj arhitekturi i periferijama odabranog PIC16F1827 mikrokontrolera i uopšte o osnovnim pojmovima u elektronici.

http://www.elitesecurity.org/t454860-PIC-razvojni-sistem
http://www.elitesecurity.org/t453500-TUTORIJAL-PicBasic-Pro-PICF

Pratite pažljivo obe teme jer se ovde neće detaljisati o stvarima koje su tamo već rečene. Ovde ćemo obrađivati primere koje Siniša bude radio za PicBasic i eventualno dodavati nove. Za sva pitanja biće otvorena posebna tema a na pitanja ću se potruditi da odgovaram što pre. Ne zamerite ako bude manjih zastoja, jer slobodno vreme najčešće ne prati fizičke zakonitosti. Otvoren sam za sve predloge za koje smatrate da mogu unaprediti kvalitet ove teme.
No, da krenemo.
Sem razvojnog sistema sa već pomenute teme, od hardvera vam je neophodan programator, PicKit2 ili PicKit3 kao jeftina a dobra rešenja, i naravno računar. Od softverskih alata vam treba MPLAB kao IDE (Integrated Development Environment) i Microchip-ov C compiler. Oba možete besplatno skinuti sa: www.microchip.com

Trenutna verzija MPLAB IDE je v8.88 a C kompajlera MPLAB XC8 v1.12. MPLAB IDE je oduvek potpuno besplatan dok je XC8 besplatan u LITE verziji. LITE se od ostalih varijanti razlikuje po tome što su ukinute metode optimizacije veličine programskog koda. Ukoliko bi ste da probate šta to donosi PRO varijanta Microchip C kompajlera možete aktivirati 60 dana probnog korišćenja FREE varijante. Verujem da je za dobar broj aplikacija sasvim dovoljno ono što nudi XC8 LITE. Inače, XC8 podržava čitavu 8-mo bitnu PIC10/12/16/18 familiju mikrokontrolera. Istovremeno sa softverom skinite sa www.microchip.com i uputstva za MPLAB IDE i XC8. Neophodno je da najpre instalirate MPLAB IDE a potom XC8 LITE a sam postupak instalacije je veoma jednostavan i ovde ga neću opisivati.

Kreiranje novog projekta započinjete pokretanjem Project Wizard-a u okviru MPLAB IDE kako je prikazano na sledeće dve slike:
gorankg
Prikačeni fajlovi
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182728.12.2012. u 23:28 - pre 136 meseci
U koraku 1 birate tip mikrokontrolera. Kako je naš razvojni sistem baziran na PIC16F1827, odaberite njega od ponuđenih opcija.
gorankg
Prikačeni fajlovi
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182728.12.2012. u 23:29 - pre 136 meseci
Nakon toga, u koraku 2, birate XC8 compiler kao alat koji ćemo koristiti za prevođenje C programa u hex izvršne fajlove.
gorankg
Prikačeni fajlovi
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182728.12.2012. u 23:30 - pre 136 meseci
U koraku 3 vašem projektu dodeljujete ime i direktorijum u kome će biti smešten:
gorankg
Prikačeni fajlovi
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182728.12.2012. u 23:31 - pre 136 meseci
Ukoliko neki od postojećih c fajlova želite da iskoristite kao osnovu za novi projekat, možete ga dodati u vaš projekat u koraku 4.
gorankg
Prikačeni fajlovi
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182728.12.2012. u 23:32 - pre 136 meseci
Kreiranje projekta je zavrseno.
gorankg
Prikačeni fajlovi
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182728.12.2012. u 23:33 - pre 136 meseci
Jedan ili više srodnih projekata mogu činiti radnu površinu ili workspace. Sačuvajte i workspace u direktorijumu koji ste kreirali kao mesto gde će se naći svi ostali fajlovi vezani za vaš projekat.
gorankg
Prikačeni fajlovi
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182728.12.2012. u 23:34 - pre 136 meseci
Projekat se prevodi u izvršni hex fajl pokretanjem opcije Build ili pritiskom na taster F10 kao što je pokazano na sledećoj slici:
gorankg
Prikačeni fajlovi
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182728.12.2012. u 23:35 - pre 136 meseci
Poruka:

Warning [1273] ; . Omniscient Code Generation not available in Free mode

koju dobijate nakon prevođenja c programa generisana je iz razloga što koristimo LITE verziju XC8. Ne treba da vas brine previše...

Prvi program koji se „servira“ početnicima obično ne služi ničemu sem da pokaže da se nešto dešava u tom novom svetu i najčešće treba da ispiše negde ono čuveno „Hello world“ U ovom svetu mikrokontrolera to se obično postiže ritmičnim treperenjem LED diode. To će biti inaš prvi primer.

Na početku svakog programa, dobra praksa je uneti informacije o tome šta program radi, za koji je mikrokontroler pisan i koji se kompajler koristi. Taj blok opštih informacija se može nalaziti između specijalnog znaka

/* koji označava početak komentarisanog teksta i
*/ koji označava kraj komentarisanog teksta

Iskomentarisani tekst kompajler neće tretirati a služi nam da u sam c fajl unesemo nama bitne informacije. Praksa pokazuje da je jako dobro unositi što više komentara u sam program jer nakon nekog vremena stvari koje su nam nekada bile jasne to više nisu. Jednostavno, nećete se moći odmah na prvu loptu setiti šta ste pre nekog vremena želeli postići nekim nizom naredbi. To ne znači da morate komentarisati svaki red ili stvari koje su poznate ali će vam svaki naredni put iskomentarisani tekst olakšati posao. Nakraju, možda će jednog dana vaš kod morati i neko drugi da čita a to je daleko teže nego pisanje programa. Kada želite da iskomentarišete jednu ili manji broj linija to možete da uradite i korišćenjem dve kose crte, ovako:

// ovo je komentar, kompajler ga neće tretirati
Taj blok opštih informacija može izgledati kao na lici u prilogu a vi ga možete formulistai po sopstvenom nahođenju. Ipak, bilo bi dobro da isti stil zadržite i u daljem radu.

gorankg
Prikačeni fajlovi
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182728.12.2012. u 23:37 - pre 136 meseci
Nakon bloka opštih informacija na početku c programa sledi direktiva:

#include <xc.h>

Ovo je direktiva kojom se u projekat uključuje header fajl xc.h. Na osnovu toga koji tip mikrokontrolera ste odabrali (u našem slučaju PIC16F1827) kompajler će nakon poziva xc.h uključiti i odgovarajući header fajl (pic16f1827.h kod nas). Header fajl sadrži sve podatke o odabranom tipu mikrokontrolera a inače se nalazi u include direktorijumu, čija putanja može izgledati ovako:
c:\Program Files\Microchip\xc8\v1.12\include>.
Možete ga otvoriti i pogledati šta se tamo nalazi ali nemojte ga menjati.
Sledeća direktiva definiše vrednost frekvencije oscilatora. Može se desiti da nam nije neophodna ali se u našem prvom primeru koriste funkcije čije vreme izvršavanja zavisi od frekvencije oscilovanja te je neophodno definisati ovu veličinu i to na sledeći način:

#define _XTAL_FREQ 4000000 // 4MHz frekvencija internog oscilatora.

Svaki mikrokontroler ima posebne memorijske lokacije čiji bitovi ili nizovi bitova definišu rad mikrokontrolera. Ove lokacije se zovu konfiguracione reči. PIC16F1827 ih ima dve a više o njima i o njihovom značenju pogledajte u datasheet-u kontorolera. Za naš prvi primer važno je napomenuti da se koristi interni oscilator kao generator osnovnog takta na kome radi mikrokontroler i to treba definisati u konfiguracionoj reči broj 1. Moj je savet da se pri tome definišu i svi ostali bitovi konfiguracione reči 1 i 2, koji nam na prvi pogled možda i nisu od interesa, ali je bolje znati pravi sadržaj ovih lokacija. To se postiže uz upotrebu makroa __CONFIG.

__CONFIG(WDTE_OFF & FOSC_INTOSC & MCLRE_OFF & CP_OFF & BOREN_OFF & PWRTE_ON & CPD_ON & CLKOUTEN_OFF & IESO_OFF & FCMEN_OFF);

Sledeće navođenje makroa __CONFIG definiše konfiguracionu reč broj 2:

__CONFIG(WRT_ALL & PLLEN_OFF & STVREN_OFF & LVP_OFF);

gorankg
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182728.12.2012. u 23:40 - pre 136 meseci
Sledi glavni program, odnosno funkcija main().

void main(void)
{


}

Deklarisanje funkcije main kao funkcije koja ne vraća i ne uzima nikakvu vrednost nije u ovom slučaju neophodno. Može se pisati i samo:

main()
{


}

Kompajler se neće buniti, ali ipak kao preporuku dajem prednost prvom načinu pisanja.
Polazna tačka svakog programa treba da bude definisanje početnih uslova za mikrokontroler i njegovo okruženje a u našem slučaju to će biti frekvencija na kojoj osciluje interni oscilator i stanja pinova mikrokontrolera nakon dovođenja napona napajanja. To se postiže nizom naredbi:

OSCCON = 0b01101010; // 4x PLL is disabled, 4 MHz HF Internal oscillator block

TRISA = 0b11111111; // Svi pinovi porta A konfigurisani kao ulazni

TRISB = 0b11111110; // Pin RB0 konfigurisan kao izlazni. Ostali kao ulazni
LATB0 = 0; // Pin RB0 na niskom naponskom nivou.

Prva naredba definiše sadržaj registra OSCCON. Više o značenju pojedinih bitova ovog registra, naravno u datasheet-u a ovde samo informacija da smo ga ovime podesili tako da osnovni generator takta radi na 4MHz.
Osmobitni TRIS registri odgovarajućeg porta definišu ponašanje pojedinih pinova tog istog porta. U našem primeru LED dioda D1 povezana je preko otpornika od 330 Ohm-a na pin 0 porta B i da bi uopšte svetlela treba taj isti pin definisati kao izlazni. Ostali pinovi portova A i B nam nisu neophodni te ih stoga definišemo kao ulazne. Sadržaj registra TRISB ili TRISA mogli smo upisati i koristeći heksadecimalnu ili dekadnu notaciju a ovde je koriščena binarna (TRISB = 0b11111110;) zbog preglednosti. Bit najmanje težine (0) porta B je u ovom primeru postavljen na nulu što ga definiše kao izlazni. Nešto slično je urađeno i sa bitom koji definiše da li se odgovarajući izlazni pin nekog porta nalazi na stanju logičke nule ili jedinice. U ovom slučaju iskorišćen je upis u bit 0 LATB registra čime je definisan nizak naponski nivo (0V) na izlaznom pinu PORTB0. Isto dejstvo postigli bi smo i sledećom naredbom:

PORTB0 = 0;

Ipak, savet je da zbog read-modify-write svojstva pri upisu u registre PORTA ili PORTB, koristite umeto njih registre LATA i LATB. Više o ovom svojstvu možete pročitati u dokumentima na microchip.com a pisanje u LAT registre omogućava vam da izbegnete situacije sa pojavom stanja na pinovima koja zapravo niste želeli da postignete.

Sav posao koji mikrokontroler u našem slučaju treba da obavi svodi se na ritmično paljenje i gašenje LED1 pa se ono što treba da obezbedi ovu funkcionalnost smešta u okviru jedne beskonačne petlje definisane komandom:

while(1)

u kojoj sledi niz komandi kojma se pali i gasi LED1

__delay_ms(500); // 500 ms kašnjenja

LATB0 = 1; // RB0 = 1 LED dioda D1 svetli

__delay_ms(500);

LATB0 = 0; // RB0 = 0 LED dioda D1 ne svetli

Ovime je program završen uz napomenu da funkcija __delay_ms(500); definiše 500ms zakašnjenja.

Isti efekat možemo postići i ukoliko bi beskonačna petlja izgledala ovako:
Code:

    while(1)
    {
        __delay_ms(500);        // 500 ms kašnjenja

        LATB0 = ~LATB0;    

    }

pri čemu je slobodan prostor programske memorije nešto veći jer nam je i kod kraći. Kad god to možete, koristite prednosti jezika C da generiše kraći i brži kod od ostalih jezika a da vam sa druge strane ne unosi problem sa „čitljivošću“ napisanog koja postoji kod asemblera.

„Hello world“ C primer je gotov. Probajte da palite i gasite i ostale LED na razvojnom sistemu. Ustvari, neka vam zadatak, kao moj predlog, bude da ih palite redom od LED1 do LED8 sa promenljivim vremenskim intervalom između paljenja naredne diode i to tako da se uvek dodaje po 300ms. Ugasite ih obrnutim redosledom. Ali da kod bude što kraći!!!

[Ovu poruku je menjao goran_68 dana 29.12.2012. u 00:59 GMT+1]
gorankg
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182728.12.2012. u 23:42 - pre 136 meseci
Na kraju evo ovog jednostavnog primera u c fajlu.

[Ovu poruku je menjao goran_68 dana 29.12.2012. u 01:00 GMT+1]
gorankg
Prikačeni fajlovi
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182729.12.2012. u 13:07 - pre 136 meseci
Spuštanje izvršnog hex fajla koji ste dobili prevođenjem vašeg projekta na mikrokontroler radi se pomoću programatora. Već sam dao preporuku da je rad sa PicKit2 ili PicKit3 sasvim dovoljan za početak. Koliko vidim Siniša je u njegovom tutorijalu već objasnio kako se to radi pomoću PicKit2. Napomene koje je dao tamo za ICSP (upisivanje hex fajla bez vađenja iz razvojnog sistema) programiranje, važe i ovde.
Iz MPLAB IDE se to može uraditi direktno odabirom odgovarajućeg programmer ili debugger alata iz glavnog menija. Na slici ispod je prikazano kako se to radi kada želite odabrati PicKit3 kao programator.
gorankg
Prikačeni fajlovi
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182729.12.2012. u 13:08 - pre 136 meseci
Spuštanje hex fajla obavite startujući opciju Program iz padajućeg menija:
gorankg
Prikačeni fajlovi
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182730.12.2012. u 16:07 - pre 136 meseci
U primeru 2 ćemo uključiti i isključiti redom sve LED na portu B mikrokontrolera i to sa pauzom od 300ms između dva sukcesivna uključenja, odnosno isključenja. Početak je isti kao u primeru 1 pa ovde taj deo neću ponovo komentarisati. Razlika je samo u tome što su nam sada svi pinovi porta B definisani kao izlazni.
Code:

TRISB = 0;


Dodaćemo i dve promenljive i par novih komandi. Savetujem vam da u vezi sa ovim pročitate poglavlje 5.4 SUPPORTED DATA TYPES AND VARIABLES iz uputstva za XC8. U tom poglavlju dat je pregled podržanih tipova podataka, pokazano je kolike su dužine i koje su granične vrednosti svih tipova podataka. U primeru dodajemo dve linije na početku koda:

unsigned char i; - deklariše nam neoznačenu promenljivu celobrojnog tipa dužine 8 bita koja će nam služiti kao brojač i
bit DIR; - deklariše nam promenljivu dužine 1 bit koja će nam pokazivati smer kretanja paljenja i gašenja LED dioda.

Bit promenljivu DIR na početku programa ćemo inicijalizovati na vrednost 1.
Code:

DIR = 1;


Sledi bekonačna petlja u kojoj će nam se vrteti program ovaj put urađena komandom for:
Code:

    for (;;)                        // beskonačna petlja
    {

    }


umesto:

Code:

    while(1)                        // beskonačna petlja
    {

    }


Oba izraza inače rade isti posao.

Sledi deo koda koji treba da obavi ono što smo zamislili a iskomentarisan je tako da treba da bude dovoljno jasno kako radi:

Code:

        for(i=0;i<7;i++)        // sledećih 7 LED ćemo redom uključivati i isključivati
        {
            __delay_ms(300);    // sa vremenskim razmakom od 300ms

            if(DIR)                // U zavisnosti od trenutnog smera
            {    
                LATB <<= 1;        // stanje na izlaznim pinovima PORT-a B se pomera za jedno mesto ulevo
            }
            else    // ili 
            {
                LATB >>= 1;        // udesno
            }        
        }


Na razvojnom sistemu svi prekidači na SW1 treba da budu u položaju ON kako bi LED bile priključene preko otpornika R1-R8 na pinove mikrokontrolera.

gorankg
Prikačeni fajlovi
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182703.01.2013. u 22:09 - pre 136 meseci
Trećim primerom obradićemo čitanje stanja digitalnog ulaza. Za tu svrhu iskoristićemo taster TA1 koji je jednim krajem vezan na GND a drugim direktno povezan na pin 4 porta A. Dodatno, preko pull-up otpornika R24 povezan je na napon napajanja VCC. Pritiskom na taster TA1 pin 4 porta A će sa stanja logičke jedinice preći na nivo stanja logičke nule. Ta dva stanja na pinu 4 porta A nam definišu da li je taster TA1 pritisnut ili otpušten. Pojava koja prati pritiskanje i otpuštanje tastera, može uticati na ispravnost čitanja pa je treba dobro sagledati i na odgovarajući način eliminisati. Ova pojava ogleda se u poskakivanju (eng. Bouncing) signala sa tastera ili prekidača. To znači da naš signal na pinu 4 porta A za to vreme neće imati definisanu vrednost logičke nule ili jedinice pa ćemo imati lažna očitavanja. Dužina trajanja ovog prelaznog režima je različita kod različitih elemenata i zavisi od mehaničke realizacije samog elementa. Postupci za otklanjanje poskakivanja signala mogu biti hardverski ili softverski a ja ću ovde dati jedno od softverskih rešenja. Ideja kod tog načina rešavanja ovog problema je da se signal na ulaznom pinu čita u unapred određenim vremenskim intervalima. Rezultat tog očitavanja smešta se na mesto bita najmanje težine jedne promenljive koja se zatim pomera za jedno mesto ulevo. Dovoljno je da ta promenljiva bude dužine 8 bita (unsigned char) pa će za ukupno osam ciklusa ta promenljiva sadržati sve nule (0x00) ili sve jedinice (0xFF), ukoliko je signal za to vreme stabilna logička nula ili jedinica. Ukoliko je sadržaj ove promenljive različit od 0x00 ili 0xFF to očitavanje se odbacuje i ide se na novi ciklus čitanja. Osnovni period čitanja se može menjati a u primeru je postavljen na oko 1ms.
Razlika u osnovnim podešavanjima mikrokontrolera, u odnosu na prethodna dva primera, se odnosi na definisanje svih pinova mikrokontrolera kao digitalnih, bilo ulaza ili izlaza. To se postiže upisom svih nula u dva registra mikrokontrolera i to ANSELA i ANSELB. Ovo nije neophodno ukoliko se pinovi koriste kao izlazni (kao u prethodnim primerima) ali je vrlo preporučljivo da sve ova dva registra pravilno podese i to treba obaviti na početku svakog programa.
Potrudiću se da svaki novi primer donese po nešto novo i iz jezika C u odnosu na prethodne. Ovde je to drugačiji način definisanja potrebnih promenljivih tipa bit koje su sada date kao struktura.

Code:

struct
{
    unsigned TA1_STATE:1;        // status bit tastera TA1 : 1 - PRESSED, 0 - RELEASED        
   unsigned TA2_STATE:1;        
   unsigned TA3_STATE:1;        
   unsigned TA4_STATE:1;        
   unsigned fill:4;
}CTRL; 


Više o strukturama možete naći u poglavlju 5.4.4 Structures and Unions uputstva za XC8.
Još jedna razlika je mogućnost da se program učini čitljivijim definisanjem makroa koji mogu obavljati jednu ili više naredbi u nizu. Tako sada imamo:

Code:

#define LED1_ON    LATB0 = 1
#define LED1_OFF    LATB0 = 0


što ćemo upotrebiti kada želimo da uključimo ili isključimo LED1. Sam kod je dovoljno iskomentarisan tako da mislim da ga ne treba dodatno ovde komentarisati. Ima zaista puno rešenja za switch debouncing na internet stranicama. Pogledajte ih a možda ćemo i mi u nekom drugom primeru koristiti nešto drugačije od ovog.
gorankg
Prikačeni fajlovi
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182718.01.2013. u 17:23 - pre 135 meseci
Današnji primer će obraditi skeniranje stanja svih tastera na ploči i prezentovati ta stanja pomoću LED dioda na sledeći način: Stanju tastera TA1 odgovaraće vizuelno stanje LED5, Stanju TA2 LED6 itd. Pritisnut taster uključivaće odgovarajuću LED. Na razvojnom sistemu DIP SW1 od 1 do 4 moraju biti u položaju ON da bi smo aktivirali LED a ostala 4 prekidača treba da su u položaju OFF. Sa šeme se može videti da se tasteri TA1 i TA2 nalaze na portu A i to pinovima 4 i 5 a tasteri TA3 i TA4 se nalaze na pinovima 0 i 3 porta B. Stoga te pinove treba postaviti kao digitalne ulaze, dok pinovi porta B RB4 – RB7 moraju biti digitalni izlazi kako bi smo pogonili LED5 – LED8. Kako jedino taster TA1 ima na razvojnom sistemu izveden pull-up otpornik za ostala tri ulazna pina definisaćemo interne pull-up otpornike na PIC16F1827. Pull-up otprornicima svi ulazni pinovi postavljeni su po dovođenju napona napajanja na stanje logičke jedinice. Pritisak na odgovarajući taster to stanje menja u stanje logičke nule a mi treba da detektujemo promenu ta dva stanja. Evo i celokupnog koda.

Code:

/*********************************************************************
*                                                                       *
*   Filename:      kbd.c                                                           *
*   Date:          16/01/2013                                        *
*   Version:           1.0                                                 *
*   Author:        Goran Ljubic                                         *
*                                                                    *
**********************************************************************
*                                                                    *
*   Architecture:  Microchip PIC Enhanced Mid-range Core             *
*   Processor:     16F1827                                           *
*   Compiler:      MPLAB XC8 v1.12 (Free mode)                       *
*                                                                    *
**********************************************************************
*                                                                    *
*   Description:    Primer 4                                              *
*                                                                    *
*  U primeru je obradeno citanje stanja tastera TA1-TA4              *
*  i prikaz ovog stanja ukljucivanjem i iskljucivanjem LED5- LED8.   *
*                                                                    *
*********************************************************************/


#include <xc.h>

#define _XTAL_FREQ  4000000     // frekvencija na kojoj radi interni oscilator. Neophodno definisati zbog delay() funkcija

/******************************************************************************************************************************
                                                                                                                                                                        *
CONFIGURATION WORDS                                                                                                                                                *
Watchdog timer is disabled, Internal RC oscillator I/O function on CLKIN pin, MCLR/VPP pin function is digital input,             *
Program memory code protection is enabled, Brown-out Reset disabled, Power-up timer enabled,                                             *
Data memory code protection is enabled, CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin,                *
Internal/External Switchover mode is disabled, Fail-Safe Clock Monitor is disabled,                                                         *
000h to FFFh flash memory write protected, 4x PLL disabled, Stack Overflow or Underflow will not cause a Reset,                    *
High-voltage on MCLR/VPP must be used for programming                                                                                                    *
                                                                                                                                                                        *
******************************************************************************************************************************/

   __CONFIG(WDTE_OFF & FOSC_INTOSC & MCLRE_OFF & CP_ON & BOREN_OFF & PWRTE_ON & CPD_ON & CLKOUTEN_OFF & IESO_OFF & FCMEN_OFF); 
   __CONFIG(WRT_ALL & PLLEN_OFF & STVREN_OFF & LVP_OFF); 


#define TA1_OFF    RA4 == 1
#define TA2_OFF    RA5 == 1
#define TA3_OFF    RB3 == 1
#define TA4_OFF    RB0 == 1


union
{
   struct
   {
    unsigned TA1_STATE:1;        // status bit tastera TA1 : 1 - PRESSED, 0 - RELEASED        
   unsigned TA2_STATE:1;        // status bit tastera TA2 : 1 - PRESSED, 0 - RELEASED        
   unsigned TA3_STATE:1;        // status bit tastera TA3 : 1 - PRESSED, 0 - RELEASED        
   unsigned TA4_STATE:1;        // status bit tastera TA4 : 1 - PRESSED, 0 - RELEASED        
   unsigned fill:4;
    }KEY;
    unsigned char KEYS;
}CTRL;


void ReadKeys(void)
{
static unsigned char dbc[4] = {0xFF,0xFF,0xFF,0xFF};    // niz od 4 debounce promenljive
unsigned char i, mask;

    mask = 0x01;                        // pomoćna promenljiva mask kojom ćemo postavljati status bitove tastrea

    for(i=0;i<4;i++)                    // Skeniramo stanja sva cetiri tastera
    {
        dbc[i] <<= 1;                    // pri cemu se najpre pomocna promenljiva dbc pomera za jedno mesto ulevo.

        switch(i)
        {
            case 0:                        // TA1
            {
                if(TA1_OFF)                // pa ukoliko odgovarajuci taster nije pritisnut
                    dbc[i] |= 0x01;    // na mesto bita najmanje težine upisuje se jedinica.
                break;
            }
            case 1:                        // TA2
            {
                if(TA2_OFF)                    
                    dbc[i] |= 0x01;
                break;
            }
            case 2:                        // TA3
            {
                if(TA3_OFF)                    
                    dbc[i] |= 0x01;
                break;
            }
            case 3:                        // TA4
            {
                if(TA4_OFF)                    
                    dbc[i] |= 0x01;
                break;
            }
            default: break;
        }

        if(dbc[i] == 0)                // Ako je dobijeni rezultat 0x00 znaci da smo za najmanje 8 ciklusa imali
        {                                    // stanje stabilne logicke nule
            CTRL.KEYS |= mask;        // pa cemo postaviti kontrolni flag u stanje PRESSED
            dbc[i] = 0xFF;                // i odgovarajucu kontrolnu promenljivu dbc postaviti ponovo na pocetnu vrednost.
          } 
        else if(dbc[i] == 0xFF)        // Ukoliko je dobijeni rezultat 0xFF to znaci da smo imali stabilno stanje logicke jedinice
            CTRL.KEYS &= ~mask;        // i da je taster otpušten pa je kontrolni flag postavljen u stanje REALASED

        mask <<= 1;    

    }


}

/******************************
*           MAIN PROGRAM            *        
******************************/
void main(void)
{

/******************************
*        INITIALISATION                *
******************************/
    OSCCON = 0b01101010;        // 4x PLL is disabled, 4 MHz HF Internal oscillator block 

    ANSELA = 0;                 // Svi pinovi porta A onfigurisani kao digitalni I/O
    TRISA = 0b11111111;        // Svi pinovi porta A konfigurisani kao ulazni
    WPUA5 = 1;                    // weak pull-up na portu RA5 je omogućen

    ANSELB = 0;                 // Svi pinovi porta B onfigurisani kao digitalni I/O
    WPUB = 0b00001001;        // weak pull-up na portovima RB0 i RB3 omogućeni
    TRISB = 0b00001111;        // Pinovi RB0-RB4 ulazni, pinovi RB4-RB7 izlazni
    LATB |= 0b00001111;        // LED1-LED4 ugašene.
    
    nWPUEN = 0;                    // Weak pull-ups are enabled by individual WPUx latch values

/******************************
*          MAIN LOOP                *
******************************/

    while(1)
    {

        __delay_ms(1);                  // Uzimanje uzorka obavlja se svake milisekunde

        ReadKeys();                            // kada čitamo trenutna stanja svih tastera



        LATB = CTRL.KEYS << 4;            // LED5 - LED8 prate stanja tastera T1 - T4

    }
}


gorankg
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182718.01.2013. u 17:26 - pre 135 meseci
Kao što vidite ima par novina u odnosu na poslednji primer. Što se tiče hardvera PIC kontrolera to je način omogućavanja internih pull-up otpornika. Kada je reč o jeziku C ima par dodatnih stvari.

Čitanje tastature smešteno je u funkciju ReadKeys koja menja stanja status bitova za svaki od tastera.
Status bitovi koji prate stanja tastera definisani su kao polje bitova. Ovim je omogućeno da u jednom koraku promenimo (npr. CTRL.KEYS |= mask;) ili pročitamo (LATB = CTRL.KEYS << 4;) sve kontrolne bitove odjednom a ne svaki ponaosob. Dakle, kraći je kod.
Pokazano je korišćenje switch i for naredbe
Četiri promenljive koje nam služe za debounce tastera su smeštene u niz dbc[] i pokazano je kako se pristupa članovima niza.
Ovaj niz definisan je kao niz static promenljivih a više o tome u poglavlju 5.5.2.1.1 Static Variables uputstva za XC8

Evo i celog koda:
gorankg
Prikačeni fajlovi
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182704.02.2013. u 15:57 - pre 135 meseci
Iz poglavlja o primeni promenljivih tipa static jasno je da prethodni program neće raditi kako treba ukoliko niz debounce promenljivih u funkciji ReadKeys bude drugačije definisan. Ove promenljive sadrže uzorkovane vrednosti sva četiri tastera i neophodno je da zadrže svoju vrednost između dva poziva funkcije ReadKeys. Druge dve promenljive iz iste funkcije „žive“ samo unutar te funkcije pa mogu biti definisane kao:

unsigned char i, mask;
gorankg
 
Odgovor na temu

goran_68

Član broj: 89012
Poruke: 932
*.dynamic.isp.telekom.rs.



+81 Profil

icon Re: TUTORIJAL: xc8 i pic16F182704.02.2013. u 16:13 - pre 135 meseci
Naredni primer je gotovo identičan prethodnom s tim što je njime pokazano kako softverski eliminisati treperenje kontakata tastera ili prekidača a pri tom detektovati prednju (trenutak kada pritisnemo taster i kada signal na pinu mikrokontrolera „silazi“ sa logičke jedinice na logičku nulu) i zadnju ivicu (trenutak kada signal sa logičke nule ide na logičku jedinicu). Kao što sam ranije pisao ova dva trenutka prati pojava treperenja kontakata pa je u tim trenucima signal na pinu nedefinisan.
Uzorkovanje stanja sva četiri tastera se obavlja u jednakim vremenskim intervalima a u primeru je to definisano pozivom funkcije __delay_ms();
Nakon isteka tog vremena poziva se pomenuta funkcija ReadKeys() koja čita trenutna stanja logičkih nivoa na pinovima mikrokontrolera na koje su povezani tasteri TA1-TA4 i kojom se detektuju prednja i zadnja ivica.
Na isti način kao i u prethodnom primeru stanje ulaznog pina se „uvlači“ u promenljivu na mesto bita najmanje težine a cela se promenljiva pri čitanju rotira za jedno mesto u levo.
Funkcija se razlikuje od one iz prethodnog primera u delu:

Code:
if((dbc[i] | 0xF800) == 0xFC00)        
        CTRL.KEYS |= mask;            
else if((dbc[i] & 0x1FFF) == 0x0FFF)    
        CTRL.KEYS &= ~mask;


Taj deo koda ću objasniti primerom:

Ukoliko je u nekom trenutku sadržaj promenljive dbc npr.

0101 | 0100 | 0000| 0000

logičkom ILI operacijom nad bitovima u prvom if uslovu ( dbc | 0xF800 ) odbacili smo prvih pet bitova najveće težine (obeleženo crvenom bojom) kao stanja koja nam nisu od interesa jer su po pretpostavci nedefinisana.
Kada je uslov prvog if izraza:

Code:
if((dbc[i] | 0xF800) == 0xFC00)


zadovoljen znači da smo u deset poslednjih očitavanja (10ms) stanja tastera detektovali stanje logičke nule (obeleženo plavom bojom ), da je tome prethodio najmanje jedan period uzorkovanja u kome je stanje tastera bilo logička jedinica (jedinica obeležena crnom bojom ) a da svemu tome prethodi period od najmanje pet očitavanja u kome je ovo stanje nedefinisano (bouncing - crveno). Sledi zaključak da smo ovim detektovali prednju ivicu signala.
Maskama 0xF800 i 0xFC00, dužinom promenljive dbc, kao i vremenskim intervalom u kome radimo uzorkovanje ( __delay_ms(x); ) možemo fino podešavati parametre ove debouncing metode. Ovde je samo pokazan princip rada a parametre treba odabrati u skladu sa aplikacijom. Suviše duga vremena uzorkovanja mogu dovesti do toga da se pritisak na taster ne registruje a prekratka neće obaviti funkciju debouncing-a.

Zadnju ivicu signala detektujemo drugim if izrazom:

Code:
if((dbc[i] & 0x1FFF) == 0x0FFF)


Ovde je pokazano kako pomoću druge dve maske ( 0x1FFF i 0x0FFF ) postižemo da nam uslov bude 12 očitavanja (12ms) logičke jedinice, da tome prethodi najmanje jedno stanje logičke nule i bouncing od 3 čitanja koja nam nisu od interesa.
Metod sa pomeranjem stanja tastera kroz pomoćnu promenljivu je jednostavan i brz pa se može i upotrebiti i za neke brže procese nego što je pritiskanje i otpuštanje tastera.
gorankg
Prikačeni fajlovi
 
Odgovor na temu

[es] :: Elektronika :: Mikrokontroleri :: TUTORIJAL: xc8 i pic16F1827
(TOP topic, by veselinovic)
Strane: 1 2

[ Pregleda: 13152 | Odgovora: 20 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.