Операции с битами (перевод байта в бит)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Artos
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка
Контактная информация:

Операции с битами (перевод байта в бит)

Сообщение Artos »

Добрый вечер уважаемые форумчане.

У меня такой вопрос:

Имею байтовые переменные

unsigned char x, y, z, k, l;

но я реально пользую 1бит каждого байта как флаги.

Как можно через дефайны или еще как то перевести байты в биты для экономии памяти?

Что то либо уже голова не соображает, либо это сложная задача :)

Такие и наподобии таких вариантов не предлагать так как много кода переписывать :((

if ((x & 0x01)==0) { /* что то делаем */ }
Реклама
Аватара пользователя
koyodza
Собутыльник Кота
Сообщения: 2623
Зарегистрирован: Вс июл 17, 2011 11:51:52
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение koyodza »

У i51 есть битовые переменные
Реклама
Artos
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение Artos »

Я знаю, есть

bit x;

Но мне надо аналог сделать без применения bit

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

а так выдает ошибку....

volatile bit x;

то есть получается нельзя указать что бит является важным и выкидывать задержки и команды нельзя.... :(
Tolmi
Говорящий с текстолитом
Сообщения: 1658
Зарегистрирован: Вс дек 11, 2011 05:25:04
Откуда: Киев, Украина
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение Tolmi »

Код: Выделить всё

struct Flag_Collection
{
   unsigned flag1  : 1;    // 0   
   unsigned flag2  : 1;    // 1  
   unsigned flag3  : 1;    // 2
//.....  и так далее ...
   unsigned flag8   : 1;    // 7
};
// ....
strust Flag_Collection flagi;
// ...
flagi.flag1=0;
flagi.flag7=1;


In theory, theory and practice are the same. In practice, they're not.
Реклама
Эиком - электронные компоненты и радиодетали
Artos
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение Artos »

Не работает... :(

Вот я так как то и хочу, но такой вариант не работает..

Так у меня есть:

Код: Выделить всё

#define  x (data_bit & 0x01)

unsigned char data_bit;

if(key)
{
if (x==1) x=0;
else x=1;
}
Реклама
Artos
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение Artos »

Tolmi писал(а):

Код: Выделить всё

struct Flag_Collection
{
   unsigned flag1  : 1;    // 0   
   unsigned flag2  : 1;    // 1  
   unsigned flag3  : 1;    // 2
//.....  и так далее ...
   unsigned flag8   : 1;    // 7
};
// ....
strust Flag_Collection flagi;
// ...
flagi.flag1=0;
flagi.flag7=1;


Ваш код тоже не подходит :(
Реклама
Аватара пользователя
avreal
Опытный кот
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение avreal »

pre-scriptum: Пока я отвлекался, фактически то же самое уже было написано, но я и свои 5 копеек вставляю.
Ваш код тоже не подходит :(
Ну и вопрос сразу: странно — какой это компилятор не поддерживает битовые поля?
Они существуют с давних пор, от начала существования С.
Artos писал(а):Имею байтовые переменные
unsigned char x, y, z, k, l;
Для начала, если это не «так, для примера», а реальные переменные, очень рекомендую перестать использовать однобуквенные имена для чего-либо, кроме «очень локальных» переменных, например, индексов циклов. Т.е. от места определения такой переменной до места её исчезновения должно быть не больше половины экрана кода :-)
Иначе очень быстро с ростом размеров программ будет путаница.
А осмысленные имена избавляют от необходимости писать комментарии вида

Код: Выделить всё

    unsigned char b; /* это счётчик битов */ 
или

Код: Выделить всё

    r = 1; /* переходим в приёма */ 
В записях

Код: Выделить всё

    unsigned char bit_cnt; 
или

Код: Выделить всё

    receive_mode = 1; 
символов набирать нужно меньше :)

По флагам.
За исключением расширения языка С в виде поддержки битовых переменных, как это есть для MCS51, остальные способы разменивают размер ОЗУ на размер флеша.
Запись

Код: Выделить всё

enum { flag1 = 0x01, flag2 = 0x02, flag3 = 0x03 }; // Имена для примера  :))) 
uint8_t flags;

if (flags & flag1) flags &= ~flag2; 
муторная, но в большинстве компиляторов даст минимальный код. Больше, чем

Код: Выделить всё

if (flag1) flag2 = 0; 
но минимально возможный для упакованніх в байт битов.

Запись в виде битовых полей

Код: Выделить всё

struct {
    unsigned char flag1 : 1; // выделяем под поле один бит
    unsigned char flag2 : 1; // выделяем под поле один бит
    unsigned char flag3 : 1; // выделяем под поле один бит
    unsigned char       : 1; // пропускаем один бит (ровняем state на полубайт), имя не обязательно
    unsigned char state : 4; // выделяем под поле четыре бита
} fags; // в сумме 8 бит займут один байт

   if (flags.flag1) flags.state = 3; 
приятнее, но может привести к размеру кода большему, чем с масками выше. Зависит от компилятора.
Но чем ближе светлое будущее, тем компиляторы умнее, так что постепенно это становится не таким страшным.

Для возможности поиграться между расходом ОЗУ и ПЗУ я иногда делаю так

Код: Выделить всё

#ifdef SMALL_RAM
#define ONEBIT : 1 // будут выделены биты
#else
#define ONEBIT  // будут выделены байты
#endif

struct {
    unsigned char flag1 ONEBIT ;
    unsigned char flag2 ONEBIT ;
    unsigned char flag3 ONEBIT ;
} fags; 
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Аватара пользователя
avreal
Опытный кот
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение avreal »

Artos писал(а):volatile bit x;
У битовых полей с volatile всё в порядке, но нужно помнить, что запись даже однобитового поля для чуть менее, чем всех процессоров будет неатомарной операцией и её надо заворачивать в запрет/разрешение прерываний.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Artos
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение Artos »

avreal писал(а): Для начала, если это не «так, для примера»,
Это для примера :)

У меня компилятор CVAVR

такая конструкция не пашет...

Код: Выделить всё

struct Flag_Collection
{
   unsigned flags_pass  : 1;    // 0   
   unsigned flag2  : 1;    // 1  
   unsigned flag3  : 1;    // 2
//.....  и так далее ...
   unsigned flag8   : 1;    // 7
} flags;

if (flags_pass ) flags_pass = 0;
else flags_pass =1;
Выдает ошибку:

Error: J:\ (1670): undefined symbol 'flags_pass'
Artos
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение Artos »

avreal писал(а):Запись в виде битовых полей
Код:
struct {
unsigned char flag1 : 1; // выделяем под поле один бит
unsigned char flag2 : 1; // выделяем под поле один бит
unsigned char flag3 : 1; // выделяем под поле один бит
unsigned char : 1; // пропускаем один бит (ровняем state на полубайт), имя не обязательно
unsigned char state : 4; // выделяем под поле четыре бита
} fags; // в сумме 8 бит займут один байт

if (flags.flag1) flags.state = 3;
приятнее, но может привести к размеру кода большему, чем с масками выше. Зависит от компилятора.
Но чем ближе светлое будущее, тем компиляторы умнее, так что постепенно это становится не таким страшным.
Не подходит.... :(

Много переписывать...

Тогда мне уже будет лучше так писать:

if (bit & 0x01) bit &=~0x01;
else bit |=0x01;
Artos
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение Artos »

странно .... в старых версиях CVAVR

такое не работало:

volatile bit x;

:shock:

в 2.05 уже работает.
Tolmi
Говорящий с текстолитом
Сообщения: 1658
Зарегистрирован: Вс дек 11, 2011 05:25:04
Откуда: Киев, Украина
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение Tolmi »

Artos писал(а): Ваш код тоже не подходит :(
И чем не подходит мой код?
Спойлер

Код: Выделить всё

#include <stdio.h>
#include <stdlib.h>
union Flag_Union {
	unsigned char chr;
	struct bite {
		unsigned flag0:1;
		unsigned flag1:1;
		unsigned flag2:1;
		unsigned flag3:1;
		unsigned flag4:1;
		unsigned flag5:1;
		unsigned flag6:1;
		unsigned flag7:1;
	} flag;
};
union Flag_Union flagi;
int main(void) {
	flagi.chr=0; // Clear all flags
	flagi.flag.flag0=1;
	flagi.flag.flag5=1;
	if (flagi.flag.flag5==1 && flagi.flag.flag6==0){
		printf("byte=%d, flags=%d,%d,%d,%d,%d,%d,%d,%d",
				flagi.chr,
				flagi.flag.flag0,flagi.flag.flag1,flagi.flag.flag2,flagi.flag.flag3,
				flagi.flag.flag4,flagi.flag.flag5,flagi.flag.flag6,flagi.flag.flag7);
	}
	return 0;
}
Вывод:
byte=33, flags=1,0,0,0,0,1,0,0
flagi.flag.flagX можно через #define переопределить в x,y,z чтобы не тарабанить по клавиатуре каждый раз.
In theory, theory and practice are the same. In practice, they're not.
Artos
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение Artos »

Tolmi писал(а): flagi.flag.flagX можно через #define переопределить в x,y,z чтобы не тарабанить по клавиатуре каждый раз.

Точно!
Продефайнить все имена! Тогда работать будет :)
Спасибо за подсказку!
А как обьявить битовое поле с числом битов 32шт. и более?

наверное unsigned long chr {} ?
Tolmi
Говорящий с текстолитом
Сообщения: 1658
Зарегистрирован: Вс дек 11, 2011 05:25:04
Откуда: Киев, Украина
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение Tolmi »

Artos писал(а): А как обьявить битовое поле с числом битов 32шт. и более?

наверное unsigned long chr {} ?
А компилятор сам разберется, пока в структуре есть последовательно расположенные битовые поля, он будет их последовательно складывать.
будет
unsigned nameXXX:1;
повторяться 32 раза,
будет 32-битная структура.

И да, длина поля может быть больше одного бита,
например
//
unsigned pack4bit:4;
// сможет принимать
значения от 0 до 15 и занимать 4 бита.

Работает вполне предсказуемо : получение значения - сдвиг и маскирование, присвоение - сдвиг и маскирование аргументом.
Но, да, если больше жаль флэш памяти, чем оперативки, то лучше забить и использовать байтовые переменные. Просто обычно купить более ёмкую флэш память гораздо проще, чем найти процессор с большим объемом ОЗУ.
In theory, theory and practice are the same. In practice, they're not.
Artos
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение Artos »

Спасибо за развернутый ответ :)

Ну оперативки тоже жалко :)
Поэтому все же лучше пожертвовать флэшой.
metan
Вымогатель припоя
Сообщения: 593
Зарегистрирован: Ср янв 06, 2010 10:01:46

Re: Операции с битами (перевод байта в бит)

Сообщение metan »

Здравствуйте!
Я думаю вполне можно попробовать заюзать такое:

Код: Выделить всё

#define   SetBit(reg, bit)          reg |= (1<<bit)            
#define   ClearBit(reg, bit)       reg &= (~(1<<bit))
#define   InvBit(reg, bit)          reg ^= (1<<bit)
#define   BitIsSet(reg, bit)       ((reg & (1<<bit)) != 0)
#define   BitIsClear(reg, bit)    ((reg & (1<<bit)) == 0)
пример использования:

Код: Выделить всё

…
SetBit(PORTB, 0);    //установить нулевой бит порта B    
InvBit(tmp,6);         //инвертировать шестой бит переменной tmp

…
if  (BitIsClear(PIND, 0)) {   //если очищен нулевой бит в регистре PIND                                     
…..                                     //выполнить блок
}
Artos
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение Artos »

Хороший код! Спасибо! Взял на заметку :)
Tolmi
Говорящий с текстолитом
Сообщения: 1658
Зарегистрирован: Вс дек 11, 2011 05:25:04
Откуда: Киев, Украина
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение Tolmi »

metan писал(а):Здравствуйте!
Я думаю вполне можно попробовать заюзать такое:
И код, который при этом получается, ну просто один в один такой же, как при использовании структур с битовыми полями :tea:
Тут больше вопрос привычки, я с битовыми полями работал ещё 25 лет назад на СМ-4 ;)
Сейчас любой МК мощнее её :)
In theory, theory and practice are the same. In practice, they're not.
Artos
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка
Контактная информация:

Re: Операции с битами (перевод байта в бит)

Сообщение Artos »

А я вовсе самоучка . Да и занимаюсь только третий год программированием, правда интенсивно.
То например ни разу не применял битовые поля...

Как по мне красивее смотрится битовое поле. Его легче читать.
Ответить

Вернуться в «Разные вопросы по МК»