Vai al contenuto
PLC Forum

Partecipa anche tu alla Live su Youtube martedì 28/01/2025 per festeggiare i 24 anni di PLC Forum

Per ulteriori informazioni leggi questa discussione: https://www.plcforum.it/f/topic/326513-28012025




Tipo Di Dati Pointer


Messaggi consigliati

Inserito:

Ciao a tutti,

ho un problema di questo tipo:

Devo utilizzare la funzione di libreria dello STEP7 "ATH" (conversione ASCII to HEX);

questa funzione riceve in ingresso l'indirizzo del primo carattere da convertire, in

formato POINTER.

Purtroppo questo indirizzo di partenza non è per me sempre lo stesso ma in base a

dei calcoli può variare, cioè vorrei poter puntare ad un qualsiasi byte della DB2 e

poi passare questo indirizzo alla ATH.

Ho fatto vari tentativi ma ho paura che l'ingresso di tipo POINTER accetti solo puntatori

"costanti" del tipo P#DB2.DBX0.0.

Grazie mille a tutti coloro che risponderanno.


Matteo Montanari
Inserita:
Ho fatto vari tentativi ma ho paura che l'ingresso di tipo POINTER accetti solo puntatori

"costanti" del tipo P#DB2.DBX0.0.

esatto.

potresti "trasferire" i tuoi dati da convertire sempre nella stessa area (utilizzata come area del puntatore)

non sò a cosa ti serve il valore in HEX ma ricorda che se si tratta di convertire numeri o lettere da ASCII a Decimale occorre sottrarre alla cifra ASCII la costante 48 (30 HEX) e che un carattere ASCII occupa un byte.

può essere che se si tratta di pochi dati di cui fare la conversione ti basti questo, senza utilizzare il blocco "pre-confezionato SIEMENS"

in alternativa potresti controllare questo codice se ti è d'aiuto:

FUNCTION "ATH" : WORD
TITLE = ASCII TO HEX 
AUTHOR : SEA
FAMILY : CONVERT
NAME : ATH
VERSION : 2.0


VAR_INPUT
  IN : POINTER;    // pointer to an ASCII string
  N : WORD;    // number characters (bytes)in ASCII string
END_VAR
VAR_OUTPUT
  OUT : POINTER;    // pointer to the hexidecimal destination table
END_VAR
VAR_TEMP
  BLKNO : WORD;    // Block number
  INDX_A : DWORD;    // Character index   
  INDX_D : DWORD;    // Digit index     
  INVFLG : WORD;    // Invalid flag 
  TMP1 : BYTE;    // value of the table WORD currently read 
  TMP2 : BYTE;    // Hex digit ANDed w/0x000F, then added to x30/x37 
  TMPLEN : WORD;    // length val. used in validating hex digits
  N2 : WORD;    // copy of org. TMPLEN value, used for comparison
  TEMP_AR2 : DWORD;    // Storage for AR2 contents, which is restored before return
END_VAR
BEGIN
NETWORK
TITLE =

      TAR2  #TEMP_AR2; // Save Address register 2 contents    
      L     0; 
      T     #INVFLG; 
      T     #RET_VAL; 
      T     #INDX_D; 

// Open DB of ptr to ascii input digits
      L     P##IN; 
      LAR1 ; // Addr.Reg1 = Ptr to Src. Table 
      L     W [AR1,P#0.0]; // load Block No. into accum 1
      T     #BLKNO; // scrblk = Block No. 
      AUF   DB [#BLKNO]; // opens 1st Block, DB
      L     D [AR1,P#2.0]; // load Block Area Reference
      LAR1 ; // load Block Addr.(area ref.)into Addr.Reg1
//---------------------------------------------------------------------------        
// Open DI of ptr to hex output digits
      L     P##OUT; 
      LAR2 ; // Addr.Reg2 = Ptr to output 
      L     W [AR2,P#0.0]; // load Block No. into accum 1
      L     0; // CORRECTION ADDED BY STEVE LOVELL ON 5/98
      ==I  ; 
      SPZ   BEGN; 
      L     W [AR2,P#0.0]; // CORRECTION ADDED BY STEVE LOVELL ON 5/98
      T     #BLKNO; // scrblk = Block No. 
      AUF   DI [#BLKNO]; // opens DI Block
// 
// START OF CORRECTION ADDED BY STEVE LOVELL 5/98
// 
      L     DW#16#5000000; // OR mask for DIX memory area in ptr
      L     D [AR2,P#2.0]; // load Block Area Reference; start addr.
      OD   ; // Force memory area to DIX
      LAR2 ; // Save into AR2
      SPA   BEG2; // Jump to label BEG2
// 
// END OF CORRECTION
//  

BEGN: L     D [AR2,P#2.0]; // start addr.       
      LAR2 ; // load Block Addr.(area ref.)into Addr.Reg1
BEG2: NOP   0; // CORRECTION ADDED BY STEVE LOVELL ON 5/98
//---------------------------------------------------------------------------        
// Check validity of each ascii input characters
      L     0; 
      T     #TMP2; 
      T     #TMP1; 

      L     #N; 
      T     #TMPLEN; 
      T     #N2; 
      L     0; 
      ==I  ; 
      SPB   DONE; // if length=0, there is nothing to do

// If length is an odd number, make the length even (add 1)
      L     W#16#1; 
      L     #TMPLEN; 
      UW   ; 
      L     0; 
      ==I  ; 
      SPB   BGIN; 
      L     #TMPLEN; 
      L     1; 
      +I   ; 
      T     #TMPLEN; 
      T     #N2; 

BGIN: L     #TMPLEN; 
NEXT: T     #TMPLEN; 
      L     B [AR1,P#0.0]; // Accum2, if(digit < 0x2F)
      L     B#16#30; // Accum1
      <I   ; 
      SPB   BAD; // Bad, Out of range
//----        
      L     B [AR1,P#0.0]; // Accum2, if(digit > 0x0x47)
      L     B#16#46; // Accum1
      >I   ; 
      SPB   BAD; // Bad, Out of range
//----        
      L     B [AR1,P#0.0]; // Accum2, if(digit == 0x0x40)
      L     B#16#40; // Accum1
      ==I  ; 
      SPB   BAD; // Bad, Out of range
//---------------------------------------------------------------------------        
      L     B [AR1,P#0.0]; // Accum2, if(digit < 0x3A)
      L     B#16#3A; // Accum1
      <I   ; 
      SPB   SB30; // Go subtract 0x30
//----        
      L     B [AR1,P#0.0]; // Accum2, if(digit > 0x40)
      L     B#16#40; // Accum1
      >I   ; 
      SPB   SB37; // Go subtract 0x37

BAD:  L     1; // Invalid value: set "invalid' flag
      T     #INVFLG; 
      L     0; 
      T     #TMP1; 
      SPB   CONT; // Go process as zero value 
//---------------------------------------------------------------------------        
SB30: L     B [AR1,P#0.0]; 
      L     B#16#30; 
      -I   ; 
      T     #TMP1; 
      SPA   CONT; 

SB37: L     B [AR1,P#0.0]; 
      L     B#16#37; 
      -I   ; 
      T     #TMP1; 
//---------------------------------------------------------------------------        
CONT: L     #INVFLG; 
      L     1; 
      ==I  ; // if (INVFLG =1)
      SPBN  GOOD; 
      L     7; 
      T     #RET_VAL; //    Set ErrorCode in RET_VAL 
      L     0; 
      T     #INVFLG; // Re-set INVFLG to 0
//----
GOOD: L     #INDX_D; // INDX_D = INDX_D + 1;
      L     1; 
      +I   ; 
      T     #INDX_D; 
      L     2; // when INDX_D is 2, time to write out a byte
      ==I  ; 
      SPB   WOUT; // go merge nibbles & write out hex byte

      L     #TMP1; 
      SLW   4; 
      T     #TMP2; 

// If last nibble needs filler of 0, detect & set it up here
      L     2; 
      L     #TMPLEN; // Is pointer at last byte?
      <>I  ; 
      SPB   REPT; // No, pointer is not at last nibble yet

      L     #N2; // Pointer at last nibble, is filler needed?
      L     #N; 
      ==I  ; // No, no filler needed 
      SPB   REPT; 
      L     0; // Yes, make last nibble a 0                  
      T     #TMP1; 
      L     #TMPLEN; 
      L     1; 
      -I   ; 
      T     #TMPLEN; // Decrement TMPLEN manually if using filler 

WOUT: L     #TMP2; 
      L     #TMP1; 
      OW   ; // Merge 2 nibbles into one byte 

      T     B [AR2,P#0.0]; // write one byte to output

      L     0; 
      T     #TMP2; // clear out variables by writing zeros
      T     #INDX_D; 

// Increment AR2, Hex Ouput pointer, by one byte
      +AR2  P#1.0; 

REPT: +AR1  P#1.0; // Increment AR1, ASCII Input pointer, by one byte
      L     0; 
      T     #TMP1; // Clear out TMP1 byte variable
      L     #TMPLEN; // LOOP statement decrements TMPLEN
      LOOP  NEXT; 

DONE: L     0; 
      L     #RET_VAL; 
      <>I  ; 
      SPB   FAIL; 

      SET  ; 
      SPA   STOP; 

FAIL: CLR  ; 
STOP: SAVE ; 
      LAR2  #TEMP_AR2; // Restore Address Register 2 Contents

END_FUNCTION
mentre questo codice è la funzione inversa
FUNCTION "HTA" : VOID
TITLE = HEX TO ASCII
AUTHOR : SEA
FAMILY : CONVERT
NAME : HTA
VERSION : 2.0


VAR_INPUT
  IN : POINTER;    
  N : WORD;    
END_VAR
VAR_OUTPUT
  OUT : POINTER;    
END_VAR
VAR_TEMP
  BLKNO : WORD;    // Block number
  INDX_D : DWORD;    // Digit index     
  TMP1 : WORD;    // the BYTE nibble being converted from Hex to Ascii 
  SAVTMP1 : WORD;    // the table BYTE that was read last 
  TMPLEN : WORD;    // length val. -Number of bytes in table
  ABYTE : BYTE;    // TMP1 value stored as a BYTE value
  TEMP_AR2 : DWORD;    // Storage for AR2 contents, which is restored before return
END_VAR
BEGIN
NETWORK
TITLE =

      TAR2  #TEMP_AR2; // Save Address register 2 contents    
// If length to be converted is 0, return immediately 
      L     #N; 
      L     0; 
      ==I  ; 
      SPB   DONE; 

// Open DB of ptr to hex input digits
      L     P##IN; 
      LAR1 ; // Addr.Reg1 = Ptr to Src. Table 
      L     W [AR1,P#0.0]; // load Block No. into accum 1
      T     #BLKNO; // scrblk = Block No. 
      AUF   DB [#BLKNO]; // opens 1st Block, DB
      L     D [AR1,P#2.0]; // load Block Area Reference
      LAR1 ; // load Block Addr.(area ref.)into Addr.Reg1
//---------------------------------------------------------------------------        
// Open ptr to output Ascii Locations as a DI
      L     P##OUT; 
      LAR2 ; // Addr.Reg2 = Ptr to Output  
      L     W [AR2,P#0.0]; // load Block No. into accum 1
      L     0; // CORRECTION ADDED BY STEVE LOVELL 5/98
      ==I  ; 
      SPZ   BEGN; 
      L     W [AR2,P#0.0]; // CORRECTION ADDED BY STEVE LOVELL 5/98
      T     #BLKNO; // scrblk = Block No. 
      AUF   DI [#BLKNO]; // opens DI Block

// 
// START OF CORRECTION ADDED BY STEVE LOVELL 5/98
// 
      L     DW#16#5000000; // OR mask for DIX memory area in ptr
      L     D [AR2,P#2.0]; // load Block Area Reference; start addr.
      OD   ; // Force memory area to DIX
      LAR2 ; // Save into AR2
      SPA   BEG2; // Jump to label BEG2
// 
// END OF CORRECTION
// 

BEGN: L     D [AR2,P#2.0]; // start addr.       
      LAR2 ; // load Block Addr.(area ref.)into Addr.Reg1
BEG2: NOP   0; // CORRECTION ADDED BY STEVE LOVELL 5/98
//---------------------------------------------------------------------------        
      L     #N; // Load length of HEX table
BYTS: T     #N; 
      L     B [AR1,P#0.0]; // Load byte from table
      T     #TMP1; // and write it into TMP1 word
      T     #SAVTMP1; // save a copy of the table's org. value

      L     2; // number of hex input digits extracted
DIGT: T     #INDX_D; // 1 byte (2 hex digits); 1 byte=2 nibbles 
//-------------
      L     #SAVTMP1; // save a copy of the table's org. value
      T     #TMP1; 

      L     2; 
      L     #INDX_D; 
      <>I  ; 
      SPB   MASK; 
      L     #TMP1; 
      SRW   4; 
      T     #TMP1; 
//-------------
MASK: L     #TMP1; // Accum 2
      L     W#16#F; // Accum 1
      UW   ; // TMP1 AW 0x000F (mask off all but lower nibble)

      T     #ABYTE; // convert from WORD to BYTE
      L     B#16#A; // Load 0x0A
      <I   ; // (Accum2 < Accum1)?  (ABYTE < 0x0A)?
      SPB   A030; // Jump to Add 0x30
      SPA   A037; // Jump to Add 0x37

// Add 0x30
A030: L     B#16#30; 
      L     #ABYTE; 
      +I   ; // 0x30 + ABYTE
      T     #ABYTE; 
      SPA   CONT; // Jump to continue

// Add 0x37
A037: L     B#16#37; 
      L     #ABYTE; 
      +I   ; // 0x37 + ABYTE
      T     #ABYTE; 

//---------------------------------------------------------------------------        
// Continue
CONT: L     #ABYTE; 
      T     B [AR2,P#0.0]; // Write BYTE to ouput
      +AR2  P#1.0; // Increment pointer to output (by 1 byte)
//---------------------------------------------------------------------------        
      L     #SAVTMP1; // Copy original table's BYTE value into TMP1           
      T     #TMP1; 
      L     #INDX_D; 
      LOOP  DIGT; // }while (INDX_D <= 2)
//---------------------------------------------------------------------------        

      +AR1  P#1.0; 
      L     0; // Clear out TMP1 WORD
      T     #TMP1; // before reading next byte from table

      L     #N; 
      LOOP  BYTS; // }while (N > 0)
      SPA   DONE; 
//---------------------------------------------------------------------------        
DONE: SET  ; 

      SAVE ; 
      LAR2  #TEMP_AR2; // Restore Address Register 2 Contents

END_FUNCTION

Inserita:

Caro Marco

ti posso consigliare di andare a vedere il manuale Programmazione con step 7 che trovi nella documentazione sotto il menu Siemens che spiega come è fatto un parametro pointer.

quindi tu come parametro devi passare all'FC un doppia parola ,md ad esempio,e all'interno della doppia parola devi mettere i dati come descritto nela manuale dopo averli calcolati.

La spiegazione la trovi nell'appendice dalla pagina A51 alla pagina A55

Se non è chiaro posta di nuovo.

Ciao

Inserita:

Grazie ragazzi,

conoscendo esattamente il formato dei dati pointer ed avendo a disposizione

i sorgenti delle funzioni ho tutte le informazioni necessarie per potermi creare

delle funzioni ad hoc. :D

A proposito, come si rimediano quei sorgenti?

Ancora grazie e a presto

Marco

Matteo Montanari
Inserita:
A proposito, come si rimediano quei sorgenti?

i sorgenti sono protetti, basta "sproteggerli"... :ph34r:

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...