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