PIC konfigurálása 1.

    Nem akarok senkit elijeszteni, de ez a témakör nagyon bonyolult. Hála istennek, hiszen ez abból adódik, hogy a PIC-ek rengeteg dologra alakalmasak! Azért, hogy sokmindenre lehessen használni őket, tele vannak olyan regiszterekkel, amelyeket az adott feladat szerint be kell állítani. Az adatlapok sokat segítenek ebben, de első ránézésre(sőt sokadikra is), enyhe káosz uralkodik a fejekben, hogy melyik bitet, hogyan és miért. Én most arra vállalkoznék, hogy néhány példán keresztül, egy-két alkalmazási mintát felhozva, némi löketet adjak azoknak, akik most kezdenek PIC-el foglalkozni. Az se zavarjon senkit, hogy itt a 18F4320 lesz az áldozat, mert a többi PIC-et is hasonló módon kell kezelni. Az eltéréseket az adatlapokból már sokkal könnyebben lehet kihámozi.

Előkészületek:
    Amikor konfigurálni kell egy PIC-et, akkor egy adatlapot kezdünk lázasan böngészni, és jó esetben meg is találjuk azt amit keresünk, jegyzetelünk és minden rendben is van. Ekkor jön az, hogy amit megtaláltunk, valahogy a PIC tudomására kéne hozni. Mit kell tenni ahhoz, hogy a kijegyzetelt elvi adatok bekerüljenek a PIC valós regisztereibe?
MPLAB IDE:  Magyar nyelvű leírást itt találsz (Az anyag Kónya László oldaláról származik)
Talán nem meglepő, ha az MPLAB IDE fejlesztő környezetet ajánlom. Ezzel a programfejlesztő programmal lehet a forrásfájlunkat megszerkeszteni, majd .hex formátumba fordítani, hogy egy PIC programozó programmal be tudjuk tölteni azt, a PIC memóriájába.
Kezdjünk is neki!
Új project indítása után, -amit értelemszerűen néhány név és elérési útvonal megadásával kreálhatunk a középtájon található zöld ikonok segítségével-, egy forráskód nélküli ablakrendszert kapunk, bal oldalon a leendő fájljaink nevét listázó-kezelő ablakkal, benne a fájl típusoknak megfelelő mapákkal, és egy a fordítás utáni kimeneti adatokat tartalmazó, most üres ablakkal. Válasszuk ki a megfelelő PIC-et(most a 18F4320-at), a menüből, majd az "Új" ikon segítségével(fent, bal szélső) egy új szövegszerkesztő ablakot nyissunk.
Érdemes néhány karaktert bepötyögni és elmenteni ezt az ablakot az előbb kreált project könyvtárunkba, .asm kiterjesztést adva neki. (A MPLAB csak akkor tudja az
utasításokat felismerni és az egyedi színeket használni, ha a betöltött fájl kiterjesztése .asm .)  Ha ez megvan, akkor a már említett fájlkezelő ablakocskában a forrásfájl mappára(a legfelső) jobb gombbal kattintva, ki kell választani az éppen elmentett fájlunkat(Add/Tallóz). Innen már, ha Assembly parancsot ütünk be, az kikékül, és a többi szín is megfelelő lesz.  Nekiláthatunk gépelni a programunkat.

A program pedig nem mással kezdődik, mint a konfigurációval.

Lássunk egy példát egy program lehetséges felépítésre:

Az első dolgunk az fordítási beállítások megadása:

  LIST P=18F4320, F=INHX32   ;a listázás a kiválasztott PIC-nek megfelelő legyen és INHX32 hexa bináris fájl szülessen fordításkor.
  #include <P18F4320.INC>        ;a fordításhoz szükséges include fájl neve. 

konfigurációs szavak beállítása:
; .............................. Config beállítása .................................................
; A 18F-ekben a konfigurációs szó hossza 8 bit, viszont van belőle néhány.

;    __CONFIG    _CONFIG1L   Nem használt regiszter
    __CONFIG    _CONFIG1H,     b'00001000'        ;
A PIC belső oszciját akarjuk használni.
    __CONFIG    _CONFIG2L,     b'00001000'        ; Brown-out Reset disabled, Tápfeszültség csökkenés 2,7 alá, resetet okoz.
    __CONFIG    _CONFIG2H,     b'00000000'        ;
Nem akarunk WatchDog-ot használni.
;    __CONFIG    _CONFIG3L,  Nem használt regiszter
    __CONFIG    _CONFIG3H,     b'10000000'        ;
Reset lábat(MCRLE) a funkciója szerint szeretnénk használni. PortB <4:0> digit be-kimenet legyen.
    __CONFIG    _CONFIG4L,     b'10000001'        ; Nem akarok külső debuggert használni, ezért az RB6 és 7 legyen digit be-ki.
                                                                                  ; Ha STACK tulcsordul akkor RESET történjen
                                                                                  ; Alacsony feszültségen való programozás tiltva.( Low Voltage ICSP disabled)
;    __CONFIG    _CONFIG4H,  Nem használt regiszter   
    __CONFIG    _CONFIG5L,     b'00001111'        ; CODE PROTECT OFF
    __CONFIG    _CONFIG5H,     b'11000000'        ; EEPROM, BOOTBLOCK PROTECT OFF
    __CONFIG    _CONFIG6L,  b'00001111'            ; WRITE PROTECT OFF
    __CONFIG    _CONFIG6H,     b'11100000'        ; EEPROM WRITE, BOOT WRITE, CONF REG WRITE PROTECT OFF
    __CONFIG    _CONFIG7L,  b'00001111'            ; TABLE READ PROTECTION OFF
    __CONFIG    _CONFIG7H,     b'01000000'        ; BOOT READ PROTECT OFF

     
                                                            ; Nem akarunk semmilyen memóriaterületeket védeni.

Lehetőségünk van azonosító kódot beégetni a PIC-be:
;***ID Location Define

    __IDLOCS _IDLOC0, 'Ü'
    __IDLOCS _IDLOC1, 'D'
    __IDLOCS _IDLOC2, 'V'
    __IDLOCS _IDLOC3, '!'
    __IDLOCS _IDLOC4, 'W'
    __IDLOCS _IDLOC5, 'A'
    __IDLOCS _IDLOC6, 'T'
    __IDLOCS _IDLOC7, 'T'

Alap beállítások:
; Itt nevet szoktam adni a nehezebben megjegyezhető regisztereknek, és később ezen a néven hivatkozom rájuk.

;......................... Flag-ek és funkció bitek elnevezése ......................
    #DEFINE        ALL_INT_E_T      INTCON,7        ; GLOBALIS MEGSZAKITASOK ENGEDELYEZESE_TILTAS
    #DEFINE        P_INT_E_T          INTCON,6               ; PERIFERIA MEGSZAKITASOK ENGEDELYEZESE_TILTAS

;....................... PORT láb funkciók kiosztása .................................
    #DEFINE        LED_1        PORTA,0     ; ez lesz a példa ledünk
    #DEFINE        SW1            PORTA,4
    #DEFINE        SW2            PORTA,5    ; Ezek a nyomógombok
  

    #DEFINE        LED_2        PORTC,1
    #DEFINE        LED_3        PORTC,2
    #DEFINE        LED_4        PORTC,3
    #DEFINE        LED_5        PORTD,0
    #DEFINE        LED_6        PORTD,1      ; Itt néhány PIC lábat elneveztünk. Ezekkel a nevekkel lehet rájuk hivatkozni.


Makrók:

Itt előre lehet deffiniálni program részeket, amelyekre a nevükkel lehet hivatkozni. Hivatkozás esetén az itt megadott kód szerint fordítódik a gépi kód a memóriába. Fontos, hogy az itt deffiniált kódrész nem csak egyszer jelenik meg, mint mondjuk egy subrutin esetében, hanem annyiszor, ahányszor hivatkozunk rá!

;.................................. Makrók .................................................
KARAKTER    MACRO
                            BSF        LCD_KAR_UTA        ; (1)= KARAKTER
                        ENDM
UTASÍTÁS      MACRO
                            BCF        LCD_KAR_UTA        ; (0)= UTASÍTÁS
                       ENDM
(Ez itt csak egy példa, nem fogok rá továbbiakban hivatkozni.)

Állandók:
;.................................. Állandók .................................................
    #DEFINE        LED6_OFF      B'00000010'          
    #DEFINE        VÉGE              B'00000001'               
    #DEFINE        CÍM                D'129'                  ; Ezek a nevek az utánuk álló karaktersor mintáját veszik fel.
                                                                             ; A forráskódban mint szöveg helyettesítők használhatók,
                                                                             ;pl. MOVLW        CÍM    ; egyenértékű a MOVLW        D'129' -el.        

    CONSTANT    áá=00
    CONSTANT    óó=01
    CONSTANT    íí=02
    CONSTANT    őő=03
    CONSTANT    öö=04
    CONSTANT    úú=05
    CONSTANT    éé=06
    CONSTANT    üü=07                                         ; Ezek a konstansok használhatóak bájt bevitelnél matematikai műveletekbenl is.
                                                                              ; pl. MOVLW    íí+öö   ; esetén a W értéke 6 lesz. Ezt a CÍM és a VÉGE                                                                                           ; címkékkel nem lehet megtenni, mert ők karakteres mintákat tartalmaznak.                                                                                     ;  Én ezeket a konstansokat LCD karakter generálásra használtam és a táblázatba
                                                                              ; töltéskor így hivatkoztam rájuk, hogy a szöveget értsem is. pl. "K",óó,"nya"

Változók:
;................................ VÁLTOZÓ DEKLARÁLÁS ....
Ezek RAM-ban lesznek.....................................
    CBLOCK         0X0020
 

    ENDC
    CBLOCK        0X0100          ; A változók RAM kezdő címe. (lehet más is igény szerint.) Le lehet foglalni RAM területeket is,
                                                   ; amiket később Indirekt címzéssel érhetünk el. Pont ezt tettük a 0x0020-0x00FFh ig terjedő bájtokkal.
                                                   ; A felhasznált PIC-ben 512 bájt RAM van, ezzel ennek első felét lefoglaltuk.
        LCD_ADAT
        LCD_FLAG
                                    ; JELZŐ BITEKNEK
        LCD_STAT
        LCD_TEMP
        LCD_VÁR_A
        LCD_VÁR_B
        LCD_IDO_A
        LCD_IDO_B                                 ; pl. LCD hez használt változók.

        KARAKTER_DB
        CIKLUS
        MUTATÓ
        COUNTER                                    ; Táblázatokhoz használható változónevek
    ENDC


A változóneveket természetesen szabadon lehet megválasztani. Szabad használni az ékezetes karaktereket is.
Számuk csak a beépített RAM memóriától függ. A példa PIC-ben 512 bájt van.
A Funkció Regisztereknek külön memóriaterület van, az FFFh címtől lefelé, ezért ezekbe nem ütközhetünk.

Flag-ek:
;    ------------------------- FLAG DEKLARÁLÁSOK -----------------------------
    #DEFINE    LCD_FÉL_BÁJT        LCD_FLAG,0    ; A 4 bites ÁTVITELHEZ JELZŐ
    #DEFINE    LCD_KAR_UTA        LCD_FLAG,1    ; KARAKTER (1), VAGY UTASÍTÁS(0) KÖVETKEZIK

A flag-eket kétállapotú események jelzésére lehet jól használni. Mint látható, a korábban deklarált LCD_FLAG változó egyes bitjeit használjuk, ill. rendeljük hozzá egy névhez. Ezek a flag-ek egy LCD vezérlésében vettek részt, itt csak példa.

Reset és Megszakítás (INT) pontok:
;.......................RESET PONT.............................................   
    ORG    0X0000                     ; "RESET belépési pontja. Ha pl. a WDT vagy a RESET gomb aktiválódik, innen folytatódi ill.
   
GOTO    INI                        ; kezdődik a további utasításvégrehajtás.
   
    ORG    0X0008                    ; High prioritású megszakítás pont     
    GOTO    MEGSZAK

    ORG    0X0018                     ; Low priorítású megszakítás pont
    GOTO    MEGSZAK _L

A megszakításokról annyit, hogy beállíthatóan több esemény tudja kiváltani. Azt is be lehet állítani, hogy High, vagy Low prioritású pontra fusson a PC (Program Counter, Program számláló). Megszakítást tudnak okozi pl. belső számlálók(Timerek),  Soros modul (USART),  RB0  külső lábra érkező, beállítható irányú(fel, le) impulzusnak az éle, stb.
A megszakítás kiszolgálásakor az éppen futó program félbeszakad, az adatok eltárolódnak a Stack-be(verem) ill. eltároljuk őket, és átadódik a vezérlés a megszakítási pontra, ahol az a program fog lefutni, amit oda megírtunk. Ha annak vége, akkor folytatódik a félbeszakadt program futása, miután minden mentett adat visszatöltődöt ill. viszatöltöttük őket. Itt nem térek ki részletesebben erre....

Beállító regiszterek inicializálása:
; ----------------------------- Alap beállítások --------------------------------------------
INI
   CLRF    INTCON
    CLRF    INTCON2
    CLRF    INTCON3                ; KULSO MEGSZAKITAS FORRASOK LETILTVA, FLAGEK TOROLVE

    CLRF    IPR1
    CLRF    IPR2
    CLRF    PIE1
    CLRF    PIE2
    CLRF    PIR1
    CLRF    PIR2                ; MEGSZAKITASOKAT KEZELO REGISZTEREK ALAPHELYZETBE ALLITVA

    SETF    CMCON                ; COMPARATOR OFF

    BSF        INTCON2,RBPU        ; PORTB FELHÚZÓ ELLENALLAS OFF

    MOVLW    B'01111011'
    MOVWF    OSCCON                ; Belső OSC 8MHz, Nincs freki hangolás   

    MOVLW    B'00001111'            ; PORTA DIGIT I/O
    MOVWF    ADCON1


Mint említettem az első példában minden láb digitális, és nem lesz megszakítás kezelés.

Portok beállítása:
;------------------------- PORTOK BEÁLLÍTÁSA --  1 -> BEMENET, 0 -> KIMENET ------------------------------------------
    CLRF PORTA
    CLRF LATA
    CLRF PORTB
    CLRF LATB
    CLRF PORTC
    CLRF LATC
    CLRF PORTD
    CLRF LATD
    CLRF PORTE
    CLRF LATE                                ; Ki és bemeneti tárolók törlése
    MOVLW    B'11110000'         
    MOVWF    TRISB           
    MOVLW    B'10000000'          
    MOVWF    TRISC
    MOVLW    B'11110000'            ; RA 4,5 bemenet a példában használt kapcsolókhoz, PA 0 a LED-re kapcsolódik (PROTA csak 6 bites)         
    MOVWF    TRISA
    MOVLW    B'00000000'           
    MOVWF    TRISD
    MOVLW    B'11101000'          ; RE 0,1,2 kimenet,   RE3 a reset és a Vpp-n van. Gyárilag bemenet lehet csak., Párhuzamos prot (PSP) MODUL OFF !
    MOVWF    TRISE                    ; PORTE csak 4 bites

A fő Program:
;***************************************** FOPROGI *******************************************
Az inicializálás után erre kell fusson a programszál. Itt lehet megszervezni a további folyamatokat.

PROGRAM
   
DO
    NOP                                    ; "ne csinálj semmit" kérés.
    CALL      ELJÁR_SUB         ; meghívunk egy példa szubrutint.
    BRA        DO                       ; relatív ugrás parancs a DO-ra
  
Ez a fő progi nem
sokat csinál, leginkább semmit, de azt piszok gyorsan! :)

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

Eljárások
:
;......................Eljárások..................................
Ide jöhetnek azok az eljárások, amiket CALL hívással lehet meghívni.
A végrehajtás után a CALL 
ELJÁR_SUB  utáni programsorra tér vissza a PC.

ELJÁR_SUB       ; a címkéket a sor elejére kell írni.
    NOP               ; üres művelet kérés.
    RETURN        ; visszatérünk a hívóhoz.

Táblázatok:
;.....................Táblázatok..............................
A táblázatokat én a program végére szeretem tenni, de ez nem kötelező. A 18F-eknél nem kell elővigyázatosnak lenni egy tábla elhelyezésénél, mert a TBLRD utasítás előtt a pontos címet be lehet állítani a tábla pointereiben (3 db van.) (bővebben a doksikban, vagy később)

Program VÉGE:
; ezzel kell lezárni a progit
END


Azt kell mondanom, hogy a nehezén még nem vagyunk túl, de valaminek már kéne derengenie. Eddig az oszcin kívül, minden belső perifériát(érdekes, hogy a belső perifériák fogalom milyen ellentmondásos, de még is igaz.) beállítottunk úgy, hogy ne csináljon semmit, és minden portot digitális ki, vagy bemenetnek állítottunk.
Ezekkel a beállításokkal még is elég sok dolgot meg lehet oldani.
Ilyenek pl:
3 lábat bemenetnek, 3 lábat kimenetnek konfigolunk. Rákötünk egy 3*3 billentyű mátrixot, és a bemeneteket felhúzzuk 1Kohm-al +5V-ra. A 3 gomb kimenetre sorban, de egyenként alacsony szintet kapcsolunk. Ha valamelyik gomb le van nyomva és a hozzá tartozó kimeneten éppen alacsony szint van, akkor a gombhoz tartozó bemeneten is alacsony szint lesz.  Ezt kell érzékelni és megfelelően cselekedni, azaz elágaztatni a program futását, mondjuk úgy, hogy ekkor egy kimenetnek konfigolt lábon magas szint jelenjen meg, aminek hatására egy LED világítani fog. Ekkor már látható jelei is vannak a ténykedéseinknek.

Most az egyszerűség kedvéért, csak két nyomógombot fogunk használni és egy LED-et.
Egyik gombbal be, a másikkal ki fogjuk kapcsolni a LED-et.
A LED-ekről tudni kell, hogy rajtuk a gyári értéknél nagyobb áramot nem szabad folyatni, de a PIC lábain sem tehetjük meg ezt. Ezért kell alkalmazni az R1 árambeállító ellenállást. 1kohm már elegendő a LED begyújtásához, és meg-se kottyan a PIC-nek a kevesebb mint 5mA.
A gombok egyik lábát testre kötöttük, és a másikakat felhúzó ellenállásokkal +5V-ra, amik szintén 1kohm-ok. Ezek a bemeneteket folyamatosan magas(+5V) szinten tartják.
Íme a rajz:


Az SW3 kapcsoló a RESET gomb. A Programozói port illeszkedik a WPB_F18_x.xx programozóhoz, amit innen lehet letölteni.
Az R2, R6 ellenállások a programozó Vpp(13V) tápját óvják. A kondik zavart szűrnek. Az R5 a PGM lábat húzza le testre, a biztonságos programozás érdekében. A +5V-ot a jelzett programozótól kapja az áramkör. Ki-Be kapcsolni a PC programból lehet.

Akkor most lássuk a programot:
Az eddig vázoltakon nem kell változtatni a Főprogramig. Viszont az itt található ciklus magjába el kell helyezni, a két lábat figyelő és a LED-et kapcsolgató rutint. Ezt két módszerrel fogom megmutatni. Az egyiket szubrutin nélkül, a másikat szubrutinokkal.

Szubrutin nélküli program:

;***************************************** FOPROGI *******************************************
; (ezt a részt kell kibővíteni.)
PROGRAM
   
DO
    BTFSC    SW1                    ; A gomb megnyomásakor az SW1 
0 lesz. (korábban az RA4-re deffiniált nyomógom)
    BRA        J_SW2                 ; Ha nincs lenyomva, akkor a másik gombbot vizsgáljuk    
    BSF         LED_1                 ; Ha le van nyomva, akkor a LED-et bekapcsoljuk.
    BRA        ÚJRA                   ; Ha az 1. gomb le lett nyomva, akkor ebben a körben már nem vizsgáljuk a 2. gombot.
J_SW2
    BTFSC   SW2                       ; A másik gombot visgáljuk, ha az 1. nincs lenyomva
    BRA        ÚJRA                    ; Ha nincs lenyomva, új ciklusba kezdünk.
    BCF        LED_1                   ; Kikapcsoljuk a LED-et  
ÚJRA
    BRA        DO                       ; relatív ugrás parancs a DO-ra
;*************************************************************


A másik megoldás szubrutinokkal:

;***************************************** FOPROGI *******************************************
;Itt szubrutint használunk a gombok figyelésére
PROGRAM
   
DO                                           ;címke
    CALL      SW1_SUB            ; 1. gomb vizsgálatára lép
    CALL      SW2_SUB            ; 2. gomb vizsgálatára lép
    BRA        DO                       ; relatív ugrás parancs a DO-ra


;........................ Eljárások ...................................
;..................SW1 rutin ................
SW1_SUB
   BTFSC    SW1                    ; A gomb megnyomásakor az SW1(korábban az RA4-re deffiniált nyomógom) 0 lesz.
    RETURN                           ; Ha nincs lenyomva, akkor visszatérünk    
    BSF         LED_1                ; Ha le van nyomva, akkor a LED-et bekapcsoljuk.
    RETURN                           ; És utána visszatérünk

;....................SW2 rutin ..........
SW2_SUB
   BTFSC    SW2                    ; A gomb megnyomásakor az SW1(korábban az RA4-re deffiniált nyomógom) 0 lesz.
    RETURN                           ; Ha nincs lenyomva, akkor visszatérünk    
    BSF         LED_1                ; Ha le van nyomva, akkor a LED-et bekapcsoljuk.
    RETURN                           ; És utána visszatérünk

Ez a megoldás csak példának jó, ahol az eljárások meghívását és a visszatérést szerettem volna bemutatni.
 
Felmerül sok kérdés, a megoldások helyességéről. Egy biztos, hogy mindkettő működik, de nem azonos módon. Az első esetben, ha az 1-es gombot megnyomtuk, akkor a másodikat abban a ciklusban már nem ellenőrizte, sőt a nyomva tartásig a másodikat egyáltalán nem, míg a másodikban igen. Viszont egy sor elhagyásával az első példában, ez az eltérés megszűnne. (melyik ez a sor?)

A másik hiba, hogy nem vizsgáljuk, hogy a gombok csak egyesével voltak e lenyomva. Persze itt nem is érdekes, hiszen ilyen esetben a LED "villogni" fog néhányszázezer Hz-el, de egy alkalmazásban ezt nem illik megengedni. A prell mentesítést is meg lehet oldani, mert addig várhatunk a lenyomás után, amíg a gombot nem engedjük el. Ekkor viszont az elengedésig eltelt időben más programrész nem tud érvényre kerülni. De van megoldás erre is, mert a kritikus programokat megszakításból kell lekezelni, és akkor addig nyomom a gombot ameddig akarom, a többi fontos funkció továbbra is működik.
A variációk tárháza véges, de iszonyú nagy. Mindig a legoptimálisabb megoldásra törekedjünk, és csak a célnak feleljen meg a program.
Hagyjunk lehetőséget a bővíthetőségre, mert soha nincs olyan, hogy nem kell bővíteni.

A további páldákat külön doksiban fogom megírni, és e mellett lehet majd megtalálni, ha megszületnek. Ott már igyekszem komolyabbnak tűnő feladatokat megoldani.
Ha megírjátok azokat a részeket, amik nem érthetők, akkor azokon módosítani fogok.

2004.11.17.
watt
watt@gprotal.hu