Fórum témák

» Több friss téma
Fórum » ARM - Miértek hogyanok
 
Témaindító: gtk, idő: Jún 26, 2007
Lapozás: OK   93 / 178
(#) vargham válasza kapu48 hozzászólására (») Máj 27, 2017 /
 
Sorosporton binárisan is kommunikálhatunk, bájtokat küldünk.
Kitalálunk 1 formátum szabályt, amit a túloldalon már tudsz értelmezni.

Pl:
1. byte: 0xAB start of message, és ha 0xAB előfordul az üzenetben is, akkor duplázni kell (escape).
2. byte: Üzenet típusa (Áram, feszültség, hőmérséklet, miegymás)
3-n byte: Adat. A küldeni kívánt értékek byteonként. Küldő oldalonn szétszeded, fogadó oldalon összerakod. Az üzenet típusából tudod, hogy hány bytera számíts, és azok mit jelentenek.

Érdemes még a fejlécbe bele rakni az üzenet hosszát, CRC-t, kér-e a küldő ACK-t, stb.

Lehet escape nélkül is, ilyenkor csak a start byte, a hossz és a CRC ellenőrzése után tudod, hogy egész üzenetet kaptál, vagy csak egy részletet.
(#) kapu48 válasza vargham hozzászólására (») Máj 27, 2017 /
 
Ezzel az a gond, hogy mi van, ha az érték is 2byte: 0xAB,0xAB?
És startnak fogja értelmezni?

Így csak a String/szám konvertálástól szabadulsz meg.
Viszont lesz helyett több egyéb megoldandó feladatod.

Én a szöveges kommunikálást ember közelebbinek érzem.
A hozzászólás módosítva: Máj 27, 2017
(#) kapu48 válasza cimopata hozzászólására (») Máj 27, 2017 /
 
Vannak C függvények a szavak szétbontására:

Bővebben: Link

char *strtok(s, ct)
Az strtok függvény megkeresi az s karaktersorozatban a ct karaktersorozatból vett karakterekkel határolt tokeneket.

És a string/szám konvertálására:
B5. Kiegészítő rendszerfüggvények: az <stdlib.h> header-ben …
(#) vargham válasza kapu48 hozzászólására (») Máj 27, 2017 /
 
> Ezzel az a gond, hogy mi van, ha az érték is 2byte: 0xAB,0xAB?
> És startnak fogja értelmezni?
Egy darab start byte lehet csak. Ha az adatban kettő pont olyan is van egymás után, akkor mindkettőt megkettőzi, vagyis összesen négyet küld. Fogadó oldalon pedig kiszedi. Ha jól van megírva a feldolgozó, akkor alacsony szinten, automatikusan. Te, az applikációd programozása közben már nem találkozol megkettőzött bájtokkal, csak a szép, tiszta üzenettel. (OSI/ISO modell) Ez azt jelenti, hogy az applikációd alatt bármikor kicserélheted a protokollt, akár binárisról szövegesre, az applikációs réteg ebből semmit sem fog észrevenni.
Nem én találtam ki, bevett módszer. Lásd: Escape

De ahogy írtam, kihagyhatod, és használhatsz start/stop byte-ot csomaghosszal kombinálva escape nélkül. Rajtad múlik.

Viszont szöveges protokoll esetén is szükséged van fejlécre, hogy tudd, hol kezdődik az adat, mik tartoznak össze, sokszor kell küldeni CRC-t, stb.

> Így csak a String/szám konvertálástól szabadulsz meg.
> Viszont lesz helyett több egyéb megoldandó feladatod.
A String/szám konvertálás eléggé számításigényes művelet. Bináris kommunikáció esetén a csomagfeldolgozás sokkal kisebb erőforrásigényű. Olyan műveleteket használ, amik max néhány gépi utasítássá fordulnak le. Desktop környezetben ez a különbség elhanyagolható, mikrokontrolleren viszont nem mindig. Ugyanez igaz a csomagok hosszára is. Szöveges protokoll esetén több bájton lehet ugyanazt az adatmennyiséget átvinni, ami növeli a pufferek memória igényét és az átviteli időt is.

> Én a szöveges kommunikálást ember közelebbinek érzem.
Ez így is van. Kérdés, hogy miért kellene emberközelinek lennie két gép beszélgetésének... Nem nekem kell látnom az adatokat, hanem a gépeknek.
(#) kapu48 válasza vargham hozzászólására (») Máj 27, 2017 /
 
OK!

Vannak érvek, ellen érvek!

Majd a felhasználó dönt, melyik felel meg jobban a céljának.
(#) vargham válasza kapu48 hozzászólására (») Máj 27, 2017 /
 
Pontosan.
(#) cimopata hozzászólása Máj 28, 2017 /
 
Mi történik akkor ha egy időzítő megszakításából meghívok egy USART_TX adatküldés függvényt ami eltart egy ideig, de ezalatt jön egy másik megszakítás pl USART_RX.

Sikerült megcsinálnom az USART adatcsomagok küldését külön külön minden szépen oda vissza megy de egyben RX-TX lefagy a program néhány mp-re mihelyst ráadom a bemenetre az RX-et.
(#) kapu48 válasza cimopata hozzászólására (») Máj 28, 2017 /
 
Szerintem a vételnek kel megszakítás, az RX-re .

Ha mégis? Akkor csak 1 Byte-ot veszünk/küldünk és pufferolunk, majd ha kész,
Akkor dolgozzuk fel a puffer tartalmát már megszakításon kívül.

Mondjuk a Küldést DMA-ra biznám!
(#) cimopata válasza kapu48 hozzászólására (») Máj 28, 2017 /
 
Igen. A z RX megszakítással megy. Tuti az kavar be mert a küldés 100ms-ként megy 5-5 csomag a fogadás 10msec-ként jön 5-5 csomag.

Ha kiveszem a teljes TX függvényt akkor megy szépen, ha benne hagyom de lehúzom az RX vezetéket e prociról akkor is megy.

Kettő együtt van hogy azonnal de max 4-5mp-en belül lefagy a program. Tehát jópár ciklust megcsinál jól aztán random 1-4mp-re kb lefagy.

Igazából semmi mást nem csinálok az RX- megszakításban hogy ha 0x40 nél nagyobb csomag jön akkor azt veszem kezdő karakternek és utána lementem a további 4 csomagot. Ha megvan a 4 csomag akkor abból legyártom az eredeti 16 bites adatot és berakom a megfelelő változóba.

Szerintem azért fagy le mert pont egybeesik az RX-TX feladat és valahogy elveszti a fonalat a a proci az RX-en belül.

A TX függvény nagyon egyszerű ott nem hinném hogy baj lehet. Ott csak beírom a regiszterbe az adatot és várok míg elküldi. Utána jön a többi 4 csomag és ki is lép.

DMA-t néztem én is esetleg TX re nagyon hasznos lenne mindenképp. Csak a TX DMA nál nem értem hogy mit adok meg regiszter címnek hogy honnan olvassa a küldeni kívánt tömböt? 5db short alsó 8-bit-jén tárolom jelenleg a küldeni kívánt adatot. Azt adagolom be jelenleg a TX-nek egymás után.

  1. void USART1_IRQHandler(void)
  2. {
  3.        
  4.         if(USART1->ISR & USART_ISR_RXNE)
  5.     {
  6.                        
  7.         usart_rx_buff = USART1->RDR;
  8.         if(usart_rx_buff > 0x40)
  9.         {      
  10.                                        
  11.         usart_rx_package_number=0;
  12.         usart_rx_store[0]=usart_rx_buff;
  13.         usart_rx_package_number++;
  14.         }
  15.         else
  16.         {
  17.                                        
  18.         usart_rx_store[usart_rx_package_number]=usart_rx_buff;
  19.        
  20.         usart_rx_package_number++;
  21.                                        
  22.         if(usart_rx_package_number>4)
  23.         {
  24.        
  25.         usart_rx_buff_shift = usart_rx_store[1] << 12;
  26.         usart_rx_buff_shift = (usart_rx_store[2] << 8) | usart_rx_buff_shift;
  27.         usart_rx_buff_shift = (usart_rx_store[3] << 4) | usart_rx_buff_shift;
  28.         usart_rx_buff_shift = usart_rx_store[4] | usart_rx_buff_shift;
  29.        
  30.         usart_rx_package_number=0;
  31.         switch(usart_rx_store[0])
  32.         {
  33.                                                                
  34.         case(0x41):      current = usart_rx_buff_shift ; break;
  35.                                                                
  36.         }
  37.                                         }      
  38.                                 }
  39.                 }
  40.                
  41.  
  42.   HAL_UART_IRQHandler(&huart1);
  43.  
  44. }
A hozzászólás módosítva: Máj 28, 2017
(#) kapu48 válasza cimopata hozzászólására (») Máj 28, 2017 /
 
Az adást szervezdki DMA-ra. Csak 1* kel jól megcsinálni, és tehermentesíti a procit.
Mivel külön adat busza van.

Megszakításban nem szoktunk adatott feldolgozni, csak eltesszük a pufferbe.
Végén jelezzük, hogy készen van a vétel.

A többi shiftelés részét nem igazán értem!
A hozzászólás módosítva: Máj 28, 2017
(#) cimopata válasza kapu48 hozzászólására (») Máj 28, 2017 /
 
Ha a forrásnak a short usart_tx_store[5] tömb lesz 16 bites ugye amiben az alsó 8 bit az adat a többi üres, célnak pedig akkor mehet az USART1->TDR. Nem lesz baj hogy az csak 8 bites? A felső 8 bit simán elveszik vagy azt két részben akarja majd adagolni?
A hozzászólás módosítva: Máj 28, 2017
(#) kapu48 válasza cimopata hozzászólására (») Máj 28, 2017 /
 
És a vétel is megszervezhető DMA-val, ha a start jel után elküldöd az adatok számát.
Akkor már tudod milyen értékekkel indítsad a DMA-t.
(#) kapu48 válasza cimopata hozzászólására (») Máj 28, 2017 /
 
Biztosítsad típus módosítással, hogy csak az alsó 8 bitet írja felül:
  1. usart_rx_store[usart_rx_package_number]=(uint8_t)usart_rx_buff;
(#) cimopata válasza kapu48 hozzászólására (») Máj 28, 2017 /
 
Ezeket tettem hozzá memory to peripheral módot kell használjak circular mode nélkül?

Adatlap azt írja:
Idézet:
„Memory-to-memory mode
The DMA channels can also work without being triggered by a request from a peripheral. This mode is called Memory to Memory mode.
If the MEM2MEM bit in the DMA_CCRx register is set, then the channel initiates transfers as soon as it is enabled by software by setting the Enable bit (EN) in the DMA_CCRx register. The transfer stops once the DMA_CNDTRx register reaches zero. Memory to Memory mode may not be used at the same time as Circular mode.”



  1. USART1->CR3 = USART_CR3_DMAT;
  2.         DMA1_Channel2->CPAR  = (uint8_t)(USART1->TDR)// peripheral (source) address
  3.         DMA1_Channel2->CMAR  = (uint8_t)(usart_tx_store);                 // memory (desination) address
  4.         DMA1_Channel2->CNDTR = 5;                             //  DAM átvitt adatok mennyisége
  5.         DMA1_Channel2->CCR |= DMA_CCR_PL_0;     // dma priority
  6.         DMA1_Channel2->CCR |= DMA_CCR_MINC ;    // memory increment mode enable
  7.         //DMA1_Channel2->CCR |= DMA_CCR_CIRC // circular mode enable
  8.         //DMA1_Channel2->CCR |= DMA_CCR_DIR; // Memory to peripheral direction
  9.         //DMA1_Channel2->CCR |= DMA_CCR_MEM2MEM; // Memory to memory direction
  10.         DMA1_Channel2->CCR |= DMA_CCR_EN ;      // Enable channel       not sircular mode start trigger.
(#) kapu48 válasza cimopata hozzászólására (») Máj 28, 2017 /
 
Ez még kell:
DMA1_Channel2->CCR |= DMA_CCR_DIR; // Memory to peripheral direction
És be kell állítani az adat szélességet 8 vagy 16 bit lehet különböző is a 2 oldal.
És meg kell adni a memória puffer kezdő pointerét.

Aztán még meglehet szervezni, hogy a végén kérjen megszakítást.
Ahol jelezhetett, hogy végzett a DMA.
(#) cimopata válasza kapu48 hozzászólására (») Máj 28, 2017 /
 
Igen a DMA1_Channel2->CCR |= DMA_CCR_DIR; közben észrevettem. Az adatszélességet végül 8->8 bit lesz mert nem fontos hogy short típusban legyen tárolva így ez nem igényel további beállítást.

A memória kezdő pointernek nem jó a DMA1_Channel2->CMAR = (uint8_t)(usart_tx_store); ?

Egyébként ezekkel így nem megy azért lehet tényleg a pointer de lehet valami más hiányzik még.
A hozzászólás módosítva: Máj 28, 2017
(#) kapu48 válasza cimopata hozzászólására (») Máj 28, 2017 /
 
Itt 1 példa:
Bővebben: Link

Ha ez tömbb? Átadhatod pointerként:
  1. DMA1_Channel2->CMAR = (uint8_t)(usart_tx_store[0]);
(#) kapu48 válasza cimopata hozzászólására (») Máj 29, 2017 /
 
Tölle lehet tanulni, mert szinte minden sort magyaráz:
Tilen Majerle:
Extend USART with TX DMA
(#) cimopata válasza kapu48 hozzászólására (») Máj 29, 2017 /
 
Valami nem oké nem indul.
  1. USART1->BRR = 480000 / 384; /* (1) */
  2.         USART1->CR3 = USART_CR3_DMAT;
  3.         USART1->CR1 = USART_CR1_TE |
  4.         USART_CR1_RXNEIE |
  5.         USART_CR1_RE |
  6.         USART_CR1_UE; /* (3) */
  7.                                                                
  8.          
  9.         DMA1_Channel2->CPAR  = (uint8_t)(USART1->TDR)// peripheral  address
  10.         DMA1_Channel2->CMAR  = (uint8_t)(usart_tx_store[0]);      // memory  address
  11.         DMA1_Channel2->CNDTR = 5;                             //  DAM átvitt adatok mennyisége
  12.         DMA1_Channel2->CCR |= DMA_CCR_PL_0;     // dma priority
  13.         DMA1_Channel2->CCR |= DMA_CCR_MINC ;    // memory increment mode enable
  14.         //DMA1_Channel2->CCR |= DMA_CCR_CIRC // circular mode enable
  15.         DMA1_Channel2->CCR |= DMA_CCR_DIR; // Memory to peripheral direction
  16.         //DMA1_Channel2->CCR |= DMA_CCR_MEM2MEM; // Memory to memory direction
  17.         DMA1_Channel2->CCR |= DMA_CCR_EN ;      // Enable channel       not sircular mode start trigger.
A hozzászólás módosítva: Máj 29, 2017
(#) cimopata hozzászólása Máj 29, 2017 /
 
Időzítővel többször indítgatom programon belül a
  1. DMA1_Channel2->CCR |= DMA_CCR_EN ;

paranccsal fel töltöttem a tömböt fix adattal de nem akar indulni.
(#) cimopata hozzászólása Máj 29, 2017 /
 
Generáltam az STM cube al is egy alapbeállítást azt még beraktam + ba hátha valami kimaradt de akkor sem. Az az érdekes hogy ugyan ez a beállítás circualr-al működik egy másik programomban ott ADC-t adagol egy regiszterbe.
(#) cimopata hozzászólása Máj 29, 2017 /
 
Na meg lett mi volt igazából nem értem miért kell de a neten volt egy példa és az illető a küldés parancsot ezzel indítja minden alkalommal:
  1. HAL_UART_Transmit_DMA(&huart1, usart_tx_store, 5);


Örülök hogy megy de igazából nem értem a ref manual azt írja elég csak az EN regisztert izgatni hogy induljon de valahogy nekem mégsem sikerült azzal.
(#) kapu48 válasza cimopata hozzászólására (») Máj 29, 2017 /
 
Most rájöttél, hogy érdemes használni a: STM32F4xx_HAL_Driver –t!
A kézi regiszter állítgatásokkal mindig kifelejt az ember valami.

Amit az előbb ajánlottam lib-et, ott is ott van a végén az: Enable USART TX DMA
  1. uint8_t TM_USART_DMA_Send(USART_TypeDef* USARTx, uint8_t* DataArray, uint16_t count) {
  2.         /* Get USART settings */
  3.         TM_USART_DMA_INT_t* Settings = TM_USART_DMA_INT_GetSettings(USARTx);
  4.        
  5.         /* Check if DMA is working now */
  6.         if (Settings->DMA_Stream->NDTR) {
  7.                 /* DMA works right now */
  8.                 return 0;
  9.         }
  10.        
  11.         /* Set DMA options */
  12.         DMA_InitStruct.DMA_Channel = Settings->DMA_Channel;
  13.         DMA_InitStruct.DMA_BufferSize = count;
  14.         DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t) &USARTx->DR;
  15.         DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t) &DataArray[0];
  16.        
  17.         /* Deinit first, clear all flags */
  18.         TM_DMA_ClearFlags(Settings->DMA_Stream);
  19.        
  20.         /* Init DMA */
  21.         DMA_Init(Settings->DMA_Stream, &DMA_InitStruct);
  22.  
  23.         /* Enable DMA Stream */
  24.         Settings->DMA_Stream->CR |= DMA_SxCR_EN;
  25.        
  26. //#define  USART_CR3_DMAT               ((uint32_t)0x0080) /*!<DMA Enable Transmitter      */
  27.         /* Enable USART TX DMA */
  28.         USARTx->CR3 |= USART_CR3_DMAT;
  29.        
  30.         /* DMA has started */
  31.         return 1;
  32. }
A hozzászólás módosítva: Máj 29, 2017
(#) csabeszq válasza kapu48 hozzászólására (») Máj 29, 2017 / 1
 
Én USART-nál körkörös DMA puffert használnék. Foglalsz 512 bájt puffert.

A DMA aktuális pozícióját ki lehet olvasni: DMA1_Channel4->CNDTR.

Tehát:
  1. #define PUFFER_MERET 512
  2.  
  3. uint8_t dma_puffer[PUFFER_MERET];
  4. int     feldolgozva = 0;
  5.  
  6. void ciklus()
  7. {
  8.  
  9.   int dmaPozicio = PUFFER_MERET - DMA1_Channel4->CNDTR;
  10.   int erkezett_adatok_szama = (PUFFER_MERET  + dmaPozicio - feldolgozva) % PUFFER_MERET;
  11.  
  12.   // itt feldolgozod őket: dma_puffer[feldolgozva ]
  13.  
  14.   // itt növeled a feldolgozottak számát
  15.   feldolgozva = ( feldolgozva + erkezett_adatok_szama ) % PUFFER_MERET;
  16. }


Egyszerű körkörös puffer, ha a DMA mutató 2-n áll, a feldolgozott mutató 510-en, akkor
  1. (512 + 2 - 510) % 512 = 4


Tehát 4 elemet tudsz feldolgozni.
A hozzászólás módosítva: Máj 29, 2017
(#) csatti2 válasza cimopata hozzászólására (») Máj 29, 2017 /
 
Szerintem nem törölted előtte az Enable bitet. Általában azt szokták elfelejteni (a DMA felfutó élre indul, ha nem törlöd az Enable-t, nincs felfutó él se).
Én is körkörös DMA-val oldom meg a fogadást. Nem kell amiatt aggódni, hogy adatot vesztesz az indítgatás során. Arra ügyelni kell persze, hogy belátható időn belül feldogozd persze a puffer-t, nehogy felülíródjon.
(#) icserny válasza csabeszq hozzászólására (») Máj 29, 2017 /
 
Idézet:
„Neharagudjatok a kérdésért, de milyen IDE-t érdemes használni ARM-ra?”

Az nem tudom, hogy melyiket érdemes használni, de vannak olyanok, mint pl:
Atollic TrueStudio (van ingyenes Lite változata, méretkorlátozás nélkül)
Segger Embedded Studio (noncommercial verziója ingyenes, méretkorlátozás nélkül)
(#) cimopata válasza icserny hozzászólására (») Máj 29, 2017 /
 
Ma szerettem volna folytatni a rx dma kiegészítéssel.

Már legeneráltam a kódot stm cube-ak hogy tuti ne legyen hiba de amint berakom a USART1->CR3 = USART_CR3_DMAR; parancsot a TX rész megszűnik működni. Egyszerűen nem értem, lassan tökön szúrom magam.
  1. USART1->BRR = 480000 / 384; /* (1) */
  2.         USART1->CR3 = USART_CR3_DMAT;
  3.         USART1->CR3 = USART_CR3_DMAR;
  4.         USART1->CR1 = USART_CR1_TE |
  5.                                 USART_CR1_RE |
  6.                                 USART_CR1_UE; /* (3) */
  7.                                                                
  8.          
  9.         DMA1_Channel2->CPAR  = (uint8_t)(&(USART1->TDR));       // peripheral  address
  10.         DMA1_Channel2->CMAR  = (uint8_t)(usart_tx_store);         // memory  address
  11.         DMA1_Channel2->CNDTR = 5;                             //  DAM átvitt adatok mennyisége
  12.         DMA1_Channel2->CCR |= DMA_CCR_PL_1;     // dma priority
  13.         DMA1_Channel2->CCR |= DMA_CCR_MINC ;    // memory increment mode enable
  14.         DMA1_Channel2->CCR |= DMA_CCR_DIR; // Memory to peripheral direction
  15.         DMA1_Channel2->CCR |= DMA_CCR_EN ;      // Enable channel      
  16.        
  17.        
  18.        
  19.         DMA1_Channel3->CPAR  = (uint8_t)(&(USART1->RDR));       // peripheral  address
  20.         DMA1_Channel3->CMAR  = (uint8_t)(usart_rx_store);         // memory  address
  21.         DMA1_Channel3->CNDTR = 5;                             //  DAM átvitt adatok mennyisége
  22.         DMA1_Channel3->CCR |= DMA_CCR_PL_1;     // dma priority
  23.         DMA1_Channel3->CCR |= DMA_CCR_MINC ;    // memory increment mode enable
  24.         DMA1_Channel3->CCR |= DMA_CCR_CIRC; // circular mode enable
  25.        
  26.        
  27.         DMA1_Channel3->CCR |= DMA_CCR_EN ;      // Enable channel        start trigger.
A hozzászólás módosítva: Máj 29, 2017
(#) csatti2 válasza cimopata hozzászólására (») Máj 29, 2017 /
 
= -t használsz |= helyett...
(#) kapu48 válasza csabeszq hozzászólására (») Máj 31, 2017 /
 
Magyarázzátok már el nekem!

Hogy az ilyen definiciók mért vannak do { között } while(0) ?
  1. #define __HAL_RCC_LSE_CONFIG(__STATE__) \
  2.                     do {                                       \
  3.                       if((__STATE__) == RCC_LSE_ON)            \
  4.                       {                                        \
  5.                         SET_BIT(RCC->BDCR, RCC_BDCR_LSEON);    \
  6.                       }                                        \
  7.                       else if((__STATE__) == RCC_LSE_BYPASS)   \
  8.                       {                                        \
  9.                         SET_BIT(RCC->BDCR, RCC_BDCR_LSEBYP);   \
  10.                         SET_BIT(RCC->BDCR, RCC_BDCR_LSEON);    \
  11.                       }                                        \
  12.                       else                                     \
  13.                       {                                        \
  14.                         CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEON);  \
  15.                         CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); \
  16.                       }                                        \
  17.                     } while(0)

A hozzászólás módosítva: Máj 31, 2017
(#) csatti2 válasza kapu48 hozzászólására (») Máj 31, 2017 / 1
 
A #define-al olyan makrókat hozol létre, amik a tényleges fordítás előtt kicserélik a makró nevét a makró-ban defininált szövegre. Ha nem csinálod elég általánosra a makrót, akkor ezért érdekes "mágikus" hibaüzeneteket kaphatsz, amiket néha komoly szívás kijavítani.
A do { .. } while(0) egy ügyes trükk, ami bármely olyan helyre beszúrhatóvá teszi a makrót, ahol sok esetben hibát okozhatna, ha mint függvényt próbálnánk használni azt a do while nélkül. pl.: mi történik ha egy if-ben használod a fenti makrót (do while nélkül) és utána raksz egy else-t, ami egyébként rendben is lenne? Hibaüzenet, hogy mit akarsz else-vel if nélkül, te meg pislognál, hogy mégis mi van.
Következő: »»   93 / 178
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