Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial Internet of Things >> Встроенный

Объединения в встроенном C: эффективное совместное использование памяти и обмен сообщениями

Понимание объединений во встроенном C

Во встроенных системах объединение — мощная структура данных, позволяющая хранить разные типы в одной и той же области памяти. Статья разбирает основы объединений, показывает практические примеры и объясняет, почему они незаменимы в приложениях с жесткими ограничениями по памяти и пропускной способности.

Разница между структурой и объединением во встроенном C

Ранее мы рассматривали структуры — способ группировки разнородных переменных в единую сущность. В C объединения — дополнительная конструкция, также группирующая разные типы, но с ключевым отличием: каждый член использует один и тот же адрес памяти.

Вводный пример

Объявление объединения почти идентично структуре; нужно просто заменить struct на union:

union test { uint8_t c; uint32_t i; };

Шаблон определяет два члена: c занимает один байт, i — четыре байта. Чтобы создать переменную этого типа:

union test u1;

Доступ к членам через точечный оператор:

u1.i = 10; m = u1.c; // m должен быть uint8_t

Так как размер объединения равен размеру его наибольшего члена, u1 занимает четыре байта. Запись в i перезаписывает ту же память, которую использует c, поэтому члены взаимоисключающи.

Нужно ли нам совместное использование памяти?

Представьте два встроенных устройства, Устройство А и Устройство Б, обменивающиеся данными о статусе, скорости и позиции (см. Рисунок 1). Элементы данных и их размеры:

Объединения в встроенном C: эффективное совместное использование памяти и обмен сообщениями

Рисунок 1
Переменная Размер (байт) Значение
power 1 Заряд батареи
op_mode 1 Режим работы
temp 1 Температура окружающей среды
x_pos 2 Координата X
y_pos 2 Координата Y
vel 2 Скорость

Если Устройству Б нужна вся информация, простая структура потребовала бы 9 байт, и каждый цикл связи передавал бы 9-байтовый кадр (Рисунок 2). Однако во многих реальных сценариях три типа сообщений взаимоисключающи: иногда только статус, иногда только позиция, иногда только скорость. В этом случае максимальная полезная нагрузка — 4 байта (сообщение позиции). Объединение, разделяющее 4-байтовый буфер, может хранить любое из трех сообщений, сокращая размер кадра с 9 до 4 байт (Рисунок 3).

Объединения в встроенном C: эффективное совместное использование памяти и обмен сообщениями

Рисунок 2

Объединения в встроенном C: эффективное совместное использование памяти и обмен сообщениями

Рисунок 3

Использование объединений для пакетов сообщений

Создадим две структуры — для статуса и позиции — и поместим их в объединение вместе с полем скорости:

struct status_s { uint8_t power; uint8_t op_mode; uint8_t temp; }; struct position_s { uint16_t x_pos; uint16_t y_pos; }; union msg_union { struct status_s status; struct position_s position; uint16_t vel; };

Размер объединения — 4 байта (размер position_s), разделяемых между всеми тремя типами сообщений.

Как отслеживать активный член объединения

Когда приемник читает объединение, он должен знать, какой член действителен. Распространенный паттерн — помеченное объединение: отдельное поле, записывающее активный член. Добавим однобайтовый msg_type перед объединением:

struct message_s { uint8_t msg_type; // 's' = статус, 'p' = позиция, 'v' = скорость union { struct status_s status; struct position_s position; uint16_t vel; } msg; };

Передавая байт msg_type вместе с объединением, получатель может правильно интерпретировать полезную нагрузку без предварительного знания её формы.

Альтернативное решение: динамическое выделение памяти

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

Далее: применение объединений

Объединения также часто используются для извлечения меньших частей данных из более крупного слова — техника, особенно ценная при разборе коммуникационных протоколов или аппаратных регистров. Следите за следующей статьей серии, где мы погрузимся в эти сценарии.

Для просмотра других статей по встроенному C посетите указатель статей.

Встроенный

  1. Выбор идеального языка программирования для решений Промышленного IoT
  2. Основы программирования микропроцессоров
  3. Использование данных в Интернете надежности: стратегии эффективного управления
  4. Демократизация Интернета вещей: Next-Gen Satellite IoT приносит универсальную, доступную связность
  5. 9 языков программирования, которые обязательно нужно выучить в 2021 году
  6. Объединения в C (union): эффективное использование памяти для разных типов данных
  7. Будущее центров обработки данных: тренды, технологии и устойчивость
  8. Использование облачной мощи для IoT: раскрытие бесшовной связности и инсайтов данных
  9. Понимание программирования роботов: методы объяснены
  10. Единицы измерения компрессора: понятное руководство по распространенным терминам