0

I'm trying to pass a struct to a function (by reference) and set several values of the struct in that function.

Here's the struct:

struct Sensor
{
    BYTE accel_data[6];
    BYTE gyro_data[6];
    int ax;
    int ay;
    int az;
    int gx;
    int gy;
    int gz;
}; 

here's the declaration in main():

struct Sensor s;

here's the pass to the function:

readAccel(&s);

readAccel function:

void readAccel(struct Sensor* s)
{
int ax, ay, az;
// Read data from Accelerometer Chip

i2c_multiRead(ACCEL_READ_ADDR, ACCEL_DATA_ADDR, s->accel_data, 6);

ax = make16(s->accel_data[1],s->accel_data[0]);
ay = make16(s->accel_data[3],s->accel_data[2]);
az = make16(s->accel_data[5],s->accel_data[4]);

fprintf(COM_A,"x: %d\ty: %d\tz: %d\r\n", ax, ay, az);

s->ax = ax;
s->ay = ay;
s->az = az;

fprintf(COM_A,"x: %d\ty: %d\tz: %d\r\n", s->ax, s->ay, s->az);
}

for some reason, the three assignment lines at the bottom of readAccel() are not working. The first print statement gives the correct accelerometer values. The second print statement gives the right value for x, but y is a junk value and z is always 0.

This is slightly nonstandard c (ccs c compiler) running on a pic microchip. The compiler has a few quirks (ints are 16 bit, all variables must be declared at the beginning of a function, etc), but I don't think it should be the reason why this isn't working (though I supposed it's possible).

Thanks for taking your time to help!

EDIT:

here's the i2c_multiread function:

void i2c_multiRead(char deviceAddrR, char registerAddr, BYTE data[], int numBytes)
{
    int x;
    i2c_start();
    i2c_write(deviceAddrR-0b00000001);
    i2c_write(registerAddr);
    i2c_start();
    i2c_write(deviceAddrR);
    for(x=0; x<numBytes-1; x++)
    {
        data[x]=i2c_read();
    }
    data[numBytes-1] = i2c_read(0); //NACK on last read
    i2c_stop();
}

void main ()
{
    struct Sensor s;
    int raw_accel_data[6];
    int i, data;
    char data_ready;
    fprintf(COM_A,"keyspan working \n\r");
    initAccel(&s);
    //initGyro(&s);
    fprintf(COM_A,"ALL SYSTEMS GO (accel initialized successfully)\n\r");

while(true) {

     //data_ready = i2c_singleRead(ACCEL_READ_ADDR,ACCEL_INT_MAP);
     //data_ready = data_ready >> 7;
    readAccel(&s);
    //readGyro(&s);
    //displayGyroData(&s);
    //displayGyroRawData(&s);

    delay_ms(100);
}
// Address of ITG (Gyro Chip)
//  Read:  0xD1
//  Write: 0xD0
}
Jacob Sharf
  • 250
  • 2
  • 12
  • Sounds strange. Does turning down optimization settings help? – aschepler Jul 20 '12 at 22:24
  • 4
    Your code looks fine to me. Its either your compiler/platform, or something else outside the scope of what you posted. – abelenky Jul 20 '12 at 22:25
  • @aschepler I'm not sure how to turn down optimization settings..... sorry. you mean things like fast_io? – Jacob Sharf Jul 20 '12 at 22:27
  • what's even weirder is that this same bit of code works in other programs... I'm probably going to work around this by returning an array with those three values. as inefficient as that is, I don't care. I hate nonstandard c. – Jacob Sharf Jul 20 '12 at 22:29
  • 1
    That's very strange, just out of curiosity, what if you try with `(*s).ax = ...`? – Vincenzo Pii Jul 20 '12 at 22:32
  • Looks fine to me too. Maybe try commenting out the i2c_multiRead and make16 lines and do int ax=1, ay=2, az=3; just to eliminate potential sources of the problem. – AW101 Jul 20 '12 at 22:41
  • @VincenzoPii when I do that, the pic behaves a bit strangely. it seems like it just break(;)s out of the function and stops executing. I'm confused – Jacob Sharf Jul 20 '12 at 22:42
  • @AW101 good idea. trying that... (it's a function I wrote for i2c com. I'll include it in the question too) – Jacob Sharf Jul 20 '12 at 22:42
  • @AW101 just tried it. the assignment is literally failing. – Jacob Sharf Jul 20 '12 at 22:45
  • 1
    I'd guess that s isn't pointing at your struct then. Try assigning values to ax, ay & az in main and add another fprintf at the start of readAccel (like the last one). – AW101 Jul 20 '12 at 22:51
  • @JacobSharf if the assignment appears to be failing, it sounds like there's definitely something wrong outside of your code (assignment is about as basic as it gets). Have you examined the assembly that the compiler emits for this function? Are you able to step through the function in a debugger? – bta Jul 20 '12 at 22:55
  • I also cannot find a mistake in the code. Can you post the full `main()`, too? – Mehrwolf Jul 20 '12 at 23:18
  • It may be due to some very weak memory model. You can try to insert several instructions between assigment and Output – Oleksandr Pryimak Jul 21 '12 at 00:26
  • @AW101 that's a good idea. unfortunately now I'm at home and can't flash the code because I don't have the pic with me. will try on monday. – Jacob Sharf Jul 21 '12 at 01:50
  • @bta I don't know assembly yet. (though I am taking a course on it this fall). I'll look at it with someone else in the lab who knows asm – Jacob Sharf Jul 21 '12 at 01:51
  • @Mehrwolf sure give me a second. – Jacob Sharf Jul 21 '12 at 01:51
  • @AlexandrPriymak that sounds interesting. however originally there were a few instructions in between and it didn't make a difference. – Jacob Sharf Jul 21 '12 at 01:54
  • @Mehrwolf I posted main() to the bottom of the post. – Jacob Sharf Jul 21 '12 at 01:57
  • What if you change the order of fields in the `struct Sensor`? Like put `ax`, `ay` and `az` as the first fields in the struct just to see what's gonna happen. – AnT stands with Russia Jul 21 '12 at 02:09
  • @AndreyT interesting. I tried changing the order around a few times but didn't think of putting ax, ay, and az first. I'll try this on monday. – Jacob Sharf Jul 21 '12 at 03:03
  • You might like to use one seperate `fprintf()` for s->ax, s->ay and s->az to verify its the members' content assigment or the `fprintf` method doing wrong. – alk Jul 21 '12 at 10:23
  • First, make sure all s->ax are actually ints (you can accidently include wrong header with wrong definition of Sensor struct), disable all optimizations, enable all compiler warnings. Also try to dump the whole Sensors structure as a byte array. And make sure it is ok – Oleksandr Pryimak Jul 21 '12 at 12:18
  • There appear to be two versions of i2c_read, one wibt no arguments `i2c_read();` and one with an (int) argument: `i2c_read(0);`. That is not possible in C (should not compile); **if** it compiles, the *empty* version will be called with a *random* argument. – wildplasser Jul 21 '12 at 16:24
  • What if value of sensor output has changed beetween that assigment ? Maybe You should consider trying to use `volatile int` in Your code, to prevent optimalization ? – JosiP Jul 23 '12 at 13:40
  • @alk I'm not sure entirely what you're saying. – Jacob Sharf Jul 23 '12 at 18:32
  • @AlexandrPriymak the sensor struct definition is in the same file. so it's not that. how do you disable optimizations? I'll look that up. I'm going to try removing the byte arrays from the sensor struct so that it only has ints in it first (the byte arrays might be messing up the spacing with padding or something). – Jacob Sharf Jul 23 '12 at 18:33
  • @JosiP I don't think so. the i2c function gives the latest value of the sensor and the sensor uses something called a FIFO buffer. so I doubt it matters. – Jacob Sharf Jul 23 '12 at 18:38
  • Can you show the output your program generates. Maybe the form of these numbers hint something – Oleksandr Pryimak Jul 23 '12 at 23:21
  • @AlexandrPriymak sure, when I get back to work tomorrow (though I have a midterm so I may not have time. intro cs course. should be a joke :D). I think it might have something to do with the output function – Jacob Sharf Jul 24 '12 at 07:14
  • @jacob sharf: I wanted to propose a test, to determine wether the malfunction dues to the way `fprintf()` handles the 3 `int`s passed or to how they are assigned their values. The proposal is to use 3 seperate calls to `fprintf()` to write out the 3 values in question. – alk Jul 25 '12 at 12:29
  • @alk interesting and sounds possible. I'll try it today – Jacob Sharf Jul 25 '12 at 15:18

1 Answers1

1

Could it be that this is just a "feature" of your fprintf implementation?

fprintf(COM_A,"x: %d\ty: %d\tz: %d\r\n", s->ax, s->ay, s->az);

The format string says that you will be providing 3 ints but you're providing 3 BYTEs instead. It's possible that the fprintf implementation generates wrong address for the 2nd and 3rd argument.

  • no, I don't think so because they're ints, not bytes. the sensor struct has ints ax, ay, and az in it. – Jacob Sharf Jul 23 '12 at 18:29
  • actually I have no clue why, but I think you're right. the print statement appears to be the issue as I restructured the program to use an array instead of a struct and the same problem happened. could you please elaborate why this is the issue and possibly how you'd fix it? – Jacob Sharf Jul 23 '12 at 20:12
  • You are right, the values are ints, not BYTEs as I said. I must not have looked well - my apologies. I did a google search for "css printf bug" and it brings up a number of results. My best bet is that your version of the compiler has a bug. – Terry Santegoeds Jul 25 '12 at 20:38