Fórum témák

» Több friss téma
Fórum » PIC kezdőknek
 
Témaindító: Placi84, idő: Okt 3, 2005
Témakörök:
- A PIC ÖSSZES Vdd és Vss (AVdd és AVss) (tápfeszültség) lábát be kell kötni!
- A táplábak mellé a lehető legközelebb 100nF-os KERÁMIA kondenzátorokat kell elhelyezni.
- Az MCLR lábat, 10kohm-mal fel kell húzni a Vdd tápfeszültségre.
- Külső kvarc használatakor 4MHz-ig XT, a fölött pedig HS konfigurációt kell beállítani.
- Stabilizált tápegységet kell használni, a kapcsoló üzemű "telefon töltő" adapterek okozhatnak hibákat.
- Programozáshoz, használj lehetőleg PICKIT2 vagy 3 programozót. Kerülendő a JDM (soros porti) programozó.
- A PIC adatlapja (PDF), tartalmazza a lábak kiosztását és a PIC minden paraméterét. Az adatlap ingyen letölthető!
- Egyes PIC típusoknál az RA4 nyitott nyelőelektródás (Csak lefelé húz L szintre, H szintet nem ad ki!)
- Ha a PGM lábat digitális ki-/bemenetnek használod, az alacsony feszültségű programozási lehetőséget le kell tiltani.
Lapozás: OK   1225 / 1225
(#) Laja1 hozzászólása Márc 2, 2026 /
 

Érintőkijelző programozás

Sziasztok!

Két kérdésem lenne, az egyik elméleti, a másik gyakorlati.
1. Adott egy rezisztív érintőképernyő (ILI 9488+XPT2046), egy DS3231 RTC óra és egy PIC18F25K22. A kijelző és érintés SPI-vel, az óra I2C-vel kommunikál a PIC-cel. DE ha az órát másodpercenként kiíratjuk, az SPI-vel történik és ha eközben történik egy érintés is, azt hogy látja a mikrokontroller? Szinte folyamatosan foglalja a TFT a SPI vonalat. Pláne, ha még a századmásodperceket is kijeleznénk? Mi az elméleti megoldás erre? Mert nálam az érzékelést nem látja. Azt gondoltam azért, mert folyamatosan frissítettem a képernyőt (mindig újrarajzolt), de ezt megszüntettem. De az időkijelzést nem tudom megszüntetni, mert az mindig frissül. Sajnos a NYÁK úgy készült, hogy a T_IRQ kivezetés nincs kihuzalozva.)
2. Az óra kijelzése valami miatt el van csúszva: az óra helyén a perc jelenik meg, a perc helyén a másodperc. A dátum jól nézett ki. De vártam vele egy napot, a nap valóban ugrott egyet, de a hónap is. Valami nagyon szét van esve, nem tudom ezt mi okozza. Tudtok ebben segíteni? Mellékelem az óra header és c fájlját és ide beszúrom a kiírást is. Köszönöm szépen!
  1. void DrawClockBar(const DS3231_Time *t) {
  2.  
  3.     char buf[32];
  4.  
  5.     // --- Óraerc középen, felül ---
  6.     // Középre 480 px szélességhez, nagy betűméret (3)
  7.     sprintf(buf, "%02u:%02u", ido_most.hour, ido_most.min);
  8.     // Szöveg kb. 6×8×3 = 144 px széles, ezért (480-144)/2 ≈ 168 px
  9.     TFT_DrawString(168, 45, buf, COLOR_WHITE, COLOR_BLACK, 3);
  10.  
  11.     // --- Dátum (Év Hónap Nap) ---
  12.     uint8_t m = (ido_most.month >= 1 && ido_most.month <= 12) ? (ido_most.month - 1) : 0;
  13.     const char *month[] = {
  14.         "Január","Február","Március","Április","Május","Június",
  15.         "Július", "Augusztus", "Szeptember", "Október", "November", "December"
  16.     };
  17.     // formátum: "2025 Március 15"
  18.     sprintf(buf, "%04u %s %02u", ido_most.year, month[m], ido_most.day);
  19.     // 2-es méret → kb. 8×16 px/karakter, szélesség kb. 200–220 px
  20.     TFT_DrawString(140, 80, buf, COLOR_WHITE, COLOR_BLACK, 2);
  21.  
  22.     // --- Hét napja (a dátum mellett, jobbra) ---
  23.     const char *days[] = {"Hétfő","Kedd","Szerda","Csütörtök","Péntek","Szombat","Vasárnap"};
  24.     uint8_t di = (t->dayOfWeek >= 1 && t->dayOfWeek <= 7) ? (t->dayOfWeek - 1) : 0;
  25.     // kis betűméret (1), a dátum mellett, kissé jobbra eltolva
  26.     TFT_DrawString(340, 80, days[di], COLOR_WHITE, COLOR_BLACK, 2);
  27. }
(#) benjami válasza Laja1 hozzászólására (») Márc 3, 2026 /
 
Szerintem nem túl szerencsés egy gyakorlatilag RAM nélküli és DMA lehetőséget is nélkülöző mikrovezérlőre ekkora felbontású és színmélységű kijelzőt kötni. Ha mégis meg akarsz küzdeni vele, akkor fel kell bontani a megjelenítést rövidebb idő alatt lefutó részekre (pl, egyszerre, csak egy betűt kirajzolni), utána lehet a touchscreen-t lekérdezni. A másik dolog, hogy csak a megváltozott karaktereket kellene kiiratni, nem pedig az egész szöveget.
(#) tki válasza Laja1 hozzászólására (») Márc 3, 2026 / 1
 
// formátum: "2025 Március 15"

Ez egyébként így fest helyesen:

2025. március 15.
(#) Laja1 válasza benjami hozzászólására (») Hé, 20:21 /
 
Igen, ezt megcsináltam. Most már jó az érintés. De az óra továbbra sem működik. Mintha mindig szemetet írna ki egy-egy újrarajzolás után. PIC18F25K22 mikrovezérlőt használok. A képernyő rajzolás, érintés SPI kommunikációval megy az óra I2C-vel. Lehet, hogy ezek összeakadnak? Bár itt két MSSP modul van és a hardveres verziót használom. Az egyiken a SPI-t, a másikon az I2C-t. De lehet, hogy ennek ellenére összeakadnak? Nagyon sokszor lefagy az óra itt: while(!PIR3bits.SSP2IF). (I2C Read). Egyszerűen nem tudom, hogy mi a baj. Tudnátok ebben segíteni? Köszönöm!
(#) Bakman válasza Laja1 hozzászólására (») Hé, 20:53 /
 
Erre a kérdésre így nem lehet válaszolni. Mit tartalmaz az I2C read rutin? Nálam ez jól működik:

  1. uint8_t i2c_read(void) {
  2.     SSP2CON2bits.RCEN = 1; // Enable to receive data
  3.     while (!SSP2STATbits.BF);
  4.     return SSP2BUF; // Return received byte
  5. }
(#) Laja1 válasza Bakman hozzászólására (») Hé, 20:55 /
 
Nálam így néz ki:
  1. uint8_t I2C_Read(uint8_t ack) {
  2.     uint8_t data;
  3.     I2C_Wait();
  4.     SSP2CON2bits.RCEN = 1;
  5.     uint16_t timeout = 5000;
  6.     while(!PIR3bits.SSP2IF && --timeout > 0);
  7.     PIR3bits.SSP2IF = 0;
  8.     data = SSP2BUF;
  9.    
  10.     I2C_Wait();
  11.     SSP2CON2bits.ACKDT = (ack ? 0 : 1); // 0=ACK, 1=NACK
  12.     SSP2CON2bits.ACKEN = 1;
  13.      while(SSP2CON2bits.ACKEN);
  14.     return data;
  15. }
(#) Laja1 válasza Bakman hozzászólására (») Hé, 21:19 /
 
Itt inkább az volna a kérdés, hogy a két kommunikáció zavarja-e egymást, vagy elvannak egymástól függetlenül. Mert ha nem zavarják egymást, akkor más irányba megyek el a hibakereséssel.
(#) Bakman válasza Laja1 hozzászólására (») Kedd, 5:19 /
 
Biztos, hogy nem zavarja egymást, legalábbis logikailag. Ha olyan a NYÁK és/vagy a vezetékezés, akkor zavarhatják egymást, leginkápp az SPI zavarhatja az I2C-t. Utóbbi jóval érzékenyebb jószág. Oszcilloszkóppal ellenőrizhető. Felhúzó ellenállások értékei az I2C vezetékeken?
(#) István_2 válasza Laja1 hozzászólására (») Kedd, 8:52 / 1
 
Sziasztok !
Esetleg ezt próbáld ki : ( Beszúrva egy flag törlést )
3. I2C_Wait();
PIR3bits.SSP2IF = 0;
4. SSP2CON2bits.RCEN = 1;
A hozzászólás módosítva: Kedd, 8:53
(#) Laja1 válasza Bakman hozzászólására (») Kedd, 9:40 /
 
Az SDA-n és az SCL-n is 4k7 ellenállás van. Szkópon az látszik, hogy az inicializálás (általában ) rendben lefut (cím: 0x68; 0x0E--0x04; 0x0F--0x00), mindig van ACK válasz. De néha az időolvasásnál (nagyon ritkán az inicializálásnál) az SDA vonal 0 V-on ragad. Ekkor mindent lekapcsolok és direktben adok az SDA lábra 3,3 V-t. Ekkor észhez tér és egy darabig működik, majd megint beakad. A NYÁK nyomvonalvezetéssel hol lehet gond? Ha közel megy a SPI adatforgalomhoz az SDA vonal? De ott is mit jelent a közel? Erre is érzékeny lehet?
(#) Tasznka válasza Laja1 hozzászólására (») Kedd, 10:36 /
 
Szia!
Amit javasolt István_2 az sem árt,de be kellene tenned 1 flag-et a
  1. PIR3bits.SSP2IF = 0;
  2.     SSP2CON2bits.RCEN = 1;
  3.     uint16_t timeout = 5000;
  4. while(!PIR3bits.SSP2IF && --timeout > 0);

után,hogy tudd,hogy jött-e tényleg valami,mert így nem tudod,hogy a timer limit,vagy az IF járt le,vagy váltott.Talán ez segít:
  1. if(PIR3bits.SSP2IF){
  2.     PIR3bits.SSP2IF = 0;
  3.     data = SSP2BUF;
  4.     flag = 1;
  5. }
  6. else
  7. {
  8.     flag = 0;
  9.     return 0;
  10. }
  11.     I2C_Wait();
  12.     SSP2CON2bits.ACKDT = (ack ? 0 : 1); // 0=ACK, 1=NACK
  13.     SSP2CON2bits.ACKEN = 1;
  14.      while(SSP2CON2bits.ACKEN);
  15.     return data;

És ezt a flag-et figyelve láthatod,hogy tényleg megjött -e a jó adat. Bár az I2C nem a kedvencem,de talán tudtam segíteni.
(#) Laja1 válasza István_2 hozzászólására (») Kedd, 11:37 /
 
Köszönöm! Ezzel most az összeomlás (eddig) megszűnt. És mintha az adatok is a helyére kerültek volna. Csak nem frissít valami miatt. De ez már más miatt lehet.
Köszönöm szépen!
(#) István_2 válasza Laja1 hozzászólására (») Kedd, 14:24 /
 
Sziv SN !
"Csak nem frissít valami miatt" -> Esetleg a DS3231-nek az oszcillátora nincs-e letiltva ?
(#) István_2 válasza Laja1 hozzászólására (») Kedd, 14:40 /
 
A cím biztos "0x68" ? Nem 0xD0 , vagy 0xD1 ?
A címzés képe az előző hozzászólásnál.
A hozzászólás módosítva: Kedd, 14:40
(#) Moderátor hozzászólása István_2 hozzászólására (») Kedd, 14:57
 
Kérjük az MSN szleng használatát mellőzni!
(#) Laja1 válasza István_2 hozzászólására (») Kedd, 21:15 /
 
Igen, minden rendbe jött! Frissítette magát, csak én nem frissítettem, hogy írja is ki ezt az új időt.
Köszönöm! És azóta nem is akadt meg!
(#) Laja1 válasza István_2 hozzászólására (») Sze, 9:40 /
 
Abban tudtok segíteni, hogy hogyan lehet gyorsabban képernyőt frissíteni? Mivel pixelenként rajzolja át a színeket, így nagyon lassú. Kb. 5-6 másodpercig tart. Nincs erre egy gyorsabb függvény?
PIC18F25K22 mikrovezérlőt használok és egy rezisztív érintőképernyőt (ILI 9488+XPT2046, 320x480). Jelenleg így színezem át a képernyőt:
  1. void TFT_FillScreen(uint16_t color) {
  2.  
  3.    // isSpiBusy = true;
  4.     TFT_SetAddrWindow(0,0,TFT_W-1,TFT_H-1);
  5.  
  6.     TFT_Command(0x2C);
  7.  
  8.     TFT_DC_LAT = 1;
  9.  
  10.     TFT_CS_LAT = 0;
  11.  
  12.     //SPI_Write(0x2C);
  13.  
  14.  
  15.    
  16.  
  17.  
  18.     for(uint32_t i=0;i<(uint32_t)TFT_W*TFT_H;i++)
  19.  
  20.     {
  21.  
  22.         TFT_WriteColor(color);
  23.  
  24.     }
  25.  
  26.  
  27.     TFT_CS_LAT = 1;
  28.  //   isSpiBusy = false;
  29. }

  1. void TFT_SetAddrWindow(uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1) {
  2.    // isSpiBusy = true;
  3.  
  4.     TFT_Command(0x2A);
  5.  
  6.     TFT_Data(x0>>8); TFT_Data(x0 & 0xFF);
  7.  
  8.     TFT_Data(x1>>8); TFT_Data(x1 & 0xFF);
  9.  
  10.     TFT_Command(0x2B);
  11.  
  12.     TFT_Data(y0>>8); TFT_Data(y0 & 0xFF);
  13.  
  14.     TFT_Data(y1>>8); TFT_Data(y1 & 0xFF);
  15.  
  16.     TFT_Command(0x2C);
  17.    // isSpiBusy = false;
  18.  
  19. }

  1. void TFT_WriteColor(uint16_t color) {
  2.    // isSpiBusy = true;
  3.  
  4.     // RGB565 (16 bit) -> RGB666 (18 bit kiterjesztve 24-re)
  5.  
  6.     SPI_Write((color & 0xF800) >> 8); // Piros (R5 -> R8-nak látszik)
  7.  
  8.     SPI_Write((color & 0x07E0) >> 3); // Zöld (G6 -> G8-nak látszik)
  9.  
  10.     SPI_Write((color & 0x001F) << 3); // Kék (B5 -> B8-nak látszik)
  11. //isSpiBusy = false;
  12. }
(#) Bakman válasza Laja1 hozzászólására (») Sze, 10:04 / 1
 
Kontrollert 64 MHz-en járatni, SPI-t felhúzni annyira, amennyire a kijelző engedi.

Esetleg más kijelzőt használni, ameliyk nem foglalja le ennyire a kontrollert, pl. Nextion valamelyik változata. Egyszerűen ehhez a kijelzőhöz kevés az a PIC, amelyiket használnod, lásd itt: Bővebben: Link.
A hozzászólás módosítva: Sze, 10:04
(#) benjami válasza Laja1 hozzászólására (») Sze, 10:20 / 1
 
A teljes képernyő újrarajzolásához 320*480*24 = 3686400 bitet kell a kijelzőre írni (sajnos az ILI9488 nem tud SPI módban 16 bites színmélységben működni, pedig azzal lehetne gyorsítani egy kicsit). Ha 5-6 másodpercig tart a feltöltés, akkor az SPI-t 700000 bit/sec sebességgel járatod. Ez mehet feljebb, szerintem a kijelző tudni fogja azt amire ez a PIC maximális sebességgel képes. Ha ez is kevés, akkor nem marad más lehetőség, mint másik mikrovezérlővel megoldani. Menet közben már nem kell az egész képernyőt irogatni, elegendő csak a megváltozott karaktereket.
Következő: »»   1225 / 1225
Bejelentkezés

Belépés

Hirdetés
XDT.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem