Easyelectronics.ru

Электроника для всех
Текущее время: 19 сен 2019, 07:30

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/10pcs (Любой цвет!)
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 19 ] 
Автор Сообщение
 Заголовок сообщения: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 17 янв 2018, 05:21 
Старожил

Зарегистрирован: 19 мар 2011, 05:05
Сообщения: 2636
Очередной затык (правда уже решил все переносом всего второй файл, но все равно интересно, как):
есть main.c
в нем
Код:
#include "app_timer.h"
...
#include "our_service.h"


APP_TIMER_DEF(m_our_char_timer_id);

static void timer_timeout_handler(void * p_context)
{
...
}
static void timers_init(void)
{

    // Initialize timer module.
    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);

    // OUR_JOB: Step 3.H, Initiate our timer
    app_timer_create(&m_our_char_timer_id, APP_TIMER_MODE_REPEATED, timer_timeout_handler);
}

//и дальше код, подразумевающий при определенном событии вызов обработчика, который находится в our_service.c


APP_TIMER_DEF определяется в app_timer.h следующим образом:
Код:
#define APP_TIMER_DEF(timer_id)                                  \
    static app_timer_t timer_id##_data = { {0} };                  \
    static const app_timer_id_t timer_id = &timer_id##_data



Вопрос, каким хитрым словом обозначить в our_service.c этот самый m_our_char_timer_id, чтобы можно было из обработчика в our_service запускать этот таймер?
указание extern app_timer_id_t m_our_char_timer_id поругалось на ненайденную переменную. оно и понятно - вроде как константа. хотя сейчас уже подумал, наверное, проще константу объявить локально?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 17 янв 2018, 05:32 
Старожил

Зарегистрирован: 17 дек 2014, 04:38
Сообщения: 677
Тут слишком много нужно объяснять :(. Начните пожалуй с начала - K&R «Язык программирования Си».
Вас интересует главы описывающие видимость имен, объявление переменных, оъявление функций, компиляцию и сборку программы.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 17 янв 2018, 07:23 
Старожил
Аватара пользователя

Зарегистрирован: 18 май 2013, 20:43
Сообщения: 4260
Откуда: Кемеровская область, Киселевск
О да, бестселлер с 34 переизданиями

_________________
RADIOWOLF.RU


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 17 янв 2018, 11:56 
Старожил

Зарегистрирован: 24 июн 2011, 14:05
Сообщения: 294
Откуда: Новочеркасск
goreprogrammist, похожая ситуация была, вышел из положения так: создал структуру и дефайном объявил член структуры. Структуру в другом файле обозвал внешней и всё, появился лишний символ и лишняя точка :).

file.h
Код:
#define CREATION_FIFO_BUF( name_buf, size_buf,type )  \
  struct str_##name_buf{\
                              unsigned short back;                     \
                              unsigned short font;                     \
                              unsigned short count;                     \
                              unsigned short flag;                     \
                              unsigned short const size_all_buf;         \
                              unsigned short const size_one_cell_buff;      \
                    type mass__##name_buf[size_buf];         \
                              }name_buf = { 0, 0, 0, 0, size_buf, sizeof(name_buf.mass__##name_buf[0]) }


struct str{
     CREATION_FIFO_BUF(fifo_servise_buf,32,Uint32);
};


file.c
Код:
struct str val;


какой то левый файл *.с
Код:
extern struct str val;


Щас еще раз прочитал первый пост и сложилось впечатление, что сделали примерно также.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 17 янв 2018, 12:30 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 3618
Макросы - это простые текстовые замены. Их либо прописать в .h файле и подключать именно его, либо, если не хотите так, просто пишите макрос в тех .c файлах, где будете его использовать. Ничего страшного, простая текстовая замена может быть прописана как угодно, лишь бы не дважды в пределах файла. Кстати, можете этот случай защитить от переопределения блоком
#ifndef <имя_макроса>
#define <сам_макрос>
#endif

Кстати, у топикстартера какая-то мозговыносительная конструкция с этим макросом, а главное, непонятно ЗАЧЕМ она???
В макросы удобно выносить такие конструкции как:
#define GREENLED_ON GPIOC->BSRR = 1 << 9
и потом использовать их в коде простой строчкой GREENLED_ON;
А тот макрос, который у топикстартера, его больше одного раза в ф-ции не используешь. Так какой смысл блыо писать его в виде макроса? Пишите открытым текстом, меньше путаницы.

Кстати, в десятый раз перечитав первый пост автора, я сам уже запутался, что конкретно нужно нему?
m_our_char_timer_id - это числовая константа или все-таки изменяющаяся переменная? Если константа, вбейте тупо число цифрами или замените на #define M_OUR_CHAR_TIMER_ID 20 и пропишите эту строчку в том .h, который подключается и к main.c, и к our_service.c

Дааа, вот что значит каша в голове программиста.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 17 янв 2018, 13:12 
Заглядывает иногда

Зарегистрирован: 15 ноя 2015, 12:11
Сообщения: 173
goreprogrammist писал(а):
Вопрос, каким хитрым словом обозначить в our_service.c этот самый m_our_char_timer_id, чтобы можно было из обработчика в our_service запускать этот таймер?

Никак. Переменные static видны только в том модуле в котором они объявлены. Компилятор не создаёт для них "выходов" на линковку. Поэтому из других модулей они недоступны - и буде в разных модулях объявлены с одним именем - это будут независимые переменные.
Разделите макрос на два - в первом объявите переменную как еxtern a во втором объявите её без static.
Код:
#define APP_TIMER_DECL(timer_id)                         \
    extern app_timer_t timer_id##_data;                  \
    extern const app_timer_id_t timer_id

#define APP_TIMER_DEF(timer_id)                               \
    app_timer_t timer_id##_data = { {0} };                  \
    const app_timer_id_t timer_id = &timer_id##_data

APP_TIMER_DECL(m_our_char_timer_id);


В заголовочном файле используйте APP_TIMER_DECL(m_our_char_timer_id); а в модуле (и только в одном модуле проекта!) APP_TIMER_DEF(m_our_char_timer_id);
В заголовке это развернётся в
Код:
extern app_timer_t m_our_char_timer_id_data; extern const app_timer_id_t m_our_char_timer_id;

а в модуле в
Код:
app_timer_t m_our_char_timer_id_data = { {0} }; const app_timer_id_t m_our_char_timer_id = &m_our_char_timer_id_data;

Остальные модули будут видеть extern объявления из заголовка.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 17 янв 2018, 13:13 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 3618
Я так понял, что топикстартер пытается написать софтовые таймеры. Блин, пишите как-то попроще, чтоль, без сложно запутанных связей и длинных имен.
Вот, тыщщу лет назад писал, не помню какая это версия была, потом переписывал под конкретные нужды:
Show swtimers.c

Show swtimers.h


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 17 янв 2018, 14:09 
Старожил

Зарегистрирован: 19 мар 2011, 05:05
Сообщения: 2636
это был пример нужного мне сервиса от нордика. его и курил. код таймера - из рекоменодванного ими SDK.
в примере много всего левого понаписано, часть - исторически так сложилось, часть - вообще необъяснимо.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 19 янв 2018, 00:28 
Старожил

Зарегистрирован: 19 мар 2011, 05:05
Сообщения: 2636
теперь еще вопрос один, на этот раз про указатели, структуры и манипуляции с ними - про прописные истины, короче говоря...
в main.c по таймеру происходит чтение температуры
Код:
static void timer_timeout_handler(void * p_context)
{
    // OUR_JOB: Step 3.F, Update temperature and characteristic value.
    int32_t temperature = 0;    // Declare variable holding temperature value
    static int32_t previous_temperature = 0; // Declare a variable to store current temperature until next measurement.
   
    sd_temp_get(&temperature); // Get temperature
   
    // Check if current temperature is different from last temperature
    if(temperature != previous_temperature)
    {
        // If new temperature then send notification
        our_temperature_characteristic_update(&m_our_service, &temperature);
...
    }

То есть создаем переменную, вызываем sd_temp_get с указателем на нее. там в черной коробочке кто-то что-то в область памяти, на которую указывает указатель, что-то положит. окей.
а потом мы отправляем этот адрес в our_temperature_characteristic_update - а эта штука уже в файле our_service.c:
Код:
void our_temperature_characteristic_update(ble_os_t *p_our_service, int32_t *temperature_value)
{
    // OUR_JOB: Step 3.E, Update characteristic value
    if (p_our_service->conn_handle != BLE_CONN_HANDLE_INVALID)
    {
        uint16_t               len = 8;
        ble_gatts_hvx_params_t hvx_params;
        memset(&hvx_params, 0, sizeof(hvx_params));

        hvx_params.handle = p_our_service->char_handles.value_handle;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
        hvx_params.offset = 0;
        hvx_params.p_len  = &len;
        hvx_params.p_data = (uint8_t*)temperature_value; 

        sd_ble_gatts_hvx(p_our_service->conn_handle, &hvx_params);
    }   
}

здесь в качестве параметра, как я понял, уже само значение?
и вот тут меня интересует строчка hvx_params.p_data = (uint8_t*)temperature_value;
что за хитрое преобразование типа со звездочкой? почему не записать просто temperature_value?
что в итоге будет записано p_data?
если я сделал это p_data длиной в 8 байт, а temperature_value - 4 байта?
и как можно обращаться к отдельным байтам (парам, четверкам байт) в поле p_data этой структуры?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 19 янв 2018, 00:43 
Старожил

Зарегистрирован: 19 мар 2011, 05:05
Сообщения: 2636
ах, да, описание типа выглядит следующим образом
Код:
/**@brief GATT HVx parameters. */
typedef struct
{
  uint16_t          handle;             /**< Characteristic Value Handle. */
  uint8_t           type;               /**< Indication or Notification, see @ref BLE_GATT_HVX_TYPES. */
  uint16_t          offset;             /**< Offset within the attribute value. */
  uint16_t         *p_len;              /**< Length in bytes to be written, length in bytes written after successful return. */
  uint8_t          *p_data;             /**< Actual data content, use NULL to use the current attribute value. */
} ble_gatts_hvx_params_t;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 19 янв 2018, 03:18 
Старожил

Зарегистрирован: 19 мар 2011, 05:05
Сообщения: 2636
запустилось и не поругалось, но во второй половине этих восьми байт - какой-то мусор возникает. очевидно, то, что код расположил в паияти после temperature_value?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 19 янв 2018, 12:39 
Заглядывает иногда

Зарегистрирован: 15 ноя 2015, 12:11
Сообщения: 173
goreprogrammist писал(а):
но во второй половине этих восьми байт - какой-то мусор возникает. очевидно, то, что код расположил в паияти после temperature_value?

temperature_value - указатель на автоматическую переменную temperature, расположенную на стеке функции timer_timeout_handler. "Мусор" - скорее всего адрес возврата из последней (зависит от платформы и соглашений по вызову функций). Что понимается под "увеличением p_data до 8 байт"? p_data это указатель и размер его ( т.е. sizeof(p_data) ) - величина мало зависящая от воли программиста. Если речь о указуемых данных и манипуляциях типом указателя - то ничего удивительного, что разыменование указателя на uint8_t и на uint64_t примет во внимание различное количество данных в памяти, хотя сам указатель будет одним и тем же числом.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 19 янв 2018, 13:34 
Старожил

Зарегистрирован: 19 мар 2011, 05:05
Сообщения: 2636
"на стеке функции time_out_handler" - это надо переварить. представить себе этот стек.

не очень понял смысла (uint8_t*)temperature_value
*temperature_value - указатеь на переменную int64_t
что делает (uint8_t*)
сейчас работает в таком виде:
Код:
void our_temperature_characteristic_update(ble_os_t *p_our_service, int64_t *temperature_value)
{
    // OUR_JOB: Step 3.E, Update characteristic value
    int64_t my_value=*temperature_value;
    my_value=my_value+0xff00;
    if (p_our_service->conn_handle != BLE_CONN_HANDLE_INVALID)
    {
        uint16_t               len = 8;
        ble_gatts_hvx_params_t hvx_params;
        memset(&hvx_params, 0, sizeof(hvx_params));

        hvx_params.handle = p_our_service->char_handles.value_handle;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
        hvx_params.offset = 0;
        hvx_params.p_len  = &len;
        hvx_params.p_data = (uint8_t*)&my_value; 

        sd_ble_gatts_hvx(p_our_service->conn_handle, &hvx_params);
    }   
}


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 19 янв 2018, 15:02 
Заглядывает иногда

Зарегистрирован: 15 ноя 2015, 12:11
Сообщения: 173
goreprogrammist писал(а):
"на стеке функции time_out_handler" - это надо переварить. представить себе этот стек.

Это часть общего стека программы - при использовании cdecl calling convensions в стек заталкиваются параметры функции, затем адрес возврата из функции, затем вызывается функция, и уже функция выделяет место под свои локальные переменные. И если переменная temperature объявлена как занимающая 4 байта, но работать с ней через указатель на восьмибайтовое целое - то не удивительно, что прихватите и адрес возврата. Но соглашений по вызову много разных - и на вашей платформе могут быть отличия от вышеописанного.
goreprogrammist писал(а):
не очень понял смысла (uint8_t*)temperature_value

Приведение указателя [предположим] типа uint32_t* к указателю типа uint8_t*.
goreprogrammist писал(а):
*temperature_value - указатеь на переменную int64_t

А переменная temperature на которую он указывает тоже типа int64_t?
goreprogrammist писал(а):
что делает (uint8_t*)

Физически - ничего. Всего лишь указание компилятору присвоить адрес без проверки типов указателей.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 19 янв 2018, 15:53 
Старожил

Зарегистрирован: 19 мар 2011, 05:05
Сообщения: 2636
ну int8_t - потому что если бы был тип int4_t (в смысле процессор бы умел работать с четырехбитными ячейками память) - было int4_t?
ну то есть в p_data мы указываем адрес ячейки, начиная с которого хранятся наши байты, а в p_len - адрес ячейки, в которой содержится число этих байт?

в общих чертах понял, спасибо за разъяснения!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 19 янв 2018, 16:19 
Старожил

Зарегистрирован: 19 мар 2011, 05:05
Сообщения: 2636
теперь с массивами затык:
есть структура
Код:
/**@brief AES ECB parameter typedefs */
typedef uint8_t soc_ecb_key_t[SOC_ECB_KEY_LENGTH];
typedef uint8_t soc_ecb_cleartext_t[SOC_ECB_CLEARTEXT_LENGTH];
typedef uint8_t soc_ecb_ciphertext_t[SOC_ECB_CIPHERTEXT_LENGTH];

/**@brief AES ECB data structure */
typedef struct
{
  soc_ecb_key_t        key;            /**< Encryption key. */
  soc_ecb_cleartext_t  cleartext;      /**< Cleartext data. */
  soc_ecb_ciphertext_t ciphertext;     /**< Ciphertext data. */
} nrf_ecb_hal_data_t;

я в своем коде делаю так:
Код:
nrf_ecb_hal_data_t my_ecb;
uint8_t mykey[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
my_ecb.key = mykey;

ну и получаю ругань: assignment to expression with array type
как тут удобнее поступить? не присваивать же в 16 строчек?

ну и далее будет, очевидно, вопрос, если у меня есть int64_t mytext - как это правильне и элегантнее преобразовать в левую (или правую?) часть массива из 16 байт? (и последующая обратная процедура)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 19 янв 2018, 16:24 
Старожил

Зарегистрирован: 19 мар 2011, 05:05
Сообщения: 2636
прокатило с memcpy(my_ecb.key, mykey, sizeof(mykey));
с остальными вопросами пока разбираюсь.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 19 янв 2018, 17:08 
Заглядывает иногда

Зарегистрирован: 15 ноя 2015, 12:11
Сообщения: 173
goreprogrammist писал(а):
ну и получаю ругань: assignment to expression with array type
как тут удобнее поступить? не присваивать же в 16 строчек?

итерацией в цикле. либо весь блок через memcpy [если это не сложные обьекты].
goreprogrammist писал(а):
ну и далее будет, очевидно, вопрос, если у меня есть int64_t mytext - как это правильне и элегантнее преобразовать в левую (или правую?) часть массива из 16 байт? (и последующая обратная процедура)

Посмотрите интереса ради в дизасм операций с int64_t - возможно расхочется его использовать - если у вас МК не 64-битный. :-D

Преобразовать можно попробовать как-то так (это идея для затравки а не пример):
Код:
for (int i = 0; i < 8; i++)
   buf[i] = 0xFF & (value >> (i * 8));


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: опять про видимость переменных и подключение файлов в C
СообщениеДобавлено: 19 янв 2018, 18:57 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 3618
my_ecb.key = mykey[5]; например. Невозможно одному байту (элементу) присвоить значение нескольких байт (элементов) сразу.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 19 ] 

Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB