View previous topic :: View next topic |
Author |
Message |
David Pouzar
Joined: 20 Sep 2005 Posts: 27
|
Getting the Data Type for a RAM Location |
Posted: Wed Nov 15, 2017 8:34 am |
|
|
Has anyone figured out a way to tell what the data type of a RAM location is ? I am working on a Modbus to RAM converter that can get the sizeof and just wondering if there is a why tell if it is an Int32 or a float for example. Part 2: is there a way to tell if it is signed or unsigned ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Wed Nov 15, 2017 8:45 am |
|
|
A RAM location doesn't have a 'type'. Variables have types. All the type defines is 'how' the ram is to be looked at. You can even take a variable that is (for instance) a unsigned int16, put 65535 in it, and then print it with %Ld, and have it be displayed as -1.....
This is also why if you pass a pointer to a routine, and want the routine to deal with this as holding data of a particular size, you have to use sizeof, and pass the size to the routine as another variable.
Then something like a union, allows multiple variables of different types, to be sharing the same memory location. Even worse, if a variable is 'local' (not global), the same RAM will often be re-used by other variables that are completely different sizes.
If you want your code to know what s stored, you are going to have to work out a way of telling your routine what it is dealing with.... |
|
|
David Pouzar
Joined: 20 Sep 2005 Posts: 27
|
Modbus to RAM |
Posted: Wed Nov 15, 2017 8:57 am |
|
|
What I am doing is taking a modbus address and mapping to a Global Ram location. I wrote a function that knows when the user is requesting modbus address 7100 it is a float at pointer 178. Here is an example below. I was hoping I could get if it a float, int32, signed int32 instead of manually identifying it by it modbus address. Ideas? thank you for your quick reply..
Code: | float read_modbus2ram(int16 modbusAddress) //takes the modbus address return a float
{
//pointers]
float *ptr_f;
unsigned int32 *ptr_uint32;
signed int32 *ptr_sint32;
unsigned int16 *ptr_uint16;
signed int16 *ptr_sint16;
float temp_float;
signed int32 temp_sint32;
unsigned int32 temp_uint32;
signed int16 temp_sint16;
unsigned int16 temp_uint16;
// int8 temp_byte[4];
dataM.field_length=sizeof(sysTotalRunTime); //DCP Testing
//
int16 temp_address;
temp_float=0;
modbus2ram(modbusAddress); //convert Modbus Address to RAM Address
switch(dataM.data_type) //what is the datatype this is manually assigned in the modbus2ram function
{
case flag:
{
temp_float=(float)(bit_test(*dataM.ram_address,dataM.bit_loc));
break;
}
case sint16: //1- signed integer 16bit
{
temp_address=dataM.ram_address; //get the ram address
ptr_sint16 = temp_address; //assign it to the pointer
temp_sint16 =*ptr_sint16; //get the value of the pointer
temp_float=(float)temp_sint16; //convert to float
break;
}
case uint16: //2 - unsigned integer 16bit
{
temp_address=dataM.ram_address; //get the ram address
ptr_uint16 = temp_address; //assign it to the pointer
temp_uint16 = *ptr_uint16; //get the value of the pointer
temp_float=(float)temp_uint16; //convert to float
break;
}
case sint32: //3 - signed integer 32bit
{
// temp_address=dataM.ram_address
temp_address=dataM.ram_address; //get the ram address
ptr_sint32 = temp_address; //assign it to the pointer
temp_sint32 = *ptr_sint32; //get the value of the pointer
temp_float=(float)temp_sint32; //convert to float
break;
}
case uint32: //4 - unsigned integer 32bit
{
temp_address=dataM.ram_address; //get the ram address
ptr_uint32 = temp_address; //assign it to the pointer
temp_uint32 = *ptr_uint32; //get the value of the pointer
temp_float=(float)temp_uint32; //convert to float
break;
}
case sFloat: //5 - float 32bit
{
temp_address=dataM.ram_address; //get the ram address
ptr_f = temp_address; //assign it to the pointer
temp_float = *ptr_f; //get the value of the pointer
//temp_float=(float)temp_int32; //convert to float
break;
}
return(temp_float);
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Wed Nov 15, 2017 9:31 am |
|
|
It won't care.....
Just transfer 4 bytes. All of the types are the same size, so just send that amount of data from the location. It doesn't matter at all 'what' is actually stored there. |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Wed Nov 15, 2017 10:27 am |
|
|
Even four bytes won't work as all Modbus registers are sixteen bit, i.e. two bytes. Coils are single bits.
As Modbus predates modern datatyping, there is no inherent data type associated with Modbus registers, they can mean whatever you want them to mean. Personally I try to keep clear of floats, using scaled 16 bit integers instead, e.g. voltage in integer millivolts rather than float volts. If you want to transfer 32 bit quantities, set up your registers in pairs, one with the high 16 bits and one with the lower. There is no inherent endianness implied by Modbus: registers are independant and have no assumed relationship to each other. So you can use whatever endianness you like, but its clearly sensible to adopt a standard and stick to it.
It is also possible, and practical to transfer groups of registers, and to implement memory-style interfaces through registers, just as the PIC hardware does for program memory and built-in EEPROM. |
|
|
|