ArcherVZ 0 April 25, 2017 Posted April 25, 2017 (edited) · Report post Добрый день, коллеги! Работаю в среде IAR for ARM 7.5 - программа под микроконтроллер STM32F103 На этот раз я столкнулся с такой проблемой: есть описание некоторой структуры typedef __packed struct { unsigned int Type:4; // код типа операции unsigned int Pause:1; // разрешение паузы до выполнения шага unsigned int DrainGate1:1; // разрешение клапана 1 unsigned int DrainGate2:1; // разрешение клапана 2 unsigned int ReservedBits:9; // зарезервированные биты unsigned int DrumSpeed; // скорость вращения unsigned char Time; // время вращения unsigned char Reserved[11]; // зарезервированные байты } WPC_SPIN_t; я ожидаю получить размер структуры 16 байт и следующее размещение данных: xx xx sl sh tt xx xx xx xx xx xx xx xx xx xx xx где xx - просто байт sl - младший байт скорости sh - старший байт скорости tt - время вращения На деле же я получаю размер структуры 18 байт и размещение байт, как показано ниже: xx xx sl sh 00 xx tt xx xx xx xx xx xx xx xx xx т.е. байт с временем перемещается на две позиции... а вместо него пишутся нули склыдывается ощущение, что параметр DrumSpeed стал 4-байтовым, потому что при его изменении в последующие два байта пишутся нули. Как мне заставить компилятор правильно размещать данные? Edited April 25, 2017 by Василий Зыков Quote Share this post Link to post Share on other sites More sharing options...
prottoss 0 April 25, 2017 Posted April 25, 2017 · Report post #pragma pack(1) typedef struct { unsigned int Type:4; // код типа операции unsigned int Pause:1; // разрешение паузы до выполнения шага unsigned int DrainGate1:1; // разрешение клапана 1 unsigned int DrainGate2:1; // разрешение клапана 2 unsigned int ReservedBits:9; // зарезервированные биты unsigned int DrumSpeed; // скорость вращения unsigned char Time; // время вращения unsigned char Reserved[11]; // зарезервированные байты } WPC_SPIN_t; #pragma pack() Quote Share this post Link to post Share on other sites More sharing options...
Alechek 0 April 25, 2017 Posted April 25, 2017 · Report post ... unsigned int DrumSpeed; // скорость вращения ... склыдывается ощущение, что параметр DrumSpeed стал 4-байтовым, потому что при его изменении в последующие два байта пишутся нули. А он у Вас какой? Тут АРМы обсуждают а не ПИКи. Quote Share this post Link to post Share on other sites More sharing options...
scifi 0 April 25, 2017 Posted April 25, 2017 · Report post Вот так? unsigned int DrumSpeed : 16; Quote Share this post Link to post Share on other sites More sharing options...
prottoss 0 April 25, 2017 Posted April 25, 2017 · Report post #pragma pack(1) typedef struct { unsigned int Type:4; // код типа операции unsigned int Pause:1; // разрешение паузы до выполнения шага unsigned int DrainGate1:1; // разрешение клапана 1 unsigned int DrainGate2:1; // разрешение клапана 2 unsigned int ReservedBits:9; // зарезервированные биты unsigned int DrumSpeed; // скорость вращения unsigned char Time; // время вращения unsigned char Reserved[11]; // зарезервированные байты } WPC_SPIN_t; #pragma pack() Ой. не верно. Извиняюсь. Битовые поля у Вас запакуются в 32-бит переменную. DrumSpeed тоже будет 32-бит. Нужно вот так: #pragma pack(1) typedef struct { unsigned short Type:4; // код типа операции unsigned short Pause:1; // разрешение паузы до выполнения шага unsigned short DrainGate1:1; // разрешение клапана 1 unsigned short DrainGate2:1; // разрешение клапана 2 unsigned short ReservedBits:9; // зарезервированные биты unsigned short DrumSpeed; // скорость вращения unsigned char Time; // время вращения unsigned char Reserved[11]; // зарезервированные байты } WPC_SPIN_t; #pragma pack() Quote Share this post Link to post Share on other sites More sharing options...
Шаманъ 0 April 25, 2017 Posted April 25, 2017 (edited) · Report post Используйте типы uint8_t, uint16_t, uint32_t и другие из <stdint.h>, если Вам нужно задать конкретный размер поля, ну и про упакованные структуры тоже не стоит забывать. Как-то так: #pragma pack(1) typedef struct { uint16_t Type:4, // код типа операции Pause:1, // разрешение паузы до выполнения шага DrainGate1:1, // разрешение клапана 1 DrainGate2:1, // разрешение клапана 2 ReservedBits:9; // зарезервированные биты uint16_t DrumSpeed; // скорость вращения uint8_t Time; // время вращения uint8_t Reserved[11]; // зарезервированные байты } WPC_SPIN_t; #pragma pack() Edited April 25, 2017 by Шаманъ Quote Share this post Link to post Share on other sites More sharing options...
Axel 0 April 26, 2017 Posted April 26, 2017 (edited) · Report post ...: Так все правильно у Вас и получается: 2 байта на битовые поля и 16 байт на все остальное. Или я чего-то не догнал? Edited April 26, 2017 by IgorKossak бездумное цитирование Quote Share this post Link to post Share on other sites More sharing options...
ArcherVZ 0 April 26, 2017 Posted April 26, 2017 · Report post Спасибо вам! Я внес исправления, и все стало как надо! Quote Share this post Link to post Share on other sites More sharing options...
scifi 0 April 26, 2017 Posted April 26, 2017 · Report post Кстати, я не понял, зачем там __packed. Вроде бы и без этого получится то же самое. Quote Share this post Link to post Share on other sites More sharing options...
Alechek 0 April 26, 2017 Posted April 26, 2017 · Report post Не совсем. у него же typedef, а не готовый объект. При __packed указатель на этот тип имеет право быть невыровенным Quote Share this post Link to post Share on other sites More sharing options...
scifi 0 April 26, 2017 Posted April 26, 2017 · Report post Не совсем. у него же typedef, а не готовый объект. При __packed указатель на этот тип имеет право быть невыровенным А вот интересно, если убрать __packed из определения типа и добавить его к объявлению указателя, всё будет работать так же? typedef struct { ... } FOO_BAR_t; FOO_BAR_t __packed* ptr; Quote Share this post Link to post Share on other sites More sharing options...
Alechek 0 April 26, 2017 Posted April 26, 2017 · Report post Документация по IAR дает однозначный ответ: IAR C/C++ Development Guide Compiling and Linking for ARM Example /* No pad bytes in X: */ __packed struct X { char ch; int i; }; /* __packed is optional here: */ struct X * xp; /* NOTE: no __packed: */ struct Y { char ch; int i; }; /* ERROR: Y not defined with __packed: */ __packed struct Y * yp; /* Member 'i' has alignment 1: */ struct Z { char ch; __packed int i; }; void Foo(struct X * xp) { /* Error:"int *" -> "int __packed *" not allowed: */ int * p1 = xp->1; /* OK: */ int __packed * p2 = &xp->i; /* OK, char not affected */ char * p3 = &xp->ch; } Quote Share this post Link to post Share on other sites More sharing options...