Fórum témák
» Több friss téma |
Értem. Mostmár egész jól alakul a dolog. Már csak azt szeretném megkérdezni, hogy szerintetek ha megkaptam a Modbus csomagot, leellenőrzöm, ha helyes elkészítem a választ és utána amikor elküldöm, akkor "karakterenként", vagy "egy az egybe" küldjem el?
Szóval:
Itt minden egyes program lefutáskor elküld egy karaktert és csökkenti a puffer számlálót. Előnye, hogy közben mással is tud "foglalkozni" a program. Azt tapasztalom, hogy a modscan programmal 100-ból 2-3 csomag timeout-tal elveszlik. Ez lehetséges azért, mert amikor bejön a soros_flag, akkor letiltom a megszakítást, kielemzem a csomagot, válaszolok és majd csak utána engedélyezem ismét az olvasást. Igazából nem tudom, hogy le kell-e tiltani a megszakítást, attól tartok, hogy válasz előkészítés közben ismét kapok egy kérést, és akkor a program elkezdi felülírni a még el nem küldött üzenetet. Vagy esetleg azért van a timeout mert a hőmérséklet érzékelők olvasásakor is le van tiltva a megszakítás és pont akkor kapok kérést?
Nem ismerem a modbus protokollt, akár mindkettő lehet, de utóbbi biztosan lehet az ok. Miért tiltod a megszakítást a hőmérők olvasásának idejére? Ha esetleg attól tartasz, hogy egymásra fut két kérés a modbus felől, akkor csinálhatsz ping-pong pufferelést. Ez azt jelenti, hogy két-két bemenő és kimenő puffert csinálsz, és felváltva dolgozol velül. Ha egy adatcsomag bejött, akkor átállítod, hogy az esetleg jövő újabb adatcsomag a másik pufferbe kerüljön, amíg ezt feldolgozod. De érzésem szerint az lesz a gond, hogy a hőmérők olvasásakor tiltod a megszakításokat.
Szia! Ha megszakításonként karakterenként veszel és megszakítással karakterenként adsz, akkor a soros port alig vesz el időt. Egy karakter beérkezésének, elküldésének ideje hosszú, nem érdemes közben ácsingózni. Így többek között a hőmérő kiolvasására is lesz idő. A kimenő puffert csak akkor töltsd fel az új adatokkal, ha befejeződött az előző megkezdett csomag elküldése(jelzők használata).
Gondolom a DS hőmérőket nem úgy használod, hogy várakozol, míg 750msec alatt elkészül a konverzió???
Természetesen nem. Flageket állítok be tmr0 megszakításban és ott növelek egy unsigned char típusú változót, ha elér 245-öt, akkor a flaget 1-be írom, jelezvén a főprogramnak, hogy lejárt a 750 ms (például) és akkor mehet a kiolvasás. Kiolvasom a ds-eket, majd törlöm a flaget.
Ez a megszakításom, a főprogramomban pedig így kezelem le:
A hozzászólás módosítva: Márc 13, 2014
Nem látom azt a részt, ahol tiltanád a megszakítást a hőmérséklet olvasás idejére. Egyébként az is csak akkor okoz gondot, ha túl hosszú ideig tiltod, hiszen ha közben jött be adat, és nem csordult túl a hardveres FIFO, akkor az rendben le fog kezelődni, amint ismét engedélyezed a megszakítást.
Igen, mert az a 1wire rutinban van implementálva.
De akkor is tiltom az usart megszakítást, ha bejött egy modbus csomag.
A hozzászólás módosítva: Márc 13, 2014
És az 1wire rutinban mikor tiltod és engedélyezed?
Az említett kódrészletben szerintem felesleges tiltani. Milyen gyakran jönnek csomagok a modbuson? Van valami előírt minimális idő az egyik csomag utolsó bájtja és a következő csomag első bájtja között?
Igazából a felügyeleti rendszerét is én fogom programozni (Vision x9), így ez elég rugalmas határok közt mozoghat, most 150ms-onként kérdezek és 100ms után van modbus_timeout.
Ez majd valószínüleg több 10s is lehet. A 1wire rutinban pedig így tiltom:
Vagy itt:
Arra gondoltam, hogy lehet célszerűbb lenne és átláthatóbb, ha a bejovo_puffer és kimeno_puffer helyett valami ilyesmit csinálnék:
És így nem a pufferhosszt növelgetném bejövő karakterenként, hanem a megfelelő változókat tölteném fel. Csak ezeket a megszakításban hogy? A hozzászólás módosítva: Márc 13, 2014
De jó lenne, ha valaki tudna segíteni rajtam. Egy 16f628 PIC-kel küzdök, aminek egy szenzor adatait kellene megjelenítenie egy 2*16 karakteres LCDn. A baj a következő: A szenzor küld 40 bit adatot (amelyből az első 16 bit a pára értéke (0-999 közti érték, melyet 10-el osztva megkapjuk az értéket egy tizedes pontossággal), a második 16 bit a hőmérséklet, majd az utolsó 8 bit az ellenőrző kód).
Nekem ott van a bajom, hogy az ellenőrzés lefut, minden rendben. Viszont a kijelzőn minden 25.5-es érték után 0.1 következik. Tehát pl. 25.6 fok az 0.1 foknak írja. És így van ez a páránál is, 25.5-enként átfordul. Ez biztosan abból van, hogy a RH_Byte1 illetve T_Byte1 adatait nem használja. Pedig megkapja, mert az ellenőrzés nem talál hibát. Ime a kód:
message1 [10]- hőmérséklet érték tizes helyiérték message1 [11]- hőmérséklet érték egyes helyiérték message1 [12]- pont (definiálva) message1 [13]- hőmérséklet érték tizedes helyiérték és a páránál hasonlóképp (message2). A T_Byte1 és RH_Byte1 azért van 256-al szorozva, mert ezek a 16 bites számnál a felső 8 bit, így első bitjük az 2 a nyolcadikon (256). A sorok végén lévő +48 pedig az ascii kód miatt van (48 érték egyenlő a nullával). Tudna valaki valamit mondani arra, hogy miért nem játszanak szerepet a felső 8 bit adatai a kódban?Próbáltam záró jellel is az sem segített. A hozzászólás módosítva: Ápr 13, 2014
Két dolog is lehet:
- egyrészt a C a műveletek eredményét is annyi biten képzni, ahány bitesek az operandusok. Namost ha az RH_Byte1 is és a 256 is nyolc biten szerepelnek, akkor az eredmény is 8 bites lesz, vagyis gyakorlatilag levágja azt, ami az értelme lenne az egésznek. Ha azt írod, hogy 256U, azzal kényszeríted, hogy 16 bitesnek értelmezze a 256-ot, és így az eredményt is 16 biten képezze. Esetleg írj 256UL-t, ha a 256U nem elég. Bár nem tudom, mi a helyzet, ha az operandus eleve nem fér el 8 biten, mint ez esetben a 256 - másrészt nem maradt ki onnan egy zárójel? Mert ha a message tömb 8 bites elemekből épül fel, akkor hiába számolunk 16 biten, ha a végén az eredményt úgyis levágjuk. Valahogy így kellene szerintem:
Köszönöm a választ. Délután ki is próbálom (most épp melózom). Van logika abban amit mondasz. Én úgy gondolom, hogy a fenti számítás ad egy értéket (16 biten, mert csak úgy fér el) ehhez hozzáadjuk a 48-at, ami eredményként egy decimális számot eredményez (szerintem valahogy így kellene), ami megfelel valamely ascII kódnak 0-255-ig (8 bites). De lehet igazad van abban, hogy akkor mikor beírjuk a tömbbe levágjuk a 8 bit felletti részt. Esetleg valahogy úgy lehetne, hogy előtte a 3 helyi értéket meghatározzuk külön-külön, majd ezt tároljuk egy 8 bites változóban, és ezt írjuk a tömbbe. Csak azt nem tudom, hogy ha pl. egy 16 bites számot osztok mondjuk 100-al (ami 8 biten elfér), hogy tudom megadni, hogy az eredmény 8 bites legyen (tudom alapból 16 bites lesz)?
Próbáld ki először, amiket írtam, a zárójelek és a 256U hozzáadásával szerintem jó lesz. Ha véletlen nem, akkor majd megyünk tovább.
Idézet: „Csak azt nem tudom, hogy ha pl. egy 16 bites számot osztok mondjuk 100-al (ami 8 biten elfér), hogy tudom megadni, hogy az eredmény 8 bites legyen (tudom alapból 16 bites lesz)?” A C automatikusan levágja a felső 8 bitet róla, ha egy 8 bites változóba akarod belerakni az eredményt. A hozzászólás módosítva: Ápr 14, 2014
Köszönöm a segítséget, jó lett. Már programozom a két szenzoros változatot.
Idézet: Ez igy pontatlan. A muveletben szereplo operandusokat egyforma tipusuva konvertalja ugy, hogy a nagyobb bitszamu operandust veszi alapul. (es meg ez sem egeszen pontos igy...) Tehat egy int es long eseten, elobb az int-et long-ra konvertalja. A char-t es short-ot automatikusan mindig int-re konvertalja, float-ot mindig double-re. Ha signed es unsigned keveredne, a signedbol unsigned lesz es az eredmeny is az lesz. Ha integer es float keveredik, akkor az egesz muvelet float lesz (double). K&R 2.7 fejezet.„egyrészt a C a műveletek eredményét is annyi biten képzni, ahány bitesek az operandusok.” Idézet: „Namost ha az RH_Byte1 is és a 256 is nyolc biten szerepelnek, akkor az eredmény is 8 bites lesz” A konstanskent leirt 256 az int lesz, de meg az 1 is. A 256u csak annyit tesz, hogy unsigned int, semmit tobbet. Az eredei problemara meg nagyon egyszeru a valasz: A C nyelvben az operatoroknak precedenciajuk van, ezert a vegrehajtasi sorrend nem feltetlenul balrol jobbra halad. A fenti peldaban az RH_Byte1 * 256 + RH_Byte2 / 100 + 48 azt csinalja, hogy megszorozza 256-tal RH_Byte1-et, aztan RH_Byte2-t elobb elosztja 100-zal, majd hozzaadja az elobbi szorzas eredmenyehez, majd ehhez meg hozzad 48-at. Mindezt 16 biten csinalja, csak a legvegen konvertalja 1 byte-osra az eredmenyt. A helyes sor: (RH_Byte1 * 256 + RH_Byte_2) / 100 + '0'; Az '0' az ugyanaz, mint a 48, csak igy szemleletesebb, hogy itt a 0 ASCII kodjarol van szo.
Sziasztok!
Hogyan tudom azt megcsinálni, hogy egy 7szegmenses kijelző szegmensei két különböző portra van kötve, de egy változóval tudjak rá hivatkozni? Valami struktúrára gondoltam, de nem tudom hogyan lehetne c-ben megvalósítani.
Írj rá egy függvényt, mert a portokat nem lehet struktúrába szervezni.
Esetleg makrót lehetne még, de az nagyon pazarolja a helyet a program memóriában, mert minden alkalommal több sort fordít be. Egy jó függvény egyszerűvé teszi a szabdalt portlábak kezelését program áttekinthetőségi szempontból, csak egy értéket adsz át neki és kész.
Értem. Elkezdtem már a függvényt megírni rá! Köszi!
Üdv!
Most váltanék Assembly-ről C-re a környezet: MPLABX v2.05 +CCS-C 5.011. MPLAB látja is a fordítót, de nem tudja értelmezni már delay_ms parancsot sem
Erre a kódra azt mondja: Unable to resolve identifier delay_ms. Úgy sejtem hogy az IDE-ben van valami rosszul beállítva vagy nem include-oltam be valamit amit kéne? Köszi.
Sziasztok!
Van egy kis problémám a C18-al és nem tudom, hogy mitől lehet ...?! A változók definiálásánál adtam nekik kezdőértéket, de mintha nem vennék fel rendesen ( nem tudom jobban kifejezni )! A program néha elindul megfelelően, néha nem... Ha ugyanezeknek a változóknak a program elején külön megadom a kezdőértékeket, akkor megfelelően megy !? Ha a programozó rajta van, akkor a deklarációs változat is elég, ki- és visszakapcsolva a tápot működik rendesen ( külön tápról megy!), de ha lehúzom a programozót, akkor már nem indul stabilan. Amennyiben beillesztem a külön inicializáló részt, akkor jól működik ( LVP letiltva, MCLR felhúzva, RELEASE módban fordítva ) ! Mondjatok valami ötletet, mert így most jól megy, de nem értem, mit nem veszek észre ! Előre is köszönöm az ötleteket!
Biztosan a változók miatt van? Nem lehet, hogy valaminek pont annyi idővel kell több a felépüléshez, amennyi a változók újradeffiniálásához kell? (teszteld egy időzítés beszúrásával).
Elég időt hagysz a ki és bekapcsolás között, hogy a táp teljesen megszűnjön(RAM kiürülése)? I2C eszközök nincsenek vonalon, amiknek szintén több táp szünet kell egy sima ki-be kapcsolásnál(kondik)?
Próbáltam több időzítést, nem működött. I2C nincs a rendszerben !
Idézet: „lég időt hagysz a ki és bekapcsolás között, hogy a táp teljesen megszűnjön(RAM kiürülése)” Pont ez a gond, ha meg tudott szűnni egy működő fázis után, akkor a "normál" inicializálás nem elég neki! Most nem volt időm vele többet foglalkozni ( már jó ideje ezzel szívtam! ), most így működik, de utána akarok járni, mert nem értem, hogy mi a gond, ezért kérnék ötleteket! Köszi az eddigi segítséged !
Közben megtaláltam a megoldást. Leírom hátha másnak is segít: MPLAB->Tools->Options->C/C++ fül-> Highlight Unresolved Identifiers és akkor most már nincs pirossal aláhúzva a fél kódom. Bár ez csak tüneti kezelés jó lenne ha értené az MPLAB és akkor talán még színezné is.
Ha jól emlékszem a startup állomány végzi az inicializált adatok feltöltését. A linker vezérlőben milyen startup van megadva? A névben az i utal az inicializálásra: pl. c018i.o
A C forrásban milyen szekcióban deklaráltad őket? ... idata ...
Köszi a segítséget!
Azt látom a "MPLAB® C18 C Compiler User’s Guide"-ban (még most kezdtem el nézegetni, 2.9.1.2. fejezet ), hogy ha adok neki kezdőértéket, akkor az idata-ba kerül, ha nem, akkor az udata-ba !? Illetve ahogy nézegettem, úgy láttam, hogy már nincs ilyen c018i.lkr, hanem c018g.lkr van, amit úgy értelmeztem, hogy az előbb leírtaknak megfelelően pakolja be az adatokat ( persze nem vagyok benne tuti ! ). A linker vezérlőt egyébként hol kell beállítanom ( a projekt *.lkr útvonalánál ?) ? |
Bejelentkezés
Hirdetés |