массив boolean в массив byte

Тема в разделе "Arduino & Shields", создана пользователем A.T.M, 9 сен 2016.

Метки:
  1. A.T.M

    A.T.M Нерд

    Есть массив типа boolean, нужно отправить его на eeprom 24с32 по i2c, использую стандартную библиотеку wire. Таким образом осуществлять передачу нужно побайтово, могу взять и собрать из булеанов байт, однако мне интересно есть ли способ сразу взять 8 булеанов и отправить непосредственно, они ведь в памяти друг за другом следуют?
     
  2. AlexU

    AlexU Гуру

    Проблема в том, что "8 булеанов" -- это 8 байт. Вот такая вот расточительность в языке С/С++....
     
  3. Tomasina

    Tomasina Сушитель лампочек Модератор

    возьми 1 байт, в котором каждый из 8 бит (B00000000) будет отвечать за свой boolean.
    Т.е. пересылаешь 1 байт, а на приемнике он уже разворачивается в 8 переменных boolean (либо так и оперируй побитово).
     
  4. ostrov

    ostrov Гуру

    Используйте битовые операции логики и сдвига, тогда упихать 8 бит в байт проблем не будет. Если самостоятельно не получится, напишу как.
     
  5. A.T.M

    A.T.M Нерд

    УЖАСНО! А я то думал что под кажный булеан свой бит. Спасибо за ответы!
     
  6. A.T.M

    A.T.M Нерд

    буду использовать примерно следующий алгоритм:

    byte a = 0; //переменая в которую буду помещать значение boolean
    byte b = 0; //переменая в кторорой соберу число из 8 boolean
    for(byte i =0,i<8,i++)
    {
    a = mass; //из массива boolean передаю в а значение
    b= b||a;
    b = b <<1;
    }
    //после чего отправлю b

    Правильно?
     
  7. A.T.M

    A.T.M Нерд

    разобрался, вот так должно быть
    byte a = 0; //переменая в которую буду помещать значение boolean
    byte b = 0; //переменая в кторорой соберу число из 8 boolean
    for(byte i =0,i<8,i++)
    {
    b = b <<1;
    a = mass; //из массива boolean передаю в а значение
    b= b|a;
    }
    //после чего отправлю b
     
    ostrov нравится это.
  8. Onkel

    Onkel Гуру

    ну это не проблема С, это вообще не проблема, это фича мк atmega328 и других atmeg- у них нет битовых полей. В некоторых других мк можно в память писать /считывать побитно.
     
  9. A.T.M

    A.T.M Нерд

    Не до конца понимаю что такое битовое поле(кажется это та часть ячейки памяти, которая нужнна, но которую нужно сперва вычленить?).Однако ведь программно можно хранить 8 битовых значений как в одном, так и в 8 байтах. В codevisionAVR есть возможность оптимизации кода по размеру и по скорости выполнения, догадываюсь явление связанно с данным вопросом?
     
  10. Onkel

    Onkel Гуру

    Нет, оптимизация не связана с хранением булевых переменных как битов, побайтная адресация - сво-ва atmega, и тут ничего с'оптимизировать не получится. Оптимизация по размеру обычно делается выделением общих каких-то функций или действий в отдельные функции, например если вы анализируете пины и по результатам что-то делаете похожее, то компилятор может объединить эти действия в одну функцию, когда оптимизация по скорости - наоборот, за счет уменьшения переходов оптимизирируется скорость, но размер кода как правило растет.
     
  11. AlexU

    AlexU Гуру

    Битовые поля -- это фишка компилятора, а не контроллера. Компилятор avr-gcc (для atmega и прочих avr) поддерживает битовые поля и ни каких проблем с использованием битовых полей в AVR'ках нет.
    Здесь у меня пробел в знаниях, можете подсказать МК, в котором можно адресовать отдельные биты?

    Что касается того, что тип bool в памяти представляется как байт, то связано это с тем, что переменная каждого типа должена быть адресуемой. А в большинстве МК/процессоров (AVR'ки, PIC'и, ARM'ы, Intel'ы, AMD'хи, PowerPC'хи и т.п.) минимальной адресуемой ячейкой памяти является байт. Поэтому компиляторы языка C/C++ (семейство GCC, Intel и т.п.), для таких МК/процессоров под bool выделяют байт памяти.
     
  12. Onkel

    Onkel Гуру

    неловко выразился, но смысл тот же- минимальная единица в atmega - байт, а не бит. Но термин битовые поля - относится именно к железу, а не к компилятору.
    Cквозную адресацию по битам встречал в stm32, вроде 051.
     
  13. Unixon

    Unixon Оракул Модератор

    Вообще-то битовые поля присутствуют в Си совершенно стандартным образом и ни с каким компилятором это не связано.

    Код (C):

    struct
    {
      unsigned int b0:1;
      unsigned int b1:1;
      unsigned int b2:1;
      unsigned int b3:1;
      unsigned int b4:1;
      unsigned int b5:1;
      unsigned int b6:1;
      unsigned int b7:1;
    } bitfields8;

    bitfields8 a;

    a.b0 = 1;
    a.b1 = 0;

    bool x = (0==rand());
    a.b2 = x;
     
     
  14. Unixon

    Unixon Оракул Модератор

    При использовании любого побайтового хранилища, хоть FLASH, хоть, EEPROM, хоть обычной памяти SRAM, все равно читать и писать ее придется байтами, поскольку побитовый доступ они не поддерживают. А в таком случае упаковку и распаковку битов в байты все равно придется делать вручную. Ну, написать функцию-обертку.

    При этом можно использовать как в буквальном смысле синтаксически оформленные битовые поля, так и побитовые операции над байтами целиком, точно так же, как мы поступаем с регистрами. Впрочем, именно в эти операции с регистрами в итоге все и превратится. Для фиксированных полей конфигурации удобнее структуры, для массивов - побитовые операции над байтами.

    Код (C++):

    bool getBit(uint16_t addr)
    {
      return (eeprom.read(addr>>3) >> (addr&7)) & 1;
    }

    void setBit(uint16_t addr, bool data)
    {
      uint8_t ha = addr>>3, la = addr&7;
      uint8_t x = eeprom.read(ha);
      x = (x&~_BV(la)) | (data<<la);
      eeprom.write(ha,x);
    }
     
     
    Последнее редактирование: 11 сен 2016
    ostrov и ИгорьК нравится это.
  15. ostrov

    ostrov Гуру

    Это как?
    Код (C++):
    la = addr&7;
     
  16. Unixon

    Unixon Оракул Модератор

    Отрезает младшие 3 бита (7 = B00000111).
     
  17. ostrov

    ostrov Гуру

    А, это логический "и", спутал с указателем. ))
     
  18. Unixon

    Unixon Оракул Модератор

    Это побитовое "и" :)
     
  19. ZAZ-965

    ZAZ-965 Гуру

    Код (C++):
    return ((eeprom.read(addr>>3) >> (addr&7)) & 1;
    тут вроде закрывающей скобки не хватает, и у меня есть как минимум две позиции для ее вставки ;)
     
  20. Unixon

    Unixon Оракул Модератор

    Поправил.