Перейти к содержанию
    

Помогите разобраться со структурами

Компилятор С-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 ?????

 

Что здесь не так?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что здесь не так?

 

указатель должен на что-то реальное указывать

 

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;

...

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

. . . .

Далее определяю ссылку:

 

static struct bme280_t *p_bme280; /**< pointer to BME280 */

. . . .

 

Это указатель объявлен. ссылка в С есть нечто другое со знаком &.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ссылка в С есть нечто другое со знаком &.
Ссылок в C нет совсем, они есть в C++.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ссылок в C нет совсем, они есть в C++.

Нэ знал. Пробелы в консерватории :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пытаюсь доконца разобраться. Для того, чтобы элементы структуры были доступны в каждой функции, мне приходится в каждую функцию прописывать:

 

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 глобален. Но все мои попытки один раз назначить ему адрес структуры приводит к ошибке в компиляции. Как это сделать?

 

Заранее спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если эта структура bme280 одна, и размножать их не планируется, предлагаю забыть слово "указатель", раз оно вызывает сложности.

Обращаться непосредственно к полям первоначальной структуры.

 

 

А вообще, правильно заданный вопрос - это хороший тон.

Правильно заданный - это минимальный пример, который показывает проблему.

"Я сделал глобальную структуру A, указатель pA, присваиваю в функции init() pA = &A, потом пользуюсь в функции doItNow() pA->var, и у возникает вот такая ошибка компиляции".

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

/* 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 в других файлах.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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;. В этом и вопрос - в приведенном мной исходнике этого не делают, а с параметрами структуры работают.

Изменено пользователем Димон Безпарольный

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А как и где у вас объявляются p_BME280 и BME280_cfg ?

Обявляются в заголовочном файле:

 

static struct BME280_t BME280_cfg;
static struct BME280_t *p_BME280; /**< pointer to BME280 */

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А заголовочный файл у вас подключается к двум исходным файлам? и получается в каждом файле своя копия BME280_cfg и p_BME280.

Так не делают, смотрите как сделано на github'e. Либо делайте через typedef и extern.

P.S. что бы не разжевывать тут, почитайте http://digitalchip.ru/osobennosti-ispolzov...-i-static-v-c-c

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Обявляются в заголовочном файле:

 

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...

Изменено пользователем conan

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо за развернутый ответ, но речь шла об одном файле. Пост 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;? Повторюсь, все происходит в одном файле.

Изменено пользователем Димон Безпарольный

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...