Димон Безпарольный 2 5 декабря, 2016 Опубликовано 5 декабря, 2016 · Жалоба Компилятор С-Free ошибок не выдает, но виснет при выполнении. Тот же софт в ARM не виснет, но данные через структуру не передает - там мусор. Вот эти структуры: struct bme280_calibration_param_t { u16 dig_T1;/**<calibration T1 data*/ s16 dig_T2;/**<calibration T2 data*/ s16 dig_T3;/**<calibration T3 data*/ u16 dig_P1;/**<calibration P1 data*/ s16 dig_P2;/**<calibration P2 data*/ s16 dig_P3;/**<calibration P3 data*/ s16 dig_P4;/**<calibration P4 data*/ s16 dig_P5;/**<calibration P5 data*/ s16 dig_P6;/**<calibration P6 data*/ s16 dig_P7;/**<calibration P7 data*/ s16 dig_P8;/**<calibration P8 data*/ s16 dig_P9;/**<calibration P9 data*/ u8 dig_H1;/**<calibration H1 data*/ s16 dig_H2;/**<calibration H2 data*/ u8 dig_H3;/**<calibration H3 data*/ s16 dig_H4;/**<calibration H4 data*/ s16 dig_H5;/**<calibration H5 data*/ s8 dig_H6;/**<calibration H6 data*/ s32 t_fine;/**<calibration T_FINE data*/ }; struct bme280_t { struct bme280_calibration_param_t cal_param; /**< calibration parameters*/ u8 chip_id;/**< chip id of the sensor*/ u8 dev_addr;/**< device address of the sensor*/ u8 oversamp_temperature;/**< temperature over sampling*/ u8 oversamp_pressure;/**< pressure over sampling*/ u8 oversamp_humidity;/**< humidity over sampling*/ u8 ctrl_hum_reg;/**< status of control humidity register*/ u8 ctrl_meas_reg;/**< status of control measurement register*/ u8 config_reg;/**< status of configuration register*/ }; Далее определяю ссылку: static struct bme280_t *p_bme280; /**< pointer to BME280 */ В Main обращаюсь к структуре, заполняя ее поля: p_bme280->cal_param.dig_T1 = (u16)1; p_bme280->cal_param.dig_T2 = (s16)2; p_bme280->cal_param.dig_T3 = (s16)3; p_bme280->cal_param.dig_P1 = (u16)4; p_bme280->cal_param.dig_P2 = (s16)5; p_bme280->cal_param.dig_P3 = (s16)6; p_bme280->cal_param.dig_P4 = (s16)7; p_bme280->cal_param.dig_P5 = (s16)8; p_bme280->cal_param.dig_P6 = (s16)9; p_bme280->cal_param.dig_P7 = (s16)10; p_bme280->cal_param.dig_P8 = (s16)11; p_bme280->cal_param.dig_P9 = (s16)12; p_bme280->cal_param.dig_H1 = (s16)13; p_bme280->cal_param.dig_H2 = (s16)14; p_bme280->cal_param.dig_H3 = (s16)15; В том же Main пытаюсь вывести значения: printf("\nT1:%x ",p_bme280->cal_param.dig_T1); //0x89 = 0x6C, 0x88 = 0x9E printf("T2:%x ", p_bme280->cal_param.dig_T2); //0x8B = 0x64, 0x8A = 0xFD printf("T3:%x ", p_bme280->cal_param.dig_T3); //0x8D = 0x00, 0x8C = 0x32 printf("P1:%x ", p_bme280->cal_param.dig_P1); //0x8F = 0x93, 0x8E = 0x43 printf("P2:%x ", p_bme280->cal_param.dig_P2); //0x91 = 0xD4, 0x90 = 0xED printf("P3:%x ", p_bme280->cal_param.dig_P3); //0x93 = 0x0B, 0x92 = 0xD0 printf("P4:%x ", p_bme280->cal_param.dig_P4); //0x95 = 0x1D, 0x94 = 0x10 printf("P5:%x ", p_bme280->cal_param.dig_P5); //0x97 = 0xFF, 0x96 = 0xFC printf("P6:%x ", p_bme280->cal_param.dig_P6); //0x99 = 0xFF, 0x98 = 0xF9 printf("P7:%x ", p_bme280->cal_param.dig_P7); //0x9B = 0x26, 0x9A = 0xAC printf("P8:%x ", p_bme280->cal_param.dig_P8); //0x9D = 0xD8, 0x9C = 0x0A printf("P9:%x ", p_bme280->cal_param.dig_P9); //0x9F = 0x10, 0x9E = 0xBD printf("H1:%x ", p_bme280->cal_param.dig_H1); //0xA1 = 0x4B printf("H2:%x ", p_bme280->cal_param.dig_H2); //0xE2 = 0x01, 0xE1 = 0x69 printf("H3:%x ", p_bme280->cal_param.dig_H3); //0xE3 = 0x00 printf("H4:%x ", p_bme280->cal_param.dig_H4); //0xE4 = 0x14, 0xE5[3..0] = 0x00 printf("H5:%x ", p_bme280->cal_param.dig_H5); //0xE6 = 0x00, 0xE5[7..4] = 0x00 printf("H6:%x\r", p_bme280->cal_param.dig_H6); //0xE7 = 0x1E 33 ????? Что здесь не так? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
megajohn 3 5 декабря, 2016 Опубликовано 5 декабря, 2016 · Жалоба Что здесь не так? указатель должен на что-то реальное указывать static struct bme280_t bme280_cfg_a; static struct bme280_t bme280_cfg_b; static struct bme280_t *p_bme280; /**< pointer to BME280 */ void main void() { p_bme280 = &bme280_cfg_a; p_bme280->cal_param.dig_H3 = 15; ... } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 5 декабря, 2016 Опубликовано 5 декабря, 2016 · Жалоба И правда. Спасибо. Заработало. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 26 6 декабря, 2016 Опубликовано 6 декабря, 2016 · Жалоба . . . . Далее определяю ссылку: static struct bme280_t *p_bme280; /**< pointer to BME280 */ . . . . Это указатель объявлен. ссылка в С есть нечто другое со знаком &. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 130 6 декабря, 2016 Опубликовано 6 декабря, 2016 · Жалоба ссылка в С есть нечто другое со знаком &.Ссылок в C нет совсем, они есть в C++. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 26 6 декабря, 2016 Опубликовано 6 декабря, 2016 · Жалоба Ссылок в C нет совсем, они есть в C++. Нэ знал. Пробелы в консерватории :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 6 декабря, 2016 Опубликовано 6 декабря, 2016 · Жалоба Пытаюсь доконца разобраться. Для того, чтобы элементы структуры были доступны в каждой функции, мне приходится в каждую функцию прописывать: p_BME280 = &BME280_cfg; Это работает. Но в исходнике, который я адаптирую: https://github.com/BoschSensortec/BME280_dr...master/bme280.c поступают иначе. Я не могу понять как это работает. В строке 55 объявляется указатель на структуру: static struct bme280_t *p_bme280; /**< pointer to BME280 */ в единственном месте - функция bme280_init(struct bme280_t *bme280)(строка 90) этому указателю присваивается адрес : /* assign BME280 ptr */ p_bme280 = bme280; И все. Далее в каждой функции идет обращение к структуре(строка 230): p_bme280->cal_param.t_fine - 122880 уже без присваивания адреса в каждой функции. Я понимаю, что указатель p_BME280 глобален. Но все мои попытки один раз назначить ему адрес структуры приводит к ошибке в компиляции. Как это сделать? Заранее спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 6 декабря, 2016 Опубликовано 6 декабря, 2016 · Жалоба Если эта структура bme280 одна, и размножать их не планируется, предлагаю забыть слово "указатель", раз оно вызывает сложности. Обращаться непосредственно к полям первоначальной структуры. А вообще, правильно заданный вопрос - это хороший тон. Правильно заданный - это минимальный пример, который показывает проблему. "Я сделал глобальную структуру A, указатель pA, присваиваю в функции init() pA = &A, потом пользуюсь в функции doItNow() pA->var, и у возникает вот такая ошибка компиляции". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 6 декабря, 2016 Опубликовано 6 декабря, 2016 · Жалоба /* assign BME280 ptr */ p_bme280 = bme280; уже без присваивания адреса в каждой функции. Я понимаю, что указатель p_BME280 глобален. Но все мои попытки один раз назначить ему адрес структуры приводит к ошибке в компиляции. Как это сделать? p_BME280 не глобален, у него область видимости только файл bme280.c bme280 передается в функцию bme280_init(&bme280) ну и дальше в файле bme280.c доступен только указатель p_bme280, а в файле bme280_support.c только структура bme280. И если использовать p_bme280 в другом отличном от файла bme280.c будет ошибка так как у указателя p_bme280 область видимости только этот файл. Хотите сделать его глобальным уберите static перед объявлением и объявляйте его extern в других файлах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 6 декабря, 2016 Опубликовано 6 декабря, 2016 (изменено) · Жалоба bme280 передается в функцию bme280_init(&bme280) ну и дальше в файле bme280.c доступен только указатель p_bme280, а в файле bme280_support.c Это меня устраивает. Но у меня (в одном файле) получается так: signed int BME280_Compensate_Temperature(signed int Uncomp_Temperature) { p_BME280 = &BME280_cfg; v_x1_u32r = ((((Uncomp_Temperature >> 3) - ((signed int)p_BME280->cal_param.dig_T1<< 1))) * ((signed int)p_BME280->cal_param.dig_T2)) >> 11; } Без строки p_BME280 = &BME280_cfg;, переменная p_BME280->cal_param.dig_T1 содержит мусор. Приходится писать в каждой функции строку p_BME280 = &BME280_cfg;. В этом и вопрос - в приведенном мной исходнике этого не делают, а с параметрами структуры работают. Изменено 6 декабря, 2016 пользователем Димон Безпарольный Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 6 декабря, 2016 Опубликовано 6 декабря, 2016 · Жалоба А как и где у вас объявляются p_BME280 и BME280_cfg ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 6 декабря, 2016 Опубликовано 6 декабря, 2016 · Жалоба А как и где у вас объявляются p_BME280 и BME280_cfg ? Обявляются в заголовочном файле: static struct BME280_t BME280_cfg; static struct BME280_t *p_BME280; /**< pointer to BME280 */ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 6 декабря, 2016 Опубликовано 6 декабря, 2016 · Жалоба А заголовочный файл у вас подключается к двум исходным файлам? и получается в каждом файле своя копия BME280_cfg и p_BME280. Так не делают, смотрите как сделано на github'e. Либо делайте через typedef и extern. P.S. что бы не разжевывать тут, почитайте http://digitalchip.ru/osobennosti-ispolzov...-i-static-v-c-c Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
conan 0 7 декабря, 2016 Опубликовано 7 декабря, 2016 (изменено) · Жалоба Обявляются в заголовочном файле: static struct BME280_t BME280_cfg; static struct BME280_t *p_BME280; /**< pointer to BME280 */ Это не объявление, а определение. И делать определения в заголовочном файле -- плохая практика. В C/C++ применяется так наз. раздельная компиляция. Если нужна глобальная переменная доступная во всех единицах трансляции (т. е. c-файлах) то, нужно делать так: 1. В одном заголовочном файле должно быть ОБЪЯВЛЕНИЕ: -------decl.h-------- ... extern struct BME280_t BME280_cfg; extern struct BME280_t *p_BME280; /**< pointer to BME280 */ 2. Только в одном C-файле должно быть ОПРЕДЕЛЕНИЕ: -------def.c-------- ... struct BME280_t BME280_cfg; struct BME280_t *p_BME280; /**< pointer to BME280 */ 3. Затем в др. C-файлах можно использовать эти глобальные переменные: -------a.c-------- #include "decl.h" void f() { BME280_cfg.member1 = 1234; p_BME280->member2 = 43444; } -------b.c-------- #include "decl.h" void g() { BME280_cfg.member1 = 5678; p_BME280->member2 = 44343; } Любой из этих C-файлов: def.c, a.c, b.c может содержать функцию main() (и сам файл может называться main.c) --------------------------------------------------------------------- Если переменная определена как static в каком-нибудь C-файле, то она будет доступна только в этом c-файле. Если в других C-файлах есть такое же static-определение, то это будет уже др. переменная -------decl.h-------- Как уже было сказано -- определения в заголовочном файле -- плохо, тем не менее ... static struct BME280_t BME280_cfg; static struct BME280_t *p_BME280; /**< pointer to BME280 */ -------a.c-------- #include "decl.h" void f() { BME280_cfg.member1 = 1234; p_BME280->member2 = 43444; } -------b.c-------- #include "decl.h" void g() { BME280_cfg.member1 = 5678; p_BME280->member2 = 44343; } После препроцессинга (в том числе обработки include-ов) перед компиляцией из a.c получится единица трансляции: -------a.c*-------- static struct BME280_t BME280_cfg; static struct BME280_t *p_BME280; /**< pointer to BME280 */ void f() { BME280_cfg.member1 = 1234; p_BME280->member2 = 43444; } Из b.c получится: -------b.c*-------- static struct BME280_t BME280_cfg; static struct BME280_t *p_BME280; /**< pointer to BME280 */ void g() { BME280_cfg.member1 = 5678; p_BME280->member2 = 44343; } Таким образом, в каждой единице трансляции будет свой комплект переменных BME280_cfg и p_BME280. При изменении переменной BME280_cfg в a.c, это никак не затронет переменную с этим же названием в b.c, ибо там своя отдельная переменная в b.c. ----------------------------------------------- Если сделать так -------decl.h-------- Как уже было сказано -- определения в заголовочном файле -- плохо, тем не менее ... struct BME280_t BME280_cfg; struct BME280_t *p_BME280; /**< pointer to BME280 */ -------a.c-------- #include "decl.h" void f() { BME280_cfg.member1 = 1234; p_BME280->member2 = 43444; } -------b.c-------- #include "decl.h" void g() { BME280_cfg.member1 = 5678; // * p_BME280->member2 = 44343; } то программа пройдет компиляцию, но не пройдет компоновку (linkage), ибо теперь одновременно в двух единицах трансляции получаются одинаковые переменные, но при этом которые должны быть доступны для компоновки с др. единицами трансляции. Т. е. возникает неопределенность, какую например из переменных BME280_cfg использовать при записи в member1 в b.c (*): ту которая определена в a.c или ту которая в b.c... Изменено 7 декабря, 2016 пользователем conan Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 8 декабря, 2016 Опубликовано 8 декабря, 2016 (изменено) · Жалоба Спасибо за развернутый ответ, но речь шла об одном файле. Пост 7 описывает проблему в одном файле. Исходный код (ссылка там же) не использует присваивания p_bme280 = bme280; в каждой функции одного файла. А у меня без этого присваивания (в каждой функции) не работает. Читается мусор. Тестовый вариант (в компиляторе C-Free, функция Main, строка p_bme280 = &bme280_cfg;) просто завершается аварийно без этого присвоения: typedef signed char s8;/**< used for signed 8bit */ typedef signed short int s16;/**< used for signed 16bit */ typedef signed int s32;/**< used for signed 32bit */ typedef signed long long int s64;/**< used for signed 64bit */ typedef unsigned char u8;/**< used for unsigned 8bit */ typedef unsigned short int u16;/**< used for unsigned 16bit */ typedef unsigned int u32;/**< used for unsigned 32bit */ typedef unsigned long long int u64;/**< used for unsigned 64bit */ struct bme280_calibration_param_t { u16 dig_T1;/**<calibration T1 data*/ s16 dig_T2;/**<calibration T2 data*/ s16 dig_T3;/**<calibration T3 data*/ u16 dig_P1;/**<calibration P1 data*/ s16 dig_P2;/**<calibration P2 data*/ s16 dig_P3;/**<calibration P3 data*/ s16 dig_P4;/**<calibration P4 data*/ s16 dig_P5;/**<calibration P5 data*/ s16 dig_P6;/**<calibration P6 data*/ s16 dig_P7;/**<calibration P7 data*/ s16 dig_P8;/**<calibration P8 data*/ s16 dig_P9;/**<calibration P9 data*/ u8 dig_H1;/**<calibration H1 data*/ s16 dig_H2;/**<calibration H2 data*/ u8 dig_H3;/**<calibration H3 data*/ s16 dig_H4;/**<calibration H4 data*/ s16 dig_H5;/**<calibration H5 data*/ s8 dig_H6;/**<calibration H6 data*/ s32 t_fine;/**<calibration T_FINE data*/ }; struct bme280_t { struct bme280_calibration_param_t cal_param; /**< calibration parameters*/ u8 chip_id;/**< chip id of the sensor*/ u8 dev_addr;/**< device address of the sensor*/ u8 oversamp_temperature;/**< temperature over sampling*/ u8 oversamp_pressure;/**< pressure over sampling*/ u8 oversamp_humidity;/**< humidity over sampling*/ u8 ctrl_hum_reg;/**< status of control humidity register*/ u8 ctrl_meas_reg;/**< status of control measurement register*/ u8 config_reg;/**< status of configuration register*/ }; static struct bme280_t bme280_cfg; static struct bme280_t *p_bme280; /**< pointer to BME280 */ int main() { p_bme280 = &bme280_cfg; p_bme280->cal_param.dig_T1 = 1; p_bme280->cal_param.dig_T2 = 2; p_bme280->cal_param.dig_T3 = 3; p_bme280->cal_param.dig_P1 = 4; p_bme280->cal_param.dig_P2 = 5; p_bme280->cal_param.dig_P3 = 6; p_bme280->cal_param.dig_P4 = 7; p_bme280->cal_param.dig_P5 = 8; p_bme280->cal_param.dig_P6 = 9; p_bme280->cal_param.dig_P7 = 10; p_bme280->cal_param.dig_P8 = 11; p_bme280->cal_param.dig_P9 = 12; p_bme280->cal_param.dig_H1 = 13; p_bme280->cal_param.dig_H2 = 14; p_bme280->cal_param.dig_H3 = 15; printf("\nT1:%x ",p_bme280->cal_param.dig_T1); //0x89 = 0x6C, 0x88 = 0x9E printf("T2:%x ", p_bme280->cal_param.dig_T2); //0x8B = 0x64, 0x8A = 0xFD printf("T3:%x ", p_bme280->cal_param.dig_T3); //0x8D = 0x00, 0x8C = 0x32 printf("P1:%x ", p_bme280->cal_param.dig_P1); //0x8F = 0x93, 0x8E = 0x43 printf("P2:%x ", p_bme280->cal_param.dig_P2); //0x91 = 0xD4, 0x90 = 0xED printf("P3:%x ", p_bme280->cal_param.dig_P3); //0x93 = 0x0B, 0x92 = 0xD0 printf("P4:%x ", p_bme280->cal_param.dig_P4); //0x95 = 0x1D, 0x94 = 0x10 printf("P5:%x ", p_bme280->cal_param.dig_P5); //0x97 = 0xFF, 0x96 = 0xFC printf("P6:%x ", p_bme280->cal_param.dig_P6); //0x99 = 0xFF, 0x98 = 0xF9 printf("P7:%x ", p_bme280->cal_param.dig_P7); //0x9B = 0x26, 0x9A = 0xAC printf("P8:%x ", p_bme280->cal_param.dig_P8); //0x9D = 0xD8, 0x9C = 0x0A printf("P9:%x ", p_bme280->cal_param.dig_P9); //0x9F = 0x10, 0x9E = 0xBD printf("H1:%x ", p_bme280->cal_param.dig_H1); //0xA1 = 0x4B printf("H2:%x ", p_bme280->cal_param.dig_H2); //0xE2 = 0x01, 0xE1 = 0x69 printf("H3:%x \n", p_bme280->cal_param.dig_H3);//0xE3 = 0x00 return 0; } Вопрос был в том, почему в исходнике нет необходимости писать в каждой функции присвоение p_bme280 = &bme280_cfg;? Повторюсь, все происходит в одном файле. Изменено 8 декабря, 2016 пользователем Димон Безпарольный Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться