help using extern int16

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
DaRe_2236336
Level 3
Level 3
First like given

I'm trying to get some values from this accelerometer, the I2C is working fine but im trying to pass the values to main so that i can see them in debug mode so i can get offset values. I'm trying to pass them from the function that gets the values in the i2c.c file to my main.c file using "extern int16 rawDATA[3];" but i am getting warnings that i am getting an error saying "undefined reference to 'rawDATA[3]'" and warnings saying that the variables i created to show the data are created but not used. I also tried just passing the data as individual pieces before i put it in an array in the function which gave me the same result.

pastedImage_0.png

tried "void accelgetAllData(void)"

and having no return while using "extern int16 rawX,rawY, rawZ;"

pastedImage_1.png

any help would be appreciated, sorry if this is in the wrong section.

0 Likes
1 Solution
KyTr_1955226
Level 6
Level 6
250 sign-ins 10 likes given 50 solutions authored

Shouldn't rawDATA[3] be defined outside of main?  I don't actually know if/how extern works when defined inside a function.  Someone with some more knowledge of the ins and outs of C could chime in on that.

A problem I see though is that int16 accelgetAllData(void) wants to return an int16 and you are returning an int16* since rawDATA is an array.  So either return a pointer to rawDATA[] or you could pass in the address of rawDATA and directly modify it in the function.

so

int16 * accelgetAllData(void) would match what you have written for the return,

but

void accelgetAllData(int16 *raw_data_array) might be what you actually want in this case.

With that 2nd one, you are passing in the address of the first element of an array into the function, so you could do:

raw_data_array[0] = rawX;

raw_data_array[1] = rawY;

raw_data_array[2] = rawZ;

And that would change the values in rawDATA when called as accelgetAllData(rawDATA);

I don't even think you'll need an extern.

extern is a promise to the linker that the symbol exists somewhere elsewhere in another .c file so you can call it.

I.E. you would define an extern variable in main.c:

uint16_t ExternalVar = 100;

but if you want to call it from adc.c you would have to declare it in adc.c or adc.h:

extern uint16_t ExternalVar;

View solution in original post

0 Likes
7 Replies
EmHo_296241
Level 5
Level 5
10 solutions authored 50 replies posted 25 replies posted

Could you try adding the keyword volatile too ? They may be getting optimized

0 Likes

tried "volatile extern int16..." same issue

0 Likes
KyTr_1955226
Level 6
Level 6
250 sign-ins 10 likes given 50 solutions authored

Shouldn't rawDATA[3] be defined outside of main?  I don't actually know if/how extern works when defined inside a function.  Someone with some more knowledge of the ins and outs of C could chime in on that.

A problem I see though is that int16 accelgetAllData(void) wants to return an int16 and you are returning an int16* since rawDATA is an array.  So either return a pointer to rawDATA[] or you could pass in the address of rawDATA and directly modify it in the function.

so

int16 * accelgetAllData(void) would match what you have written for the return,

but

void accelgetAllData(int16 *raw_data_array) might be what you actually want in this case.

With that 2nd one, you are passing in the address of the first element of an array into the function, so you could do:

raw_data_array[0] = rawX;

raw_data_array[1] = rawY;

raw_data_array[2] = rawZ;

And that would change the values in rawDATA when called as accelgetAllData(rawDATA);

I don't even think you'll need an extern.

extern is a promise to the linker that the symbol exists somewhere elsewhere in another .c file so you can call it.

I.E. you would define an extern variable in main.c:

uint16_t ExternalVar = 100;

but if you want to call it from adc.c you would have to declare it in adc.c or adc.h:

extern uint16_t ExternalVar;

0 Likes

Tried changing to int16* still no dice, with and without volatile, and in and out of the for(;;). I had it out of the for(;;) when i started but moved it in because i thought that might have had something to do with it. rawDATA[3] is declared in the function accelgetAllData() then as an extern in main. I'm stumped. I've done this before with other sensors and it worked fine. I cant find any differences in the way I'm doing it this time that would be causing issues. I'll post the complete project.

0 Likes
lock attach
Attachments are accessible only for community members.

project

0 Likes

OK so I had a look.  Here's what I found:

1) You had rawDATA declared twice.  Once in main() in main.c, once in accelgetAllData() in i2c.c.  This won't break anything, but will create a variable with the same name in two different scopes (two different functions)  remove the declaration from accelgetAllData(), we only want one rawDATA array.

2) rawDATA[3] was declared inside of main().  This scopes it local so you can only use it inside main().  This is fine in your specific case, but if you want to use it anywhere in main.c, declare it before main().

3) You had rawDATA[3] defined as int16* rawDATA[3].  You don't need to declare it as a pointer since an array is already a pointer.  You essentially made a int16** rawDATA;.  declare it int16 rawDATA[3];

4) I changed accelgetAllData to take an int16* as it's argument.

void accelgetAllData(int16* raw_data)

when done like this you can just call it as accelgetAllData(rawDATA); and then replacing the references inside the function with:

raw_data[0] = rawX;

raw_data[1] = rawY;

raw_data[2] = rawZ;

This will write these values to your rawDATA array (since that's the pointer you passed in).  All without the need for an extern.

If you want to use extern though, declare rawDATA OUTSIDE of main, just after your header includes in main.c.  Your declaration here will NOT be extern.

int16 rawDATA[3] = {0,0,0};

In i2c.c, just after your header includes (or inside i2c.h), declare rawDATA as extern.:

extern int16 rawDATA[3];

the extern keyword here tells the linker that the declaration/definition is in another c file.  In our case, main.c.  It will then find the symbol and link up the proper address.

then you can assign to rawDATA as you were originally inside accelgetAllData:

rawDATA[0] = rawX;

rawDATA[1] = rawY;

rawDATA[2] = rawZ;

EDIT:

lol you got it just before I posted this.  I'm gonna leave it for posterity in case someone comes by looking for help on externs.

oh man that worked! ha thanks KTrenholm_1955226​! I did it worng the first time i tried

0 Likes