Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: как создать массив из bit?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
zuuuuk
Добрый день.
Я собираюсь программировать контроллер AT90S8515 в CodeVision.
Возник вопрос.
Можно ли создать массив с типом bit?
И обращаться к отдельным битам этого массива.

Я пробовал вот так
typedef struct {
char mybit:1;
} b;
b Bit[127];
…..

Bit[counter].mybit=PINA.0;

Но запись в память происходит, по типу char. Массив занимает много места.
Пожалуйста, плдскажите другие варианты.
VladimirYU
Цитата(zuuuuk @ Sep 30 2008, 10:44) *
Добрый день.
Я собираюсь программировать контроллер AT90S8515 в CodeVision.
Возник вопрос.
Можно ли создать массив с типом bit?
И обращаться к отдельным битам этого массива.

Я пробовал вот так
typedef struct {
char mybit:1;
} b;
b Bit[127];
…..

Bit[counter].mybit=PINA.0;

Но запись в память происходит, по типу char. Массив занимает много места.
Пожалуйста, плдскажите другие варианты.


Как вариант, посмотрите в сторону UNION, в купе с вашим вариантом, может быть поможет.
mempfis_
Цитата(zuuuuk @ Sep 30 2008, 10:44) *
Добрый день.
Я собираюсь программировать контроллер AT90S8515 в CodeVision.
Возник вопрос.
Можно ли создать массив с типом bit?
И обращаться к отдельным битам этого массива.

Я пробовал вот так
typedef struct {
char mybit:1;
} b;
b Bit[127];
…..

Bit[counter].mybit=PINA.0;

Но запись в память происходит, по типу char. Массив занимает много места.
Пожалуйста, плдскажите другие варианты.


Так сохраняйте в структуре состояние всего порта (ну т.е. состояние его пинов)
а потом в программе анализируйте необходимый бит

Код
typedef struct {
  char  pin_state;
} ps;
ps PinState[4]; //например будете хранить состояния пинов 4х портов

#define port_a 0
#define port_c 1
#define port_b 2
#define port_d 3

#define bit_0  1<<0
.........................
#define bit_7  1<<7

PinState[port_a].pin_state = PINA;

if(PinState[port_a].pin_state&bit_0) //проверка пина 0 порта А
{
}
Непомнящий Евгений
примерно так:
Код
char getBit(char* array, int n)
{
  return array[n/8] & (1<<(n%8));
}

void setBit(char* array, int n, char val)
{
   char *p = &array[n/8];
   if (val)
    *p |= 1<<(n%8);
   else
     *p &= ~(1<<(n%8));
}

char array[50]; // размер 50*8

setBit(array, 10, 0);
setBit(array, 11, 1);

char t = getBit(array, 10);


Если с++ - можно обернуть это в класс с перегруженным оператором []
GDI
Поройтесь в заголовочных файлах CV там где порты описаны, там уже есть готовые макросы для подобного описания
tag
Цитата(mempfis_ @ Sep 30 2008, 11:05) *
Так сохраняйте в структуре состояние всего порта (ну т.е. состояние его пинов)
а потом в программе анализируйте необходимый бит

Код
typedef struct {
  char  pin_state;
} ps;
ps PinState[4]; //например будете хранить состояния пинов 4х портов

#define port_a 0
#define port_c 1
#define port_b 2
#define port_d 3

#define bit_0  1<<0
.........................
#define bit_7  1<<7

PinState[port_a].pin_state = PINA;

if(PinState[port_a].pin_state&bit_0) //проверка пина 0 порта А
{
}



я бы перефразировал

Код
typedef union
{
  struct
  {
    unsigned char  _0:1;
    unsigned char  _1:1;
    unsigned char  _2:1;
    unsigned char  _3:1;
    unsigned char  _4:1;
    unsigned char  _5:1;
    unsigned char  _6:1;
    unsigned char  _7:1;
  } pin;

  unsigned char port;
} ps;


ps PinState[4]; //например будете хранить состояния пинов 4х портов

#define port_a 0
#define port_c 1
#define port_b 2
#define port_d 3


PinState[port_a].port = PINA;

if(PinState[port_a].pin._0) //проверка пина 0 порта А
{
}
Ph. Anatoliy
Цитата(zuuuuk @ Sep 30 2008, 10:44) *
Добрый день.
Я собираюсь программировать контроллер AT90S8515 в CodeVision.
Возник вопрос.
Можно ли создать массив с типом bit?
И обращаться к отдельным битам этого массива.

Я пробовал вот так
typedef struct {
char mybit:1;
} b;
b Bit[127];
…..

Bit[counter].mybit=PINA.0;

Но запись в память происходит, по типу char. Массив занимает много места.
Пожалуйста, плдскажите другие варианты.


Доброго времени суток!

Вот Вам, мой вариант:
#define BUFFER_BIT_SIZE 32

unsigned char buffer[BUFFER_BIT_SIZE/8+1]; // +1 для запаса. Если буфер кратен 8 то не нужно

void set_bit_buffer (unsigned char value)
{
unsigned char b,i;

b = value/8;
i = value%8;

buffer[b] |= (0x80 >> i);
}

unsigned char get_bit_buffer (unsigned char value)
{
unsigned char b,i;

b = value/8;
i = value%8;

b = buffer[b];
b <<= i;
b &= 0x80;

return b; // Если бит = "1" возвращаем 0x80;
}

Такой вариант будет экономить память, но нагружать АЛУ (соответсвенно - потери в скорости).
defunct
Цитата(Ph. Anatoliy @ Oct 1 2008, 14:15) *
Вот Вам, мой вариант:

b = value/8;
i = value%8;

Такой вариант будет экономить память, но нагружать АЛУ (соответсвенно - потери в скорости).


Плохой вариант. Лучше так:

b = value >> 3;
i = value & 0x7;
Сергей Борщ
Цитата(Ph. Anatoliy @ Oct 1 2008, 14:15) *
Вот Вам, мой вариант:
#define BUFFER_BIT_SIZE 32

unsigned char buffer[BUFFER_BIT_SIZE/8+1]; // +1 для запаса. Если буфер кратен 8 то не нужно
А вот Вам мой:
Код
unsigned char buffer[(BUFFER_BIT_SIZE + 7)/8];//всегда выделяет столько, сколько нужно
И можно оформить это в виде макросов:
Код
#ifndef    BIT_ARRAY_H__
#define    BIT_ARRAY_H__
#include    <stdint.h>

#define    BA_BASE    uint8_t                                // 8 bits
#define    BA_BASE_BITS    (CHAR_BIT * sizeof(BA_BASE))        // 8
#define    BA_BASE_MASK    (BA_BASE_BITS - 1)                    // 7 = 0x07

#define    BIT_ARRAY(name, size)    \
    BA_BASE name[ (size + BA_BASE_BITS - 1) / BA_BASE_BITS ]
//  Macro can be modified to functions to reduce code size
#define    BIT_SET(array, bit)        \
    do { array[ bit / BA_BASE_BITS ] |=  (1 << ( bit & BA_BASE_MASK)); } while (0)
#define    BIT_CLR(array, bit)        \
    do { array[ bit / BA_BASE_BITS ] &= ~(1 << ( bit & BA_BASE_MASK)); } while (0)
#define    BIT_TEST(array, bit)    \
    ( array[ bit / BA_BASE_BITS ] & (1 << ( bit & BA_BASE_MASK)) )

/*
// functions can be placed into separate .c file to reduce code size
void BIT_SET(BA_BASE *array, uint8_t bit)
{
    array[ bit / BA_BASE_BITS ] |=  (1 << ( bit & BA_BASE_MASK));
}
void BIT_CLR(BA_BASE *array, uint8_t bit)
{
    array[ bit / BA_BASE_BITS ] &=  ~(1 << ( bit & BA_BASE_MASK));
}
BA_BASE BIT_TEST(BA_BASE *array, uint8_t bit)
{
    return array[ bit / BA_BASE_BITS ] & (1 << ( bit & BA_BASE_MASK));
}
*/
#endif    //BIT_ARRAY_H__

использование:
BIT_ARRAY(Array1, 50);
BIT_ARRAY(Array2, 16);
void test()
{
     BIT_SET(Array1, 45);
     if(BIT_TEST(Array1, 27))
          BIT_CLR(Array2, 5)
}
Ph. Anatoliy
Главное это идея, а как реализовать это дело вкуса =)

Хорошо было бы сравнить полученный ассемблерный код, да и вопрос нельзя решить однозначно, все зависит от задачи.


unsigned char buffer[(BUFFER_BIT_SIZE + 7)/8];//всегда выделяет столько, сколько нужно

хорошая мысль ....

b = value >> 3;
i = value & 0x7;

Опять же, кто-нибудь сравнивал ассемблерный код ?
Сергей Борщ
Цитата(Ph. Anatoliy @ Oct 1 2008, 18:21) *
b = value >> 3;
i = value & 0x7;

Опять же, кто-нибудь сравнивал ассемблерный код ?
IAR, GCC при включенной оптимизации генерят идентичный код для обоих вариантов - заменяют деление на степень двойки сдвигом и взятие остатка наложением маски.
Ph. Anatoliy
Сергей Борщ - Спасибо за анализ ....

Опять таки вопрос оптимизации...

А спрашивали "как организовать битовый массив" а не "как оптимально написать код" =)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.