Добрый день. Нужна помощь в решении следующей проблемы: В данном коде есть битовая маска размером 32. Я написал три простых функции, которые выставляют бит, убивают бит и проверяет его состояние. Маска в функции передается по указателю, а не по значению, так как масок может быть более одной. Нужно осуществлять контроль бита до его записи или уничтожения. Никак получается это реализовать если я вызываю функцию проверки в функциях записи или уничтожения... Думаю дело в том, что я не правильно передаю указатель на битовую маску. Если проводить проверку отдельно - то все получается. Но это извращение... Пример кода с проверкой проводимой отдельно (где все срабатывает): Биты выставляются и убиваются через передачу в сиреал нажатия кнопок (см test()), проверка проводится в функции test(). Код (C++): uint32_t flags_list=0; void setup(){ Serial.begin(9600); }; void loop(){ Serial.println(flags_list, BIN); test(); delay(1000); }; void SetFlag(uint32_t *flags_list, uint32_t flag){ // if (!CheckFlag(* flags_list , flag)) *flags_list = *flags_list + flag; }; void DropFlag(uint32_t * flags_list, uint32_t flag){ // if (CheckFlag(* flags_list , flag)) *flags_list = *flags_list - flag; }; uint8_t CheckFlag(uint32_t * flags_list, uint32_t flag){ Serial.print(F("* flags_list = ")); Serial.println (*flags_list); if (* flags_list & flag) return 1; else return 0; }; void test(){ if (Serial.available()){ byte symbol = Serial.read(); if (symbol == '6'){ Serial.println("6 pressed"); if(!CheckFlag(&flags_list, 2)) SetFlag(&flags_list, 2); } else if (symbol == '7'){ Serial.println("7 pressed"); if(CheckFlag(&flags_list, 2)) DropFlag(&flags_list, 2); } else if (symbol == '8'){ Serial.println("8 pressed"); if(!CheckFlag(&flags_list, 4)) SetFlag(&flags_list, 4); } else if (symbol == '9'){ Serial.println("9 pressed"); if(CheckFlag(&flags_list, 4)) DropFlag(&flags_list, 4); } } } Пример кода где возникают глюки, это видно при выводе в сиреал. Биты выставляются и убиваются через передачу в сиреал нажатия кнопок (см test()), проверка проводится в функциях SetFlag() и DropFlag(), как это и должно быть, но не работает ;(((. Код (C++): uint32_t flags_list=0; void setup(){ Serial.begin(9600); }; void loop(){ Serial.println(flags_list, BIN); test(); delay(1000); }; void SetFlag(uint32_t *flags_list, uint32_t flag){ if (!CheckFlag(* flags_list , flag)) // думаю ошибка где-то здесь *flags_list = *flags_list + flag; }; void DropFlag(uint32_t * flags_list, uint32_t flag){ if (CheckFlag(* flags_list , flag))// думаю ошибка где-тоз десь *flags_list = *flags_list - flag; }; uint8_t CheckFlag(uint32_t * flags_list, uint32_t flag){ Serial.print(F("* flags_list = ")); Serial.println (*flags_list); if (* flags_list & flag) return 1; else return 0; }; void test(){ if (Serial.available()){ byte symbol = Serial.read(); if (symbol == '6'){ Serial.println("6 pressed"); // if(!CheckFlag(&flags_list, 2)) SetFlag(&flags_list, 2); } else if (symbol == '7'){ Serial.println("7 pressed"); // if(CheckFlag(&flags_list, 2)) DropFlag(&flags_list, 2); } else if (symbol == '8'){ Serial.println("8 pressed"); // if(!CheckFlag(&flags_list, 4)) SetFlag(&flags_list, 4); } else if (symbol == '9'){ Serial.println("9 pressed"); // if(CheckFlag(&flags_list, 4)) DropFlag(&flags_list, 4); } } }
Попробуйте заменить это: Код (C++): if (!CheckFlag(* flags_list , flag)) // думаю ошибка где-то здесь На это: Код (C++): if (!CheckFlag(flags_list , flag))
И еще, я бы Вам хотел посоветовать, делать имена локальных переменных не совпадающими с глобальными. У Вас есть глобальная: Код (C++): uint32_t flags_list=0; Сделайте локальные хоть так: Код (C++): uint8_t CheckFlag(uint32_t * flags_list_ptr, uint32_t flag){ Так будет видно, что это - раз указатель (pointer), два не спутаешь с глобальной. Иначе, если Вы вдруг поменяете название переменной в определении функции - компилятор даже ошибки не выдаст - будите мучиться искать ошибку.
Ну и по операциям, то, что у Вас делается, не является работой с битами, если я правильно Вас понял: Код (C++): void SetFlag(uint32_t *flags_list, uint32_t flag){ // if (!CheckFlag(* flags_list , flag)) *flags_list = *flags_list + flag; }; void DropFlag(uint32_t * flags_list, uint32_t flag){ // if (CheckFlag(* flags_list , flag)) *flags_list = *flags_list - flag; }; uint8_t CheckFlag(uint32_t * flags_list, uint32_t flag){ Serial.print(F("* flags_list = ")); Serial.println (*flags_list); if (* flags_list & flag) return 1; else return 0; }; Это добавление и вычитание числа к / из переменной "flags_list" Оно, конечно, работает, как частный случай, с проверкой состояния бита, Но правильно это сделать, как то так: Код (C++): int checkbit(const uint32_t value, const uint32_t position) { return ((value & (1 << position)) != 0); } uint32_t setbit(const uint32_t value, const uint32_t position) { return (value | (1 << position)); } uint32_t unsetbit(const uint32_t value, const uint32_t position) { return (value & ~(1 << position)); } При таком варианте не нужно проверять, взведен ли уже бит, при новом взведении бита.
Ну или Ваш вариант с указателями: Код (C++): void SetFlag(uint32_t *flags_list, uint32_t flag){ *flags_list |= flag; }; void DropFlag(uint32_t * flags_list, uint32_t flag){ *flags_list &= ~flag; }; uint8_t CheckFlag(uint32_t * flags_list, uint32_t flag){ Serial.print(F("* flags_list = ")); Serial.println (*flags_list); if ((*flags_list) & flag) return 1; else return 0; };