Fórum témák
» Több friss téma |
Fórum » CCS PIC Compiler
Hogy néznek ki ezek a .h és .c fájljaid? Mi van pontosan bennük? Hozzáadtad a projekthez ezeket a fájlokat is?
Amúgy találkoztam már én is ilyennel, hogy windows hibaüzenetet adott az, ha nem jól volt a forráskódban valami. A hozzászólás módosítva: Jan 13, 2014
Igyekeztem a lehető legegyszerűbb programot összeállítani, mert a lényeg az "alma.c" file kapcsolása - linkelése lenne főprogramhoz.
Ez a főprogram:
ez az "alma.h" file:
és ez az "alma.c" file:
Fordítás után a következő hibaüzenetet kapom: *** Error 112 "alma.c" Line 7(1,1): Function used but not defined: ... delay_ms 495 SCR=2882 1 Errors, 0 Warnings. Build Failed. Skipping link step. Not all sources built successfully. BUILD FAILED: Mon Jan 13 19:19:53 2014 A kérdés továbbra is az, hogy hogyan lehet több ".c" forrásfile-ból, egy működőképes programot összeállítani. Szívesen tanulnék, csak nem találom az ösvényt !
Nem teljesen értem az alma.h funkcióját. Ellenben nem látom, hogy include-oltad volna az alma.c -t.
Ha valahol azt látod, hogy
Na akkor az nem jó, .c fájlt sosem includolunk másik fájlba!
Éppen az lenne a kérdés, hogy hogyan kellene ezt helyesen beállítani. Fogalmam sincs erről az egészről. Ami információt elértem ezzel kapcsolatban abból nem derült ki mit kell tennem. Próbáltam korábban "__.c"-t include-olni, de akkor az sem sikerült, tehát éppen azt nem tudom, hogy ezt hogy lehet korrekt módon megoldani.
Igen, szintaktikailag nem szabadna, de lehet. (és működik is, nem kiabál a fordító)
Viszont az include-olt header file előbb hívja meg a led() függvényt, mint ahogy az deklarálva lenne. Vagy nem? Miért nem a header-ben van megírva?
Pedig a hibaüzenet egyértelmű, az alma.c fájl fordítása közben nem találja a delay_ms függvény definícióját. Mégpedig azért nem találja, mert az alma.c fáljban nem hoztad a fordító tudtára, hogy hol találja ezt a függvényt. Mivel CCS, ezért nem biztos, de ha jól sejtem, akkor az kellene neki, hogy az alma.c fájlba is betedd a
sorokat. Először próbáld csak az alsóval, aztán a felsővel is. ---------------- Az elmélet: minden .c fájlt a fordító külön fordít, egymástól viszonylag függetlenül. Ezért ha alma.c fájlban valami függvényt akarsz használni, ami nem magában abban a fájlban található, akkor azt a fordító tudomására kell hozni, hogy hol is találja, ugyanígy, mint ahogy a main.c-ben is
Persze lehet, meg le is fordul, de egyenes út az útvesztőbe
A hozzászólás módosítva: Jan 13, 2014
Szerintem egy kis program esetén, rövid az útvesztő ki lehet találni belőle. Egy komplex program esetén érthető...
Jobb megszokni a rendet szerintem még az elején
A volt főiskolai tanárom azt mondta:
Idézet: Van benne igazság... Egy led villogtatást inkább beírom 4x is minthogy külön .h és .c állományokat hozzak létre, még egy függvényhez is lusta vagyok. „A lusta emberek forgatják a földet!”
Az alma.c-be is be kell tenni a standard inkludokat, legalább az stdio-t. Abban deklarálódik a delay_ms és azt hiányolja a fordító a hibaüzenet szerint.
A fordító teljesen külön kezeli a c fájlokat, vagyis ha bármilyen alapfüggvényt hívsz, nem elég a főprogramban megadni. Alaptétel, hogy minden c fájl így kezdődik: #include <24HJ128GP502.h> #include <stdio.h> #include <string.h> Úgy kell felépíteni minden c fájlt, mintha az lenne az egyetlen. Közöttük a kapcsolatot a h-k jelentik. Na, még hülyeséget is írtam. Természetesen a "delay" deklarációját kell betenni a hibakód miatt, de a többi se árt. A hozzászólás módosítva: Jan 13, 2014
A lényeg, mint írtam másik hozzászólásban, hogy a fordító minden .c fájlt külön egységként fordít. A fordítás eredményeként kapott objektum kódot utána a linker veszi kezelésbe, és linkeli össze egy egésszé. Igazából nincs kiemelt főprogram forráskód, hanem az van, hogy main() függvényt teszi a fordító oda, hogy indulás után az induljon el. Egyéb szempontból semmi kiemelt szerepe nincs a main függvénynek sem.
Tehát van egy main.c, egy alma.c és egy alma.h fájlunk. A .c fájlokat hozzá kell adni a projekthez, egyéb esetben a fordítónak valószínűleg fogalma sem lesz róla, hol találja egyiket vagy másikat. Minden .c fájlba be kell includolni azokat a .h fájlokat, amikhez tartozó dolgokat használni akarunk. Tehát pl. ha késleltetéseket használunk az alma.c fájlban, akkor kell a delay_ms függvényeket tartalmazó .h beincludolása. Ha pl. színusz függvényt akarunk számolni a main.c-ben, akkor kell a math.h a main.c-be. De ha az alma.c-ben nem számolunk színuszt, akkor oda nem kell a math.h - bár épp gondot sem okoz, csak felesleges. A .c fájlokat tehát egymástól függetlenül fordítja a fordító. Akkor mégis mi alapján hívjuk a függvényt, a példában a led() függvényt? Az alapján, hogy a led() függvény az alma.h-ban deklarálva van, és az alma.h be van includolva a main.c-be. Ez alapján tudja a fordító, hogy az a függvény majd valahol ott lesz, és át kell adnia a linkernek, hogy keresse meg a függvény definícióját, és linkelje majd össze. A linker pedig jön, látja, hogy van egy hívás a led() függvényre, másik fájlban pedig ott a led() függvény maga, hát összeköti őket. Tehát .c fájlba kerül a függvény definíciója (ahol a {} is van), míg az ugyanolyan nevű .h fájlba kerülnek azon függvények deklarációi (a függvénytörzs nélkül, tehát {} jelek nélkül, csak a fejléc), amiket elérhetővé akarunk tenni másik forráskódok számára. Ami függvényt nem akarunk elérhetővé tenni, azokat nem tesszük be a .h fájlba. A másik dolog a globális változók, amiket több fájlból el akarunk érni. Fontos, hogy a váltózó csak egyik .c fájlban legyen definiálva, sehol máshol. A változó definíció egyszerűen azt jelenti, hogy lefoglaljuk a helyet a változónak. Ha ezt a változót el akarjuk érni egy másik forrásfájlból, akkor a változó definícióját tartalmazó .c fájlhoz tartozó .h fájlba bele kell tennünk a változó deklarációját, ami azt jelenti, hogy ugyanazt beírjuk, csak elé teszük egy extern szócskát. Deklaráció olyasmi, hogy csak jelezzük, hogy az a változó majd ott lesz, de nem foglalunk neki helyet mégegyszer. Tehát pl. alma.c-ben van egy szilva nevű unsigned változó, amit el szeretnénk érni main.c-ből. Akkor az alma.c-be egyszerűen beírjuk, hogy
alma.h-ba beírjuk, hogy
main.c-be bedig be kell includolnunk az alma.h fájlt. main.c fordításakor a fordító látja az extern unsigned szilva; változódeklarációt, ami kb. azt jelenti számára, hogy majd lesz egy szilva nevű változó valahol, át kell adni a linkernek, hogy ahol megtalálja, helyettesítse be. Az alma.c fájl is természetesen látja az extern unsigned szilva deklarációt, de mivel az alma.c fájlban ott van extern nélkül is, így tudja, hogy ott ugyanarról van szó. Alapesetben a globális változók csak forrásfájlon belül léteznek, és így lehet több azonos nevű globális változó is a projektben. Ha viszont valahol egyiket extern-ként deklaráljuk, akkor többé már nem lehet ugyanolyan nevű globális változó sehol máshol, mert a linker nem tudná, hogy mikor melyiket akarjuk elérni, ezért hibát fog jelezni. Ugyanígy nem lehet két ugyanolyan nevű függvényünk sem, mert akkor sem tudja, hogy melyiket akarjuk. Aztán kicsit még meg lehet keverni a dolgot a static kulcsszavakkal a függvények és globális változók előtt, de most mennem kell sörözni, esti mesének elég ennyi A hozzászólás módosítva: Jan 13, 2014
A "delay_ms" paranccsal egy kicsit tévútra vittem a témát, de az kiderült, hogy ezek szerint a "_.c" file-ok között nincs prioritás, és a kapcsolt "_.c"-ben is el kell végezni a beállításokat. Amit én szerettem volna az az, hogy egyes megírt funkciókat (pl. egy karakter kiírása, vagy egy szám konverziója) kikerüljön a fő programból, ahol minden függvénynek meg kell előznie a main() programrészt. Emiatt a program eleje és vége között egy végtelennek tűnő egér görgetés, és függvény káosz van. Azt hittem ez egyszerűbb lesz! Pl. a főprogram elején belinkelem a másodlagos c file.t, ami a csatolás helyén beolvasódik a főprogramba, együtt lefordul az egész és kész a kód. Csak ennyit akartam.
Valójában lehet, bár fordítója válogatja. Az include semmi más csak egy fájlbeszúrás. A gond az, hogy egyes kitüntetett típusú fájlokat a fordító egyedileg kezel. De ha pl. fogod az összes függvényedet a main előtt és átrakod egy alma.c1 nevű fájlba, az eredeti c-ből kitörlöd őket és beírod , hogy #include "alma.c1" közvetlenül a main elé, ha egyébként helyes sorrendben vannak a deklarációk, oda fogja befordítani a program, ahova kell. Ez csak olyan, mintha több darabba szeletelnéd a main.c-t, viszont ilyesmi a cél.
Csak ez nagyon nem ansi és roppant eretnekségnek tartják a c-s fiúk. Úgyhogy senkinek ne áruld el, hogy tőlem hallottad. Nem tudom pontosan, hogy a CCS is így működik-e, de minden általam kipróbált c-s fordítónál működött.
Köszi, ez igen alapos megfogalmazás volt!
Egy kis kiegészítés:
A függvény deklarációja nem csak azért kell a függvényt használó modulnak (.c), hogy a linker fel tudja oldani a hivatkozást, hanem a paraméterek és a visszatérési értékek kezelése miatt is. A forrásban levő eljárás(paramért_lista) sort fordítása során ismerni kell a paraméterek számát és típusát. Ezen információ alapján kell az aktuális paraméterek értékét a "stack" -re (kis teljesítményű kontrollereknél átmeneti RAM területre) tölteni. Ezek után egy hivatkozás kerül a fordított (obj) állományba az eljárás -ra, amit majd a linker felold. A visszatérés után (a C már csak ilyen) a hívó feladata a visszatérési érték levétele a "stack" ról (kiovasása az átmeneti RAM területről), ehhez a visszatérési érték típusát kell ismerni. A .h állományban vagy magában a .c állományban (ha előbb hívjuk az eljárást, mint ahogy deklaráljuk) a {} nélküli deklaráció ezen információkat adja meg a fordítónak.
Üdv simért!
rs232-t szeretnék használni 115200-on. Ezzel kapcsolatban lenne pár kérdésem: -16f688 belső 8MHz-es oszcillátora mennyire lesz jó ehhez? -jelillesztéshez max232-t használnék szokásos módon 100nF-os kondikkal. Fog ez menni ezen a sebességen? Egy routerre kellene bejelentkezni soros konzolon és ott adatokat módosítgatni.
Csak az alábbi beállítással: SYNC =0; BRG16 = 1; BRGH = 1; SPBRGH = 0; SPBRG = 16;
Ezeket az #use_rs232-nél kellene megadni? Csak mert ilyen paraméterek nincsenek a helpben (csak hasonló) ccs 5-öt használok
Illetve ha a C4 és C5-öt adom meg akkor a hardveres uartot fogja használni? Abból gondolom, hogy van egy kapcsoló, ami ezt tiltja. (Vagyis akkor ha külön tiltani kell akkor alapból a hardware-t használja)
A hozzászólás módosítva: Jan 24, 2014
Kaptam egy 2,2"-os 320x240-es lcd panelt. Úgy nézem SPI-t használ, de google nem segített az életre keltésében
Kellene hozzá valami driver, ha tudna ebben valaki segíteni. Erről az lcd-ről lenne szó.
Üdv!
Itt van hozzá adatlap, ebből mindent megtudhatsz: Bővebben: Link
Sziasztok!
Egy villogót szeretnék készíteni aminek a sebessége soros portról vezérelhető. Az alábbi kódot raktam össze:
Ez azonban csak akkor működik, ha kitörlöm a késleltetéses sorokat - amivel ugye az egész használhatatlanná válik. Hogyha benne hagyom, akkor váltogat 100 ms-enként, de semmilyen soros adatot nem vesz és nem is küld. Mi lehet a probléma?
Hali!
CCS optimiser témában lenne kérdésem. Egy 4.058-es CCS-em van. Belefutottam egy furcsa hibába. Nem értettem, hogy mi lehet a gond, aztán végső elkeseredettségemben elkezdtem kapcsolgatni az optimiser szinteket és láss csodát működött a program. #opt7-el nem müxik viszont #opt6-al már igen. Honnan lehetne azt megtudni, hogy melyik optimalizációs szint ponosan mit optimalizál? Tud ebben valaki segíteni? Köszi! Üdv: Péter
Programozz fel egy timert -t 1 ms -es periódikus megszakítás kérésre. A megszakítási rutinjában egy belső változót csökkentsen, fa a változó 0, akkor váltsa a port bitet és töltse be a legutoljára kapott időzítés értéket a belső számlálóba. A főprogram figyelje az UART -ot, vegye át a táviratot és frissítse az időzítés értéket. Még jobb, ha az uart kezelése is megszakításos, ekkor még sok-sok feladat elvégzésére használható marad a kontroller.
Köszi! A timeres megoldással működik. Viszont UARTos megszakítást nem sikerült megcsinálnom, mert Error 7 "main.c" Line 19(0,1): Invalid Pre-Processor directive hibát kapok a #INT_RDA sorra.
Megszakítást, csak a hardveres UART-nál tudsz kérni.
A software uart rengeteg féle lehet. A programhurkos időzítéssel működő nem is lesz itt jó, hiszen a megszakítás kezelése is időt vesz igénybe. Az uart időzítését is meg lehet valósítani timerrel...
|
Bejelentkezés
Hirdetés |