Fórum témák

» Több friss téma
Fórum » PIC programozása C nyelven, C-Compiler
Lapozás: OK   98 / 153
(#) Wudoou válasza watt hozzászólására (») Jún 10, 2014 /
 
Átszerveztem a programot, most 20 Mhz-en megyek, 9600-as BAUD-al. A helyzet a következő:
Néha, 5000-ből 1-2 invalid response hibával jelentkezik. Sajnos az adatforgalmat megnézve észrevettem, hogy a csomag első néhány bájtja hiányzik. A puffer mutatót jól kezelem, gyanítom, hogy az RTS vonal kapcsolgatása miatt lehet a dolog.
Max485-öt használok, hogyan javasolt az rts vonal váltása?
Most úgy van, ha bejött egy csomag, akkor meghív egy ellenőrző függvényt, ennek a függvénynek a visszatérési értéke határozza meg, hogy mit kell csinálni. Ha 0, akkor a csomag rendben ekkor állítom az RTS vonalat egybe, majd meghívom azt a függvényt, ami a választ készíti elő, ezt követően pedig válaszolok. Ha kiürült a küldő pufferem, RTS = 0.
Igy elkerülhető lenne a késleltetés az RTS vonal kapcsolgatása miatt.
De valami csak nincs rendben. Mindenképpen el szeretném kerülni a delay használatát, van valami javaslat?
(#) potyo válasza Wudoou hozzászólására (») Jún 10, 2014 /
 
Bár gondolom így van, de azért rákérdezek: az RTS vonalat akkor kapcsolod ki, amikor az utolsó bit is kiért, vagy pedig akkor, amikor a pufferből átkerül az adat a shift regiszterbe?
(#) watt válasza Wudoou hozzászólására (») Jún 10, 2014 /
 
Sajnos a kábel hosszától függően mindenképpen szükséges időzítés a kommunkáció irányának megváltoztatása után, az első adatok előtt és az utolsó adat kijutását is meg kell várni...
(#) Wudoou válasza potyo hozzászólására (») Jún 10, 2014 /
 
Amikor kiürül a puffer, be van téve egy 3,5 karakter időt késleltető timer és utána kapcsolom ki.
Az elvileg majdnem 4 ms.
(#) Wudoou válasza watt hozzászólására (») Jún 10, 2014 /
 
A késleltetés úgy gondoltam elég, ha a függvény meghívása előtt kapcsolom az RTS vonalat.
Az kb 4-500 us. A modscan scan rate most 1000 ms, de 400 ms-el próbálgattam.
A delay between polls pedig 200ms.
(#) Wudoou válasza Wudoou hozzászólására (») Jún 10, 2014 /
 
Szóval így:
  1. if ( !kimeno_puffer.UARTIntTxBufferEmpty )
  2.          {
  3.          TXREG = kimeno_puffer.vUARTIntTxBuffer[kimeno_puffer.vUARTIntTxBufRdPtr];
  4.          //if ( parity )
  5.          //   {
  6.          //   addParityBit(0, vUARTIntStatus->vUARTIntTxBuffer[vUARTIntStatus->vUARTIntTxBufRdPtr]);
  7.          //   }
  8.  
  9.          kimeno_puffer.UARTIntTxBufferFull = 0;
  10.          kimeno_puffer.vUARTIntTxBufDataCnt--;
  11.          if ( kimeno_puffer.vUARTIntTxBufDataCnt == (UINT)0 )
  12.             {
  13.             kimeno_puffer.UARTIntTxBufferEmpty = 1;
  14.             }
  15.          kimeno_puffer.vUARTIntTxBufRdPtr++;
  16.          if ( kimeno_puffer.vUARTIntTxBufRdPtr >= ( BYTE)TX_BUFFER_SIZE )
  17.             {
  18.             kimeno_puffer.vUARTIntTxBufRdPtr = 0;
  19.             }
  20.          }
  21.       else
  22.          {
  23.          PIE1bits.TXIE = 0;
  24.                  MB_end_flag=1;         //jelezzük, hogy elment az utolsó karakter
  25.                  reset_t0();                    //engedélyezzük t0-t, hogy lejárjon a 3,5 karakternyi idő
  26.        
  27.          }


Majd a reset_t0():
  1. if (T0IE && T0IF)
  2.         {
  3.  
  4.                 if(MB_end_flag) //ha lejárt az idő, akkor mehet a modbus kérés ismét, befejeztük az adást
  5.                 {
  6.                         Bejovo_puffer.hossz = 0;
  7.                         MB_end_flag = 0;
  8.                         RTS_OFF();
  9.                 }
  10.                 if(MB_start_flag)               //ha bejött minden karakter és lejárt az idő, akkor mehet a kiértékelés
  11.                 {
  12.                         soros_flag = 1;
  13.                         MB_start_flag = 0;
  14.                 }
  15.            delete_t0();
  16.         }


Ahol a reset_t0():
  1. void reset_t0 (void)
  2. {
  3.         TMR0 = 100;
  4.         T0IE = 0;
  5.         T0IF = 0;
  6.         OPTION_REG=0x06;
  7.         T0IE = 1;
  8. }


Bekapcsolni pedig:
  1. if (soros_flag)
  2.                 {
  3.                         MB_control = ReadMBFrame();
  4.  
  5.                         if (MB_control == 0)
  6.                         {
  7.                           RTS_ON();
  8.                           readRegResponse(&atlag);     
  9.                           PIE1bits.TXIE = 1;
  10.                         }
  11.                         else if ( MB_control > 0)
  12.                         {
  13.                           RTS_ON();
  14.                           writeBadRequest(MB_control);
  15.                           PIE1bits.TXIE = 1;
  16.                         }
  17.                         soros_flag=0;
  18.  
  19.                 }
A hozzászólás módosítva: Jún 10, 2014
(#) Wudoou válasza Wudoou hozzászólására (») Jún 11, 2014 /
 
Urak!

Ezzel a módosítással már szépen, hibátlanul működik.
  1. if (MB_control == 0)
  2.                         {
  3.                           RTS_ON();
  4.                            DelayUs(200);
  5.                            DelayUs(100);
  6.                           readRegResponse(&atlag);     
  7.                           PIE1bits.TXIE = 1;
  8.                         }

Hogy tudnám ezt elkerülni? Valaki esetleg?
A hozzászólás módosítva: Jún 11, 2014
(#) watt válasza Wudoou hozzászólására (») Jún 11, 2014 /
 
Ha belefér az időbe és nem a megszakításban várakozol, akkor maradhat így is, mert a fontos dolgok úgy is megszakítják.
A vonalak váltása időt igényel, ezt nem tudod elkerülni.
(#) Wudoou válasza watt hozzászólására (») Jún 11, 2014 /
 
Értem. És mennyi a javasolt késleltetés? Nekem a DE RE össze van kötve és +Vdd-re van csatlakoztatva egy 4,7 K-s felhúzón keresztül és rá van kötve a PIC egyik lábára. Ti is így használjátok? Nem akarok visszaolvasást küldéskor...Mennyi késleltetés javasolt?
(#) Wudoou válasza Wudoou hozzászólására (») Jún 11, 2014 /
 
Most ilyen hibám érkezett (lásd csatolmány). Bár meg kell mondjam felturboztam a scan rate-t a modscan32-n 150 ms-ra. Ekkor jönnek ezek a hibák. Lehet, hogy ez már nem is az én vezérlőm hibája, hanem az RS232 - USB konverteré?

hiba.jpg
    
(#) watt válasza Wudoou hozzászólására (») Jún 11, 2014 /
 
Meg lehet keresni a minimumot(kábelhossz (kapacitás, induktivitás) függő), de szerintem nincs értelme kihegyezni. Ha ettől nem lenne elég a sebesség, az régen rossz. Az RS485-nek, pontosabban az egyszerű soros vonalaknak nem a sebesség a legfőbb erősségük.

Ha jól látom lemaradnak az adatok, helyette újabb "fejlécet" küld el a PC? Hogyan detektálod ezeket az adatokat?
Mindenesetre érdekes, de ez nem biztos, hogy hardwer hiba. Az átalakítók is tudnak érdekesen viselkedni. Akkor lehetne ezt kiszűrni, ha lenne valós COM-od. Én vettem egy PCI kártyát...

Kezdem sejteni a dolgot. Tehát a PC küldi a csomagot és nem válaszol a PIC, ezért lejár a 150ms és jön a következő kérés. Ez lehet a PIC program hibája is, de lehet az átalakítóé is, vagy még mindig rövid az irányváltási idő. Persze egy fordulónak bele kell férnie a 150ms-be minden eshetőséggel...
A hozzászólás módosítva: Jún 11, 2014
(#) Wudoou válasza watt hozzászólására (») Jún 11, 2014 /
 
Idézet:
„Hogyan detektálod ezeket az adatokat?”

Mármint miket?
(#) watt válasza Wudoou hozzászólására (») Jún 11, 2014 /
 
Egyébként az irányokat egyszerűen úgy kezelem, hogy a slave mindig bemenet, kivéve ha fel van jogosítva a válaszra. Tehát ha küldeni kell, akkor irányváltás kimenet, időzítés vonal beálltára, küldés megkezdése megszakításban, utolsó bájt kiérkezésének figyelése, újra bemenetre váltás.
(#) watt válasza Wudoou hozzászólására (») Jún 11, 2014 /
 
A képen...
(#) Wudoou válasza watt hozzászólására (») Jún 11, 2014 /
 
Modscan32-vel. Figyelem, mikor hibázik, majd printscreen.
(#) Wudoou válasza watt hozzászólására (») Jún 11, 2014 /
 
Én is ugyanígy.
(#) watt válasza Wudoou hozzászólására (») Jún 11, 2014 /
 
Volt ott valami 3,5 karakteridő várakozás az adás utáni vételre váltás előtt is, nem? Vagy elnéztem...
(#) Wudoou válasza watt hozzászólására (») Jún 12, 2014 /
 
Igen, az eredetiben volt, de már átírtam így:
  1. if (soros_flag)
  2.                 {
  3.                         MB_control = ReadMBFrame();
  4.  
  5.                         if (MB_control == 0)
  6.                         {
  7.                           RTS_ON();
  8.                         DelayUs(250);
  9.                         DelayUs(250);
  10.                           readRegResponse(&atlag);     
  11.                           PIE1bits.TXIE = 1;
  12.                         }
  13.                         else if ( MB_control > 0)
  14.                         {
  15.                           RTS_ON();
  16.                         DelayUs(250);
  17.                         DelayUs(250);
  18.                           writeBadRequest(MB_control);
  19.                           PIE1bits.TXIE = 1;
  20.                         }
  21.                         soros_flag=0;
  22.                 }


  1. if ( PIR1bits.TXIF & PIE1bits.TXIE )
  2.       {
  3.       if ( !kimeno_puffer.UARTIntTxBufferEmpty )
  4.          {
  5.          TXREG = kimeno_puffer.vUARTIntTxBuffer[kimeno_puffer.vUARTIntTxBufRdPtr];
  6.          //if ( parity )
  7.          //   {
  8.          //   addParityBit(0, vUARTIntStatus->vUARTIntTxBuffer[vUARTIntStatus->vUARTIntTxBufRdPtr]);
  9.          //   }
  10.  
  11.          kimeno_puffer.UARTIntTxBufferFull = 0;
  12.          kimeno_puffer.vUARTIntTxBufDataCnt--;
  13.          if ( kimeno_puffer.vUARTIntTxBufDataCnt == (UINT)0 )
  14.             {
  15.             kimeno_puffer.UARTIntTxBufferEmpty = 1;
  16.             }
  17.          kimeno_puffer.vUARTIntTxBufRdPtr++;
  18.          if ( kimeno_puffer.vUARTIntTxBufRdPtr >= ( BYTE)TX_BUFFER_SIZE )
  19.             {
  20.             kimeno_puffer.vUARTIntTxBufRdPtr = 0;
  21.             }
  22.          }
  23.       else
  24.          {
  25.          PIE1bits.TXIE = 0;
  26.                  while ( TXSTAbits.TRMT == (BYTE)0 );
  27.                  RTS_OFF();
  28.                  Bejovo_puffer.hossz = 0;

De így is van egy-két hiba. Mostmár eléggé bosszantó...
(#) watt válasza Wudoou hozzászólására (») Jún 12, 2014 /
 
A megszakításban való küldést így oldom meg:
  1. //EUSART1 TX1 INT Küldés (RS485)
  2. if (PIE1bits.TX1IE && PIR1bits.TX1IF){
  3. if(TX1_cik>Data_TX1_Size){
  4.                 PIE1bits.TX1IE=Ki;              // TX megszakítás kikapcs
  5.                 RS485_Vetel_1();                //Adás végén vételre váltunk
  6.         }else{
  7.                 TXREG1=TX1_DataPointer[TX1_cik++];
  8.         }                      
  9. }

És így hívom meg:
  1. //________________________________________________________|
  2. //                      TX1 Adat küldés INT-ben CRC-vel                                 |
  3. //________________________________________________________|
  4. void TX1_Send_CRC(unsigned char Size, unsigned char* Buffer){
  5.         unsigned int CRC_Ertek_int, cik;
  6.         CRC_Ertek_int=Modbus_CRC16(Buffer, Size);
  7.         Buffer[Size++]=CRC_Ertek_int >> 8;      //CRC High
  8.         Buffer[Size++]=CRC_Ertek_int;           //CRC Low                                              
  9.         Data_TX1_Size=Size;                                     //Adatcsomag hossza;
  10.         TX1_cik=0;
  11.         TX1_DataPointer=Buffer;
  12.         RS485_Adas_1();
  13.         for(cik=0;cik<1000;cik++);                      //Vonal beállására várunk                  
  14.         PIE1bits.TX1IE=Be;      //Adás indítása TX1 megszakítás engedélyezésével.
  15. }
A hozzászólás módosítva: Jún 12, 2014
(#) Wudoou válasza watt hozzászólására (») Jún 12, 2014 /
 
Hát hasonlóan kezeled.
Ez miért jobb, mint a delay?
  1. for(cik=0;cik<1000;cik++);

Illetve itt nem használsz késleltetést?
  1. RS485_Vetel_1();                //Adás végén vételre váltunk
(#) watt válasza Wudoou hozzászólására (») Jún 12, 2014 /
 
Nem jobb, csak mindegy. Egyébként függvényhívás nélküli várakozás. Nem szeretem a C függvényeit...

A TX1_cik akkor lesz nagyobb, mint a Data_TX1_Size(adathossz), ha már kiment mindegyik bájt. Az utolsó bájt kilépése után még egy megszakítás fog történni, ekkor már nincs mire várni. while-t, vagy bármilyen várakozást megszakításba tenni nem illik, még ha egy karakternyi időről is van szó, ami egyébként rengeteg utasítás helyét emésztené fel...
A hozzászólás módosítva: Jún 12, 2014
(#) Wudoou válasza watt hozzászólására (») Jún 12, 2014 /
 
Ez nem lehet igaz!!!! 2000-3000 üzenet hibátlan, utána be-becsúszik 1-2 hibás újra. Egyszerűen nem értem. Akkor ezt vegyem ki?
  1. PIE1bits.TXIE = 0;
  2.                  while ( TXSTAbits.TRMT == (BYTE)0 );
  3.                  RTS_OFF();
  4.                  Bejovo_puffer.hossz = 0;
(#) watt válasza Wudoou hozzászólására (») Jún 12, 2014 /
 
Mi a gond azzal, hogy néhány csomag elvész? Ez alapértelmezés egy wifinél, még is működik...

Ha ide akkor jön be a megszakítás, miután az utolsó adat kiment, nincs szükség a TRMT vizsgálatára.
(#) Hp41C válasza watt hozzászólására (») Jún 12, 2014 /
 
A TX megszakítás akkor jön, ha a Tx buffer regiszter üres, az utolsó karakter akkor ment el, ha az utolsó karakter betöltése után a TXSTA regiszter TRMT bitje 0 értékű lesz. Egy "üres" adó (jó régen nem kellett küldeni semmit sem) egymásután két karaktert képes átvenni, az első egyből átkerül a léptető regiszterbe, a másodikat pedig a buffer tárolja. Ebből az jön ki, hogy az utolsó karakter betöltése után a TXIF akkor lesz ismét 1 (megszakíáskérés), ha a karakter átkerült a Tx léptető regiszterbe. A vonalat pedig csak ez után akkor lehet vételre kapcsolni, ha a TRMT jelzőbit is 0 lesz. Sajnos a TRMT nem okoz megszakítást.
A hozzászólás módosítva: Jún 12, 2014
(#) watt válasza Hp41C hozzászólására (») Jún 12, 2014 /
 
Nem vitaképpen, mert ezen nem lehet, de akkor hogyan létezik, hogy hibanélkül működik?
(#) Wudoou válasza Hp41C hozzászólására (») Jún 12, 2014 /
 
Akkor ezek szerint mégiscsak jól tettem, hogy benne van. Nemde?
(#) Wudoou válasza watt hozzászólására (») Jún 12, 2014 /
 
Nem akarok olyan programot írni,a mit nem értek, miért működik / nem működik.
Meg szeretném érteni, mit rontok el. Csupán ennyi lenne. Amúgy ha megnézed a kódot,
  1. if ( kimeno_puffer.vUARTIntTxBufDataCnt == (UINT)0 )
  2.             {
  3.             kimeno_puffer.UARTIntTxBufferEmpty = 1;

Vagyis beállítja a kimeno_puffer.UARTIntTxBufferEmpty egybe, de csak a következő ciklusban vizsgálja meg:
  1. if ( PIR1bits.TXIF & PIE1bits.TXIE )
  2.       {
  3.       if ( !kimeno_puffer.UARTIntTxBufferEmpty )
  4.          {
  5.          TXREG = kimeno_puffer.vUARTIntTxBuffer[kimeno_puffer.vUARTIntTxBufRdPtr];
  6.          //if ( parity )
  7.          //   {
  8.          //   addParityBit(0, vUARTIntStatus->vUARTIntTxBuffer[vUARTIntStatus->vUARTIntTxBufRdPtr]);
  9.          //   }
  10.  
  11.          kimeno_puffer.UARTIntTxBufferFull = 0;
  12.          kimeno_puffer.vUARTIntTxBufDataCnt--;
  13.          if ( kimeno_puffer.vUARTIntTxBufDataCnt == (UINT)0 )
  14.             {
  15.             kimeno_puffer.UARTIntTxBufferEmpty = 1;
  16.             }
  17.          kimeno_puffer.vUARTIntTxBufRdPtr++;
  18.          if ( kimeno_puffer.vUARTIntTxBufRdPtr >= ( BYTE)TX_BUFFER_SIZE )
  19.             {
  20.             kimeno_puffer.vUARTIntTxBufRdPtr = 0;
  21.             }
  22.          }
  23.       else
  24.          {
  25.          PIE1bits.TXIE = 0;
  26.                  while ( TXSTAbits.TRMT == (BYTE)0 );
  27.                  RTS_OFF();
  28.                  Bejovo_puffer.hossz = 0;
A hozzászólás módosítva: Jún 12, 2014
(#) watt válasza Wudoou hozzászólására (») Jún 12, 2014 /
 
Nem tudok erre mit mondani. Nekem működik. A te megoldásodat nem teljesen látom át, mert sok a felesleges sallang. De ettől még működnie kéne, ha hibátlan. Nem stílustanulmányt kell írni, csak egy jó programot.

A felvetés szerint egyébként a programom nem működhetne, mert az utolsó bájt a CRC alsó bájtja. Ha nem várnám meg míg kiér, soha nem lenne elfogadva CRC hiba miatt. Márpedig ha tényleg úgy működik ahogy Hp41C leírta, nem működhetne, mert 19200-on kb. fél msec egy bájt ideje, a kikapcsolás viszont usec nagyságrend alatt van.
Érdekelne, hogy mi miatt tud működni egy elvileg lehetetlen működés!
(#) watt válasza Wudoou hozzászólására (») Jún 12, 2014 /
 
Kipróbálhatnád, hogy kikommenteled a TRMT sort, mi történik!? Ez csak fél perc...
(#) Wudoou válasza watt hozzászólására (») Jún 12, 2014 /
 
Igazából annyira nem akartam megbonyolítani, van egy puffer tele jelző, egy puffer üres jelző, egy puffer adat számláló, meg egy adatmutató. A puffer tele jelzőt, puffer üres jelzőt ki lehetne hagyni, mert egy if-el kiderülne, de így oldottam meg. Holnap kipróbálom kikommentelve azt a sort, de azt hiszem volt már úgy, hogy nem volt benne és nekem is működött csak több hibám volt.
Következő: »»   98 / 153
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