Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

ADC Channel

Status
Not open for further replies.
Thank you for your input and I can appreciate that some don't care for MCC but you and the people that wrote it know more about this then I do (self taught hobbyist), having said that it produces code that has been a teaching tool for me. With the code from MCC this is what I have
C:
void GetTemp(void)
{
    uint8_t chan = 3;
    uint8_t ii = 0;
    uint8_t i;
    float TempRead;
   
   
    for (i = 0; i<chan; i++)
    {
        data = &TempRead;
        TempRead = *((float*)data);
       
        i2c_readDataBlock(address, reg, *data, len);
   
       
       
        if (ii == 0) SysTemp.ArrayTemp = TempRead;
        else if (ii = 1) SysTemp.WaterTemp = TempRead;
        else SysTemp.PoolTemp = TempRead;
       
        ii++;
    }
   
}
I get the following error:
temp.c:46: error: (182) illegal conversion between types
void -> pointer to void

for: i2c_readDataBlock(address,reg,*data,len)
 
Thank you for your input and I can appreciate that some don't care for MCC but you and the people that wrote it know more about this then I do (self taught hobbyist), having said that it produces code that has been a teaching tool for me. With the code from MCC this is what I have
C:
void GetTemp(void)
{
    uint8_t chan = 3;
    uint8_t ii = 0;
    uint8_t i;
    float TempRead;
 
 
    for (i = 0; i<chan; i++)
    {
        data = &TempRead;
        TempRead = *((float*)data);
 
        i2c_readDataBlock(address, reg, *data, len);
 
 
 
        if (ii == 0) SysTemp.ArrayTemp = TempRead;
        else if (ii = 1) SysTemp.WaterTemp = TempRead;
        else SysTemp.PoolTemp = TempRead;
 
        ii++;
    }
 
}
I get the following error:
temp.c:46: error: (182) illegal conversion between types
void -> pointer to void

for: i2c_readDataBlock(address,reg,*data,len)

The argument to i2C_ReadDataBlock() expects an argument of type:
void *data

This means that you need to put a pointer as the argument or the ADDRESS of something else as the argument (i.e. a pointer in the form void *ptr_var, or a literal memory address such as &variable.)

But you tried to put in *data in as an argument, you are putting in the value of the variable located at the memory address specified by data. But it is expecting an address. Not a value.

Data is the pointer. It returns the address of a memory location.

*Data is the pointer being dereferenced. This means it returns the value stored at the memory location specified by Data.

So if Data = 0x0F, then Data is pointing to 0x0F. If I then go Data = 0x0A, then it points to a different memory location. But if I now go *Data = 23, then the value 23 is written to the memory location 0X0A.

If I read Data, I will now get 0x0A. If I read *Data, then I will get 23. 23 is being stored at memory location 0x0A, and the address 0x0A is being stored in memory at the address where the pointer itself is located (&Data).
 
Last edited:
The argument to i2C_ReadDataBlock() expects an argument of type:
void *data

This means that you need to put a pointer as the argument or the ADDRESS of something else as the argument (i.e. a pointer in the form void *ptr_var, or a literal memory address such as &variable.)

When you try and put *data in as an argument, you are putting in the value of the variable located at the memory address specified by data. But it is expecting an address. Not a value.

I thought that was what I was doing with
C:
data = &TempRead;
TempRead = *((float*)data)
 
I thought that was what I was doing with
C:
data = &TempRead;
TempRead = *((float*)data)

This part is convoluted and circular simplifies down to this:

1. TempRead = *((float*)data);
2. TempRead = *( (float*)(&TempRead) );
3. TempRead = *(&TempRead);
4. TempRead = TempRead;

which you can see is a pointless, circular assignment. But it's also convoluted because you go about it in a roundabout way using the data pointer as an intermediary. So obviously there is a problem here, but that wasn't what I was actually talking about.
 
Last edited:
What I was talking about is that you go:

i2c_readDataBlock(address, reg, *data, len);

But the function is declared as,
void i2c_readDataBlock(i2c_address_t address, uint8_t reg, void *data, size_t len)
{...}

The function is expecting a pointer because it's declared as *data, but then you give it a dereferenced pointer instead when you use *data as an argument. THe * symbol has different meanings depending on context. WHen declaring a variable, it means the variable is a pointer. But in use, when being written or read, the * is the derferencing symbol when stuck in front of the a variable name of a pointer when it's being assigned to or read from.
 
Last edited:
The * is something that is always present when declaring a pointer since it specifies that the variable being declared is a pointer of type X, and not just a variable of type X.

However, when using the variable the * is not something that is always there. It is there as required depending on whether you want to write/read the address value being stored BY the pointer or the value at the location being pointed to.

Also be aware that there is a difference between the declarations:
Code:
const int* Integer_Pointer; //makes the value at the location being pointed to not writable via the pointer, but you can change the pointer to point to another memory location

int* const IntegerPointer = 0x0AF; //makes it so the address being pointed to can never change. The pointer can only ever point to one place, but you can modify the value at this place through the pointer

const int* const Integer_Pointer = 0x0AF; //the address being pointed to cannot be modified, nor can the value at the location being pointed to via the pointer

Pointers have an extra degree of freedom in their reads/writes compared to other variables so don't mix them up.
 
Last edited:
This part is convoluted and circular simplifies down to this:

1. TempRead = *((float*)data);
2. TempRead = *( (float*)(&TempRead) );
3. TempRead = *(&TempRead);
4. TempRead = TempRead;

which you can see is a pointless, circular assignment. But it's also convoluted because you go about it in a roundabout way using the data pointer as an intermediary. So obviously there is a problem here, but that wasn't what I was actually talking about.
dknguyen thanks for your help. With your info I came up with the following
C:
#define TEMP 0x10; //slave address
#define Array 0x60; //memory address
#define Water 0x63; //memory address
#define Pool 0x66; //memory address

uint8_t TempReg [] = {Array, Water, Pool};

i2c_readDataBlock(TEMP, TempReg, &TempReg, 3)
now if I understand correctly I can take &TempReg and typecast to TempRead as a float
 
dknguyen
i2c_readDataBlock(TEMP, TempReg, &TempReg, 3)
[/code]

That function makes a lot more sense in the context of how I expect it to work now.

If I understand i2c_readDataBlock(), that line of code would take the 3 bytes located at &TempReg and send them over the I2C bus to be written to TempReg register in the the device with an I2C address of TEMP.

now if I understand correctly I can take &TempReg and typecast to TempRead as a float
As for typecasting to a float, I think I flubbed when I said typecast. You need to convert since a single precision float is 32-bits long and a double precision float is 64-bits long. You only transmitted 24 bytes.

Casting is where you take a value and just interpret it differently (8 bits can be interpreted as either an integer or a char, but it's still the same 8-bits). But a conversion actually takes those bits and runs it through something to change it to a new form.

You can probably just rely on float having an operator overloading conversion operator for iintegers so you might just be able to go:

float Number = some_integer;

and it will implicitly convert it for you. Or if you have a char that for some reason needs to be converted to a float, you might need to typecast that to an integer so the implicit float conversion knows what to do with it (it doesn't make sense to convert a char to a float, but it does make sense to convert an integer to a float):

float Number = integer(some_char);

If this doesn't exist then you'll have to find a conversion in a math library, possibly the math.h or float.h that is included with your compiler.
 
Last edited:
After doing some studying I have found that I need to send a float via i2c 1 byte at a time (for MPLab float = 3 bytes). need to load into buffer on the slave transfer to master then load into memory as a float, and I'm not sure on how to do that.
 
After doing some studying I have found that I need to send a float via i2c 1 byte at a time (for MPLab float = 3 bytes). need to load into buffer on the slave transfer to master then load into memory as a float, and I'm not sure on how to do that.

Assuming this is a value that you read from an analogue input?, store it to EEPROM before you convert it to a float (only two bytes, or ten bits) - problem solved.
 
After doing some studying I have found that I need to send a float via i2c 1 byte at a time (for MPLab float = 3 bytes). need to load into buffer on the slave transfer to master then load into memory as a float, and I'm not sure on how to do that.
I showed you how..

union{
float myfloatVal;
char mySerialval[4];​
} floatCtl;

If you use a union you can store and redeem values as bytes... Just to make it easier for yourself... Use 32bit and not 24bit floats.... ( you select this in compiler settings...)
 
I showed you how..

union{
float myfloatVal;
char mySerialval[4];​
} floatCtl;

If you use a union you can store and redeem values as bytes... Just to make it easier for yourself... Use 32bit and not 24bit floats.... ( you select this in compiler settings...)

your right you did, I just didn't make the connection as I am communicating MCU-MCU.
 
Assuming this is a value that you read from an analogue input?, store it to EEPROM before you convert it to a float (only two bytes, or ten bits) - problem solved.
Seeing's how it s from an ADC, I didn't think about just sending the raw ADC result but that is a good idea.
 
is the R_nW & D_nA bits in SPPxSTAT SFR set by hardware or software?
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top