Easyelectronics.ru

Электроника для всех
Текущее время: 19 фев 2020, 12:43

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



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

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

Зарегистрирован: 19 мар 2011, 05:05
Сообщения: 2816
Очередной затык (правда уже решил все переносом всего второй файл, но все равно интересно, как):
есть 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
Сообщения: 686
Тут слишком много нужно объяснять :(. Начните пожалуй с начала - K&R «Язык программирования Си».
Вас интересует главы описывающие видимость имен, объявление переменных, оъявление функций, компиляцию и сборку программы.


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

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

_________________
RADIOWOLF.RU


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

Зарегистрирован: 24 июн 2011, 14:05
Сообщения: 299
Откуда: Новочеркасск
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
Сообщения: 4037
Макросы - это простые текстовые замены. Их либо прописать в .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
Сообщения: 177
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
Сообщения: 4037
Я так понял, что топикстартер пытается написать софтовые таймеры. Блин, пишите как-то попроще, чтоль, без сложно запутанных связей и длинных имен.
Вот, тыщщу лет назад писал, не помню какая это версия была, потом переписывал под конкретные нужды:
Show swtimers.c

Show swtimers.h


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

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


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

Зарегистрирован: 19 мар 2011, 05:05
Сообщения: 2816
теперь еще вопрос один, на этот раз про указатели, структуры и манипуляции с ними - про прописные истины, короче говоря...
в 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
Сообщения: 2816
ах, да, описание типа выглядит следующим образом
Код:
/**@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
Сообщения: 2816
запустилось и не поругалось, но во второй половине этих восьми байт - какой-то мусор возникает. очевидно, то, что код расположил в паияти после temperature_value?


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

Зарегистрирован: 15 ноя 2015, 12:11
Сообщения: 177
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
Сообщения: 2816
"на стеке функции 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
Сообщения: 177
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
Сообщения: 2816
ну int8_t - потому что если бы был тип int4_t (в смысле процессор бы умел работать с четырехбитными ячейками память) - было int4_t?
ну то есть в p_data мы указываем адрес ячейки, начиная с которого хранятся наши байты, а в p_len - адрес ячейки, в которой содержится число этих байт?

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


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

Зарегистрирован: 19 мар 2011, 05:05
Сообщения: 2816
теперь с массивами затык:
есть структура
Код:
/**@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
Сообщения: 2816
прокатило с memcpy(my_ecb.key, mykey, sizeof(mykey));
с остальными вопросами пока разбираюсь.


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

Зарегистрирован: 15 ноя 2015, 12:11
Сообщения: 177
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
Сообщения: 4037
my_ecb.key = mykey[5]; например. Невозможно одному байту (элементу) присвоить значение нескольких байт (элементов) сразу.


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


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


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

Сейчас этот форум просматривают: sdv_cyborg


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

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

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