Fórum témák
» Több friss téma |
Fórum
Viszont, ha mindig az adási puffer kerül a shift regiszterbe, és mondjuk nem írtam bele semmit se, akkor mi megy ki? 0?
Az errata-ban csak annyit említenek az SPI kapcsán, hogy van egy parazita órajel, a modul engedélyezésekor, master módban. Más semmi... Közben kipróbáltam átkonfigurálva SPI2-re. Ugyanez a jelenség...
Igen, az világos, hogy egyszerre tud adni és venni is, csak számomra az nem világos, amikor nem küldenék vissza semmit sem direkt, akkor az eredeti vett adatok shiftelődnek ki vissza, vagy mindig, mindenkor az SPIBUF adási puffere megy ki vissza?! Bár ez utóbbinak nem sok értelmét látnám...
Nem, nem jó az adat a master oldalon, hiszen ha jó lenne a vétel, akkor nem tudnék a problémáról sem ![]() ![]()
Küzdök itt egy SPI kommunikáció megvalósításával.
Adott egy PIC(dsPIC33EP32GS504), melyet slave üzemmódban van. A jelenség a következő: ha masternak konfigurálom, működik jól, a kiküldött adatok szépen ki is mennek. Ám nekem slave kell. Ekkor viszont az van, hogy befelé fogadja jól az adatokat, viszont kifelé nem tudok semmi értelmeset sem küldeni. Mintha csak valamiféle szemét menne ki a vonalra. Sőt, már abban sem vagyok biztos, hogyan kellene működnie az SPI perifériának?! Tehát, azt gondolnám, hogy a shift regiszterbe kerülő bitek, az órajel hatására 8 órajel múlva meg kellene jelennie a kimeneten is, mintegy visszakapva a küldött adatot késleltetve. Ekkor ugye minden 8. órajelre a shift regiszter tartalma beíródik az SPIREG vételi pufferébe(vagy jelen esetben a 8 szintű fifo-ba). Ez elvileg tiszta sor. De mi történik a másik iránnyal? Ekkor szerintem, ha írás történt az SPIREG-be, akkor gondolom az megy tovább a shift regiszterbe, felülírva a korábban beérkezett adatot. Ami nem világos, ez mindig meg történik, vagy csak akkor, ha volt előtte beleírva valami adat, ha viszont nem, akkor ilyenkor nem íródik felül a shift regiszter tartalma? Próbáltam az inicializálás után azonnal feltölteni az adási fifo-t ismert adatokkal, amit elvileg vissza kellene kapjak a SDO-n, amikor adatokat fogadok a PIC-el(amit jó vesz is), de csak valami szemét szerűséget kapok... Van valakinek ötlete, mi lehet az oka?
Én 16 bites PIC-eket programozok, jellemzően dsPIC33E sorozatúakat. De korábban 18F-eket programoztam, azok valóban lényegesen gyorsabban debuggolhatóak PICkit3-al is, és ott nálam sem kellett ki-be dugdosni. A 16 bitesek PICkit3-al már nem olyan szép világ sajnos.
Másrészt a Watch ablakban nálam kB-nyi, sokszor több tíz kB-nyi változót jelenítek meg. (UART vételi tömbbök, struktúra-fifo-k, gyűrűs bufferek stb.) És valóban, a maximum 3db töréspont sokszor kevés tud lenni. ICD4-nél annyit töréspontot használok amennyit akarok. Mondjuk lehet hogy ez az ICD3-nál is így van, nem tudom. A hozzászólás módosítva: Jan 3, 2018
Hát egy kicsit sikerült egybedarálni az ömlesztett vegyes felvágottat, de azt hiszem, értem a kérdés lényegét.
A lényegre válaszolva, adási irányban is használhatsz megszakítást, ha igényled, de akár elhagyható is. A megszakítás lényege, hogy időben olyankor van adat kezelési kényszered, amíg talán másvalamit csinál a főciklusod, ami mégsem ülhet ölbe tett kézzel egész nap arra várva, mikor fog vagy nem fog adat érkezni. Szóval fut a főciklus, és majd foglalkozik az adattal, amikor jön. Ha a beérkező adat olyan helyre kerül, ahol tuti nem fut rá a következő adat addig, míg a főciklus kényelmesen végig fut, akkor megszakításra semmi szükség nincsen. A főciklus elérkezik oda is, pollozással ránéz az adattárolóra, és kiveszi az adatot. adási irányban az annyit jelent, hogy betölti. Megszakítás használatával egy kicsit gyorsabb lehet a kommunikáció egyes esetekben. Pic32-esekben például van vagy 4 byte-os uart buffer, és azt akár ha 115200-al hajtod is, a 32 bit eltart 270 uSec ideig, míg kimegy, annyi idő pedig temérdek sok egy főciklusnak végig futni, ami normálisan van megírva, és tuti nem kap blokkot sehol sem. A probléma akkor kezdődik, amikor valamelyik komponens low quality. Szóval adásnál is meg lehet tenni, hogy jelezze csak interrupt, mikor kell rá figyelni. Az adatbufferek felépítése gondolom nem fog gondot okozni, a trükk csak a megszakítási flagek kezelése. A megszakítási engedélyt a főciklus kapcsolja be, amikor pld első alkalommal azt látja, hogy hiba flag van jelezve valami statikus változóban. Például a device reset alapinit kapcsolhatja azt be első alkalommal, később pedig az utolsó uart transmit interrupt. Amikor a főciklus azt látja, hogy az adat küldő gépezet le van halva, és adatokat rak éppen a kimeneti bufferbe, első alkalommal "bebikázza" az adat küldést: kikapcsolja a hiba flaget, visszakapcsolja az interruptot, és utána az első byte-ot saját kezűleg tölti át a kimeneti regiszterbe. Később az interruptok majd beszipkázzák a többit. Az utolsó byte után olyan interrupt fog érkezni, ami nem fog adatot találni a kimeneti bufferben, olyankor az interrupt rutin tiltja le a saját további élezését, és kapcsolja fel a hiba flaget a főciklusnak jelezni, hogy ha lesznek még kimeneti adatok, újra be kell majd indítani a küldési gépezetet. Van olyan lehetőség is pld uu64 kommunikációnál, hogy az uart saját magát tömi 0x00 byte-okkal, amikről a túloldal tudja, hogy nem értékes byte-ok, és csak dobálja el őket. De az nem valami elegáns megoldás energetikailag. Az persze az egyik előnye, hogy olyan módon sosem kell interrupt engedélyezést kapcsolgatni, csak egyszer felkapcsolni, és had fusson, mint ahogy az is előnye, hogy külön kontrol és adat csatorna szervezhető úgy az uart kommunikációra. Ha éppen olyasmit bütykölsz, azt a megoldást is választhatod. Nagyjából érthető a flow control?
UART adási megszakítás kiszolgálása:
- Ha van adat az adási pufferben, ki kell venni az adatot a pufferből, el kell küldeni a soron következő adatot az UART -nak. - Ha nincs adat az adási pufferben, le kell tiltani az UART adási megszakítás kérését. Az adási puffer beírásakor az adatot be kell tenni a pufferbe és engedélyezni kell az UART adási megszakítás kérését.
pajti2 egy más irányú kérdés, ha már az asszinkron állapotgép és a fifo bufferelés szóba jött.
Vegyünk egy UART kommunikációt, az adatok fogadása logikus interrupt és pakolni bele a fifo-ba az adatokat (vagy épp DMA-val interrupt helyett) és amikor oda érek ki olvasni. Na de a küldés annak is az lenne inkább a megfelelője while(!TRMT); TXREG = data; helyett, hogy be kapcsolom a TXIE-t és küldéskor a fifo-ba bele dobom az adatok[cim+1]-et majd a 0. adatot beírom TXREG-be és utána az interrupt végig küldi az adatokat (vagy itt is DMA interrupt helyett)?
A megszakítási rutin elegáns esetben megszakítási "alsó fél". A teljes programod egy darab hatalmas nagy aszinkron állapot gép, aminek az alkalmazás szintű rutinjai végzik a megszakítási "felső réteg" teendőit. A két fél statikusan elég nagyra szabott memória buffereken (pld fifo) kommunikál egymással. A megszakítási rutinból csak az adatot veszed át attól a hardvertől, ami nem tudja azt sokáig tárolni, és berakod memória bufferbe "becsomagolva" minden olyan szükséges másodlagos adattal, ami ideális adatcsomaggá ki tudja azt egészíteni, hogy következő lépésben már absztrakt szinten kezelhesd az adatot. A megszakítási rutinban nem csinálsz mást. Ha az adatot átvetted, memória csomagot készítettél belőle, beraktad a fifoba / akármibe, _akkor_ törlöd az IF-et, és utána már csak visszatérsz a megszakítási rutinból.
Hmm, halványan emlékszem csak valami említésre az interrupt kezelésről, hogy az interrupt jelző flag törlése utáni utasítást még nem szakítja be következő interrupt akkor sem, ha már tűkön ülve várakozik. Ha asm szinten nincs ott más az interrupt engedélyezés után, csak egy return, akkor a következő interrupt nem "ütközik bele" az előzőbe. Ha jól sejtem, az jár a fejedben, hogy olyan sűrűn jönnek egymás után az interruptok, hogy végül túlcsordul a verem a sok egymásba futott interrupt miatt. A hozzászólás módosítva: Aug 13, 2017
A szintaktikát ne kérjétek számon rajtam, mert nem tudok C-ben programozni, de azért remélhetőleg érthető, mit javasolok.) ![]() A hozzászólás módosítva: Aug 8, 2017
Én meg arra gondoltam hogy létrehozok egy külön C fájlt amelyben karakterláncokat hozok létre a programmemóriában. A karakterlánc-konstansokat (nem is tudom helyes-e ez a megnevezés) melyek jelenleg a függvények bemeneti paraméterei közt aposztrófok közt szerepelnek, kicserélem az újonnan létrehozott C fájlban lévő megfelelő const char tömb címére.
Azaz, a C fájlban:
Az eredeti fájlban pedig:
Szerencsére van a panelon egy 128kB-os SRAM, a fifo-kat kipakolom bele. Így kb 17kb memória felszabadul a PIC-ben.
Először is van egy struktúrám amelyben adatokat tárolok, összesen kb 60 bájtnyit. Ebből a struktúrából van létrehozva egy 200 elemű fifo tömb, ebben pufferolja a PIC a küldendő adatokat ha épp nincs mobilnet. Na ez a fifo már kb 12kB.
Négy UART-ot használok, mindegyiknél van egy-egy vételi puffer melyek közül némelyik 500 elemű, némelyik 1000. És mindegyiknél dupla pufferelés van, a sikeres és befejeződött vétel eredménye egy másik pufferba kerül hogy a következő vétel ne tudja felülírni. A WIFI modulnál ezen felül van egy 2048 elemű char tömb is az érkezett IPD üzenetek tárolására. Van két 500 elemű amelyeket arra használok hogy sprintf()-el, strcat()-al és hasonlókkal szövegeket hozzak létre, illetve ezeket átalakítsam pl linkké. (A szóközből %20 lesz stb…). A mikrovezérlő a GSM modullal meg a WIFI modullal e-maileket is küld, viszont az e-mail megszületésének pillanatában lehet hogy épp nincs mobilnet ezért van egy 1000 elemű tömb amely egy szem e-mail tárolására szolgál. Van egy 200 elemű amely hasonlóképp egy SMS tárolására használatos. (A problémám egyébként pont az hogy ennek a méretét szeretném 200-ról 500-ra megnövelni hogy három egybefűzött SMS is beleférjen.) Van még kb 100-200 bájtnyi egyéb kisebb, nem sztring tárolására használatos statikus változó is. Lokális változóból jó kérdés hogy mennyi van. Azért nem tudok itt minden esetben pointereket használni, mert például a soros porton üzenetet kiküldő függvényem is formázott sztringet fogad bemeneti paramétereként és a függvényen belül a vsprintf() által lesz belőle elkészítve a sztring egy (1000 elemű) lokális változóban. Ugyan ez van az AT-parancsokat küldő függvényeimben is. Aztán vannak olyan függvények amely TCP/IP kapcsolatot használva, mondjuk WIFI-n lekérnek egy weboldalt (pontosabban csak a headerjét) és annak headerjéből kimazsolázzák hogy mennyi az idő és év, hónap, nap, óra stb.-vel térnek vissza. Na itt a függvényen belül kell egy lokális tömb amelyben a TCP lekérésre kapott választ eltárolom hogy ki tudjam olvasni belőle az adatokat. Hasonló függvény van arra a célra hogy megtudjam, van-e épp internet elérés vagy sem. Vagy hogy egy adott szerver elérhető-e épp. Egy ehhez hasonló függvény a GSM modulnál USD kódokkal lekérdezi a szolgáltatótól hogy mennyi az egyenlege a SIM-kártyának. Az ilyesmi függvényeknél mindig kell egy 500-1000 elemű lokális változó. Mondjuk ezek szinte soha nincsenek egymásból meghívogatva hogy egyszerre foglalják le a memóriát. ![]()
Szervezd át az egészet.
- Vegyél fel egy körforgó puffert (amiben legalább egy távirat elfér) a vételnek és egyet az adásnak. - A vételi megszakítás a hibátlanul vett karaktert írja be a vételi pufferbe, ha hiba volt, kezelje le. - A főprogram bogarássza a vételi pufferből kiolvasott adatokat, ha értelmes táviratot talál dolgozza fel. - A feldolgozás eredményét valamint a diagnosztikai üzenetet az adási pufferbe írja be. Engedélyezi az adási megszakítást. Ha nincs elég hely a pufferben, várakozik. - Az adási megszakítási rutin az adási puffer soron következő adatát küldi el, ha nincs adat letiltja az adási megszakítást. Működik több példányban.
Na szóval... én eddig nem is tudtam hogy az UART periféria fifo-ba dolgozik.. Most már tudom.
![]() Az URXDA bit jelezte hogy még van kiolvasni való a fifo-ból, az OERR pedig azt is mutatta hogy túl is csordult valamikor a fifo. Az egész függvényt amely a vett karaktereket feldolgozza, beletettem egy do-while ciklusba ahol a feltétel az URXDA bit. Ezt mindkét UART periféria megszakításával megtettem. Így úgy néz ki hogy működik, egyenlőre még nem sikerült kiakasztanom.
Sziasztok!
Egy 32mx170f256b-vel próbálok SPI DMA-t csinálni, de nem akar úgy működni ahogyan szeretném.
A kódnak így sok értelme nincs, csak a teszt miatt van benne a while a végén. A problémák amiket észre vettem: bárhogy állítom a STXISELT az IFS1 SPI2TXIF-et nem tudom törölni a DMA transzfer előtt. Ha az SSIZ 16 byte méretű akkor szépen megy, de az ENHBUF be van kapcsolva ami pont 16 byte-os. Ha 16 byte-nál nagyobb az SPI2EIF mindig 1 lesz. Ebből gondolom azt, hogy valamiért a DMA "rosszul informálódik az SPI transzfer OK-ról" és küldi folyamatosan az adatot és gondolom az error if abból van, hogy a fifo teli van és úgy akarok bele írni. Próbáltam az RX IRQ-ra is rakni, de ott is csak 16 byte-ig ment mi lehet a baj?
Próbáltam, nem lett jó.
De nem is ezzel, hanem a Homerseklet_alapjel kiírással van gond. És azzal is csak akkor ha adási puffer van beállítva ( és akkor a főciklusból az fputc_send(UART_PORT2); parancs küldi ki az adatot) A hozzászólás módosítva: Jan 24, 2017
CCS-C ben járatos emberek segítségét kérném!
soros protra küldök ki adatokat:
Ha a soros portnál beállítom, hogy legyen adási puffer akkor a Homerseklet_alapjelet többnyire hibásan küldi ki a portra. Ciklikusan ismétlődnek a hibás adatok, de minden 6.-ra helyesen küldi ki. Ha nincs adási puffer akkor mindig hibátlanul küldi az adatokat. A Lakas1_homerseklet mindig hibátlanul megy. Ez mitől lehet?
Megette a fene a vaksi szemem. Pont az atmega128 doksit neztem meg, mielott azt allitottam, hogy nem tudja megforditani. Az NXP kerdesben viszont csak reszben tevedtem, mert az altalam hasznalt LPC11xx, LPC13xx, LPC17xx, LPC23xx sorozatokban nem tudja megforditani a bitiranyt az SSP modul. Az LPC81x sorozat egy ujabb fejlesztes, annak az SPI modulja egy vicc. De teny, hogy a bitsorrendet meg tudja forditani, de mar egy puffer nem fert bele, nemhog egy fifo. Igazabol nem is ertem, hogy miert lehet megforditani, hiszen az SPI kimondja, hogy MSB first. Ettol kezdve mire jo ez?
Van egy ilyen UART hibakezelőm megszakításban.
Kommunikáció során többször betér ide, amit a LED és a hiba számláló villogása illetve növekedése mutat. Ellenben egyetlen egyszer sem fut be a szál a három lehetséges kiváltó ok vizsgálatába. Breakpontot tettem mindháromra, nem fut bele. Kérdésem, mi okozhat még megszakítást? Vagy létezik, hogy a kiváltó ok megszűnik, mire beér a megszakításba? Az RX megszakítás kezelése gyors, elvileg minden adatot el tudok kapni, majdnem kizárt, hogy a 8 mélységű fifo megteljen. FERR előfordulhat, de még nem tudtam elcsípni a fenti módon, lehet nem is lehet így... A hozzászólás módosítva: Márc 15, 2016
A fifo_Deep 1 és 4 közötti, akkor kimegy 121-ig minden bájt
Ha a fifo_Deep x: kimenő bájtok 9 után elnyelődnek al alábbi módon. 5: 1-9, 11-121 6: 1-9, 13-121 7: 1-9, 15-121 8: 1-9, 17-121 9: 1-9, 19-121
A hozzászólás módosítva: Márc 11, 2016
Igen, de végül is nem tudod nem használni a fifo-t, csak ha minden egyes TXREG-be írás után kijössz a megszakításból, akkor csak egy mélységben használod. Ezt tudom feltornászni 4-re, eddig. Sajnos annyira nem tudok angolul, hogy ilyen bonyolult dolgokról tudjak társalogni velük.
![]()
Lehet, hogy valamilyen bug-ról van szó. Szerintem a Microchip fórumban kérdezz rá. De ide is tedd fel a forrást, azért belekukkantok. Bár fifo-t nem használtam még, amit a forrásban láttál abban egy bájtot küldözgetek.
Majdnem igen, 8+1bit széles a fifo, 8 mélységben.
Nem lehet a fifo-t kikapcsolni (ha tévedek, akkor javítsatok ki). Célnak? A célom az, hogy megismerjem és kihasználjam az MZ lehetőségeit. Sokat gondolkodtam a dolgon, lehetséges, hogy a megszakítási logika 4 mélységnél többet nem tud kezelni, azaz bugos? Az MX-eken csak 4 mély a fifo... ![]() A hozzászólás módosítva: Márc 11, 2016
Kicsit olvasgattam az adatlapját.
A 8 level deep azt jelenti, hogy 8 bájt? Ha a fifo ki van kapcsolva, az nem felel meg a célnak? Ha megszakításból kezeled, úgy jól tud működni.
De be van kötve (panelen van kettő illesztő a 4 és a 6 UART-on). Tudod, írtam, hogy ha 1-től 4 mélységig töltöm fel a fifo-t, akkor hibátlan (az 1 mélység felel meg a régi módnak, ahogy te is használod), ezért nem lehet külső hiba.
Tedd fel a forrást és belenézek.
A megszakításokat kirpóbáltad külön külön? Pl az Rx-nél egy lLED-en nyom egy toggle-t. A tx-ben pedig csak egy változót számlálsz és összehasonlítod annyi-e mint ahány karaktert küldtél? Most nem emlékszem fejből, higy fifo nélkül lehet-e használni. A logikai analizátor már nem kell, mert jó lett az I2C. Az ack-nál i2c1 volt a regiszter neve, de az i2c2-t használtam. Most azért szedtem szét, mert mással kell foglalkoznom. Rakd fel a progit és megnézem szívesen. Jut eszembe, én a Microchip fórumon kérdezősködtem már párszor az MZ-ről. Ott eléggé vágják a dolgokat. Végső esetben érdemes oda feltenni. A regisztráció viszont időbe telik, amíg egy admin jóváhagyja.
Előtte fogadok adatot, adás közben nem(Az RS485 half-duplex). Az RX fifo külön hardver a TX fifo-tól, remélem nem szólhatnak egymás dolgába, de itt bármi előfordulhat. A legnagyobb bajom az, hogy alig van még PIC32MZ-vel foglalkozó fórum, úgy tűnik kevesen használják.
A forrást ide is fel tudom majd tenni délután, nem titok, egyébként se működik ![]() A hozzászólás módosítva: Márc 11, 2016
Adatot is fogadsz közben?
Az errata a 8. Pontjában említ egy RX fifo szinkronizációs hibát.
Tegnap sikerült pár dolgot kideríteni:
Mód: 01, akkor szakít meg, ha a fifo kiürült és az SR is kiment. (ilyenkor a TRMT is 1 lesz) első 9 karakter fifo-ba töltése megszakításjel törlése (debuggerben elenőrizve, sikeres) Ezt követően kilép a megszakítás kezelésből és nem kéne visszalépnie, csak amikor a fifo kiürült és az SR is kitolta az utolsó karaktert. Ennek ellenére gyakorlatilag azonnal visszatér. A következő 9 karakter rátöltődik a fifo-ra, ami abból látszik, hogy az első U6TXREG-be való töltéskor a BF (túlcsordulás) bit beáll. A megszakítás jelző bit itt is törlésre kerül Ekkor elmeg az első 9 bájt! A megszakításba betér, de ekkor már az utolsó 4 bájt kivitelére fut a szál, mert az index 18-on áll. (összesen 24bájt kerül kivitelre most) Az utolsó 4 bájt is kimegy, és megszakít. Kérdés, miért nem várja meg az első 9 kiküldését a megszakítási logika? Ami érdekes, ha csak 1-től 4 bájttokkal töltöm fel a fifo-t, akkor jól működik. Ha már 5-el, akkor 1 bájt lemarad. Ha többel, akkor egyre több bájt marad le az első és az utolsó csomag között. 9 esetén az egész középső csomag lemarad. Ha valakinek van ötlete, nagyon örülnék neki! ![]()
A legnagyobb bajom az, hogy ezen a héten 0 időm volt és ma sem lesz sok. Emellett lehet, hogy túlbonyolítottam a mód váltogatással. Talán a legjobb megoldást, ahol nem kell a TX INT módot menet közben módosítani, nem próbáltam.
A terv: A megszakítási mód: 01 (Akkor szakít, ha kiürült a fifo és az SR is.) UART buffer pointer beállítása Adat méret beállítása RS485 irány kimenet TX Interrupt engedélyezése 9 adat betöltése a fifo-ba, ha van annyi. Ha hamarabb elfogy, kilépés és várakozása megszakításra - ha kiürült a fifo és az SR, megszakítás: Ha van még adat ugrás az előzőre... Ha nincs több adat, TX int tiltása, RS485 vonal bemenetre váltása, kész... Remélem lesz időm este még kipróbálni. Talán lehetne még variálni, de módot kellene közben váltani. Van a 10-s TX INT mód, ahol akkor szakít meg, ha üres a fifo (de az SR még nem ment ki). Ezzel nyerhető valamennyi idő, de szerintem az minimális és a végén még is csak váltani kéne, amikor az adat elfogy, mert a legvégén meg kell várni az SR ürülését, mert az RS485 irány vezérlő vonalat nem szabad addig változtatni, míg ki nem ér az utolsó Byte is. Ellenben ez a változtatás akkor történne, amikor a fifo üres, azaz az ajánlásnak megfelelne. Ezt is kipróbálom majd. ![]() A hozzászólás módosítva: Márc 10, 2016
|
Bejelentkezés
Hirdetés |