Как передать в shiftOut() значения нескольких boolean?

Тема в разделе "Arduino & Shields", создана пользователем avdeal, 31 мар 2019.

  1. avdeal

    avdeal Нуб

    Доброго времени суток.
    Подскажите пожалуйста.
    Хочу управлять блоком реле с помощью сдвигового регистра.
    Возможно ли в функцию shiftOut() передать значения булиновских переменных?
    shiftOut(dataPin, clockPin, LSBFIRST, j);
    Как из 8 переменных boolean сделать эту j?
    Спасибо.
     
  2. DIYMan

    DIYMan Гуру

    Тупо в лоб:

    Код (C++):
    uint8_t j = uint8_t(boolean1) |  (uint8_t(boolean2) << 1) | (uint8_t(boolean3) << 2) | (uint8_t(boolean4) << 3) | (uint8_t(boolean5) << 4)
    | (uint8_t(boolean6) << 5) | (uint8_t(boolean7) << 6) | (uint8_t(boolean8) << 7);
    Можно и без явных преобразований типов, по идее - навскидку не помню, что там стандарт по этому поводу говорит.
     
    ZAZ-965 и DetSimen нравится это.
  3. avdeal

    avdeal Нуб

    Большое спасибо. Работает как надо!!!
    Зря не пошел я на програмиста учиться а гайки стал крутить. Пол дня гуглил, как это сделать!!! А тут всего: назвал переменную и по битам, сдвигаясь, из других переменных её заполнил.
    Шайтанама!
    Спасибо.
     
  4. fogary

    fogary Гик

    IMHO. Наверное, вместо 8 логических переменных можно использовать битовое поле. Тогда, вместо преобразования, потребуется только приведение к uint8_t.
     
    Daniil нравится это.
  5. avdeal

    avdeal Нуб

    Еще не владею знаниями, чтобы понять это. Переменные меняются в основном цикле программы. Хочу управлять 8 реле 3 контактами.
    Вариант выше работает.
     
  6. DetSimen

    DetSimen Гуру

    Код (C++):

    #pragma pack(push,1)
    struct {
    bool Flag0 : 1;
    bool Flag1 : 1;
    bool Flag2 : 1;
    bool Flag3 : 1;
    bool Flag4 : 1;
    bool Flag5 : 1;
    bool Flag6 : 1;
    bool Flag7 : 1;
    } Flags;
    #pragma pack(pop)


    Flags.Flag7 = true;
    Flags.Flag5 = false;
    Flags.Flag2 = true;
    Flags.Flag1 = true;

    shiftOut(..., ..., ..., static_cast<uint8_t>(Flags));
    вся структура занимает 1 байт и хранит 8 флагов. Подробности - в гугале, ключевые слова для поиска "Битовые поля С"
     
    Последнее редактирование: 1 апр 2019
    Daniil, ИгорьК и DIYMan нравится это.
  7. DIYMan

    DIYMan Гуру

    "Вариант выше" - просто ответ на ваш вопрос. Но, как правильно заметили - хранить булево состояние в 8 переменных - излишество, для этого в одном байте есть целых 8 бит. Использование битовых полей - один из вариантов, ещё вариант - просто битовыми масками сбрасывать/устанавливать нужный бит.

    Вариант с битовыми полями существенно выигрывает в читабельности кода, что в дальнейшем, в случае серьёзного проекта - скажется только положительно. В век, когда компиляторы и оптимизаторы уже умеют делать оптимизацию лучше, чем среднестатистический программист - грех этим не пользоваться, в угоду читаемости кода. Пмсм, конечно.
     
    Daniil и DetSimen нравится это.
  8. DIYMan

    DIYMan Гуру

    Деда, небольшие правки:

    1. Забыл префикс Flags. при обращении к полям структуры;
    2. Структура не обязана иметь размер в один байт, это специфика компилятора и target, под который компилируем. Поэтому лучше указывать выравнивание по границе байта директивой #pragma pack ;)
     
    ИгорьК нравится это.
  9. Asper Daffy

    Asper Daffy Гуру

    И именно потому террористическая группа из восьми ваххабитов называется ваххабайт.
     
    ИгорьК и DIYMan нравится это.
  10. DIYMan

    DIYMan Гуру

    Согласен, был неточен :D: надо было написать "как правило, в одном байте - 8 бит" ;)
     
  11. DetSimen

    DetSimen Гуру

    А бит это байт минус налоги
     
  12. DetSimen

    DetSimen Гуру

    Да. pragma pack я и забыл.
    ПыСы Поправил
     
    Последнее редактирование: 1 апр 2019
  13. DetSimen

    DetSimen Гуру

    А интересно, можно ли Flags обнулять одной командой?
    Типа
    (uint8_t)(Flags) = 0; Низя?
    Или надоть union делать?
     
  14. DIYMan

    DIYMan Гуру

    memset бьёт всё ;)
     
    DetSimen нравится это.
  15. Asper Daffy

    Asper Daffy Гуру

    Дед, так просто она не преобразуется. Через задницу можно, но я бы union делал.

    А "через задницу" - это примерно вот так
    Код (C++):
    #include <Printing.h>

    #pragma pack(1)
    struct {
        bool Flag0 : 1;
        bool Flag1 : 1;
        bool Flag2 : 1;
        bool Flag3 : 1;
        bool Flag4 : 1;
        bool Flag5 : 1;
        bool Flag6 : 1;
        bool Flag7 : 1;
    } Flags;


    void setup(void) {
        Serial.begin(115200);
        Flags.Flag7 = true;
        Serial << "Flags=" << * (uint8_t *) & Flags << "\r\n";
        * (uint8_t *) & Flags = 0;
        Serial << "Flags=" << * (uint8_t *) & Flags << "\r\n";
    }

    void loop(void) {}
    Я тут подумал, и всплыло, что я то исходил, что структура железобетонная. Если её можно немного поменять, то присваивание перестанет быть проблемой. Вот
    Код (C++):
    #include <Printing.h>

    #pragma pack(1)
    struct {
        uint8_t operator = (const uint8_t n) { return * (uint8_t *) this = n; }
        bool Flag0 : 1;
        bool Flag1 : 1;
        bool Flag2 : 1;
        bool Flag3 : 1;
        bool Flag4 : 1;
        bool Flag5 : 1;
        bool Flag6 : 1;
        bool Flag7 : 1;
    } Flags;


    void setup(void) {
        Serial.begin(115200);
        Flags.Flag7 = true;
        Serial << "Flags=" << * (uint8_t *) & Flags << "\r\n";
        Flags = 0;
        Serial << "Flags=" << * (uint8_t *) & Flags << "\r\n";
    }

    void loop(void) {}
     
    Последнее редактирование: 1 апр 2019
    DetSimen нравится это.
  16. avdeal

    avdeal Нуб

    Может года через два, мелкими шагами. Пока непонятно.