This subroutine was created to convert signed long integers into a floating point number. In working with Modbus communication between Multilin power monitoring breakers/meters and a PLC-5, it became necessary to translate between the two when it came to large negative numbers. The Modbus protocol transfers a large negative number (such as kVAR for instance) as one 32 digit binary number (in the binary two's complement format). The PLC, unfortunately, will read the number as two separate 16 digit numbers. The logic below helps the PLC translate these two garbled numbers into its own floating point format that will accurately represent the original number.
The first two input parameters in the first line (x & y) represent the two 16 digit integers (as the PLC interprets them). The third input (z) is a conversion number (for example the Multilin would send a power factor of 0.73 as the number 73; the PLC must then divide by 100 to get the actual power factor). X, y, and z come in as integers. F1, F2, etc. refer to floating point format buffers.
This routine was constructed around the way I was taught to convert the negative side of a two's complement number. That is, throw out the high sign bit, take the rest, reverse them, and then add one. The following routine attempts to mirror the way I would do the conversion on paper. The logic may have been written more efficiently, but it gets the job done.
------------------------------------------------------------------------------------------------------------------------------------
|************************************************************************* |
|THE FOLLOWING SUBROUTINE WAS ADDED TO CONVERT SIGNED 2'S COMPLEMENT LONG |
|INTEGERS INTO THEIR FLOATING POINT EQUIVALENT. THIS WAS MAINLY DONE FOR |
|MULTILIN CONVERSIONS OF SIGNED LONG INTEGERS THAT WOULD NOT WORK WITH THE |
|FORMER (UNSIGNED) LONG INTEGER CONVERSION SUBROUTINE. |
|CONVERSION |
|FROM SIGNED |
|LONG INTEGER CONVERSION |
|TO FLOATING SUBROUTINE |
|POINT ACTIVE |
|+--SBR--------------+ |
0||Subroutine |------------------------------------------------------------------------------------------------( )-----|
||Input Par: x| |
||Input Par: y| |
||Input Par: z| |
|+-------------------+ |
|IF THE FIRST WORD IS POSITIVE (IE THE FIRST BIT IS ZERO IN BINARY) THEN |
|THE LOWER HALF OF THIS FILE NEEDS TO BE USED. THE UPPER HALF OF THIS FILE |
|WILL BE USED WHEN THE FIRST WORD IS NEGATIVE WITH THE JUMPS SEPERATING THE |
|TWO HALVES. |
|1ST HIGH WORD |
|OF LONG INTEGER |
|+--GEQ--------------------+ J1 |
1||Grtr Than or Equal (A>=B)|--------------------------------------------------------------------------------------------[JMP]-|
||A: x| |
|| | |
||B: 0| |
|+-------------------------+ |
|BEGINNING OF UPPER HALF OF ROUTINE FOR NEGATIVE NUMBERS. THIS RUNG |
|DOES THE INTEGER EQUIVALENT OF REVERSING EACH BIT OF THE FIRST HALF OF |
|THE TWO'S COMPLEMENT BINARY WORD AND THROWING AWAY THE FIRST SIGN BIT |
| +--SUB-----------+ |
2|----------------------------------------------------------------------------------------------------------|Sub |-|
| |A: -1.0| |
| |B: x| |
| | | |
| |Dest: F1| |
| | | |
| +----------------+ |
|THIS RUNG DOES THE INTEGER EQUIVALENT OF TAKING THE SECOND WORDS BINARY |
|BITS, REVERSING THEM, AND ADDING ONE TO IT. |
| +--NEG-----------+ |
3|----------------------------------------------------------------------------------------------------------|Negate |-|
| |Source: y| |
| | | |
| |Dest: F2| |
| | | |
| +----------------+ |
|THIS RUNG CARRIES A ONE FROM THE SECOND WORD INTO THE HIGHER |
|FIRST WORD IF THE LOWER WORD WAS ZERO. |
|+--EQU-----------+ +--ADD-----------+ |
4||Equal (A=B) |----------------------------------------------------------------------------------------|Add |-|
||A: F2| |A: F1| |
|| | | | |
||B: 0.0| |B: 1.0| |
|+----------------+ |Dest: F1| |
| | | |
| +----------------+ |
|IF THE SECOND WORD BECAME NEGATIVE, THIS MAKES IT POSITIVE. |
|+--LES-----------+ +--ADD-----------+ |
5||Less Than (A<B) |----------------------------------------------------------------------------------------|Add |-|
||A: F2| |A: 65536.0| |
|| | | | |
||B: 0.0| |B: F2| |
|| | | | |
|+----------------+ |Dest: F2| |
| | | |
| +----------------+ |
|FINALLY, THIS EXPRESSION COMPUTES THE TOTAL FLOATING POINT VALUE. |
|Z IS A TERM TO CHANGE THE FINAL VALUE (SUCH AS CONVERT A kVAR |
|VALUE TO MVAR BY DIVIDING BY 1000, ETC.) |
|1ST HIGH WORD |
|OF LONG INTEGER |
|+--LES-----------+ +--CPT----------------------+ |
6||Less Than (A<B) |-----------------------------------------------------------------------------|Compute |-|
||A: x| |Dest: F3| |
|| | | | |
||B: 0| |Expression: | |
|| | | (((F1 * 65536.0) +| |
|+----------------+ | F2) * -1.0) | z| |
| +---------------------------+ |
|END OF FIRST HALF OF ROUTINE FOR NEGATIVE NUMBERS WITH JUMP TO END |
| J2 |
7|-----------------------------------------------------------------------------------------------------------------------[JMP]-|
|START OF SECOND HALF OF ROUTINE FOR POSITIVE NUMBERS |
| J1 +--MOV-----------+ |
8|-[LBL]----------------------------------------------------------------------------------------------------|Move |-|
| |Source: x| |
| | | |
| |Dest: F1| |
| | | |
| +----------------+ |
|IF SECOND LOW WORD IS NEGATIVE, THIS CONVERTS IT TO A POSITIVE |
|NUMBER AND COPIES IT INTO THE FLOATING POINT BUFFER |
|2ND LOW WORD OF |
|LONG INTEGER |
|+--LES-----------+ +--ADD-----------+ |
9||Less Than (A<B) |----------------------------------------------------------------------------------------|Add |-|
||A: y| |A: y| |
|| | | | |
||B: 0| |B: 65536.0| |
|+----------------+ |Dest: F2| |
| | | |
| +----------------+ |
|MOVES FIRST HIGH WORD INTO A FLOATING POINT BUFFER. |
|2ND LOW WORD OF |
|LONG INTEGER |
|+--GEQ--------------------+ +--MOV-----------+ |
10||Grtr Than or Equal (A>=B)|-------------------------------------------------------------------------------|Move |-|
||A: y| |Source: y| |
|| | | | |
||B: 0| |Dest: F2| |
|| | | | |
|+-------------------------+ +----------------+ |
|COMPUTATION FOR SECOND HALF OF ROUTINE FOR POSITIVE NUMBERS |
| +--CPT----------------------+ |
11|---------------------------------------------------------------------------------------------|Compute |---|
| ||Dest: F3| | |
| || | | |
| ||Expression: | | |
| || ((F1 * 65536.0) + F2)| | |
| || | z| | |
| |+---------------------------+ | |
| |Arithmetic Arithmetic | |
| |overflow overflow | |
| |occurred occurred | |
| | S:10 S:10 | |
| +----| |---------(U)-----------+ |
| 14 14 |
|ENDING JUMP FROM FIRST HALF OF ROUTINE |
| Arithmetic Arithmetic |
| overflow overflow |
| occurred occurred |
| J2 S:10 S:10 |
12|-[LBL]-----| |-------------------------------------------------------------------------------------------------------(U)-----|
| 14 14 |
| RETURN |
| AFTER |
| CONVERTING |
| SIGNED LONG INT |
| TO FLOATING |
| +--RET-------------+ |
13|--------------------------------------------------------------------------------------------------------|Return |-|
| |Return Par: F3| |
| +------------------+ |
14|-----------------------------------------------------------------------------------------------------------------------[END]-|
Back to Main