Работа с битами.
- Войдите на сайт для отправки комментариев
Ср, 31/10/2012 - 14:48
Коллеги!
Есть переменная типа uint16_t. Необходимо с битами этой переменной проводить операции: установить в 0, установить в 1, инвертировать.
В качестве параметра получаю номер бита и собственно переменную.
Установить в 1 - я понимаю. Сделать битовую маску возведением 2 в степень i и выполнить битовое ИЛИ.
Вопросы:
1. можно ли инвертировать битовую маску? Например из 00010000 получить 11101111.
2. Как красиво инвертировать i-й бит?
Не гуру в С.
Подскажите пожалуйста.
bitRead()
bitWrite()
bitSet()
bitClear()
Ну и так чуть чуть на примере:
int i = 5; // бинерно: 101
i |= (1<<2); // Or -> 111 или i |= _BV(2);
i &= ~(1<<1); // And -> 110 или i &= ~_BV(1);
Спасибо огромное! То что нужно!
А вот от последних двух строчек аж волосы на спине дыбом встали! Где бы почитать про синтаксис?
p.s. Еще раз спасибо!
Читать теорию по с. Любой учебник, битовые операции.
| - или (OR)
& - и (AND)
~ - инверсия (NOT)
^ - исключающее или (XOR)
<< - сдвиг влево
>> - сдвиг вправо
тоглить к-тый бит
i^=1<<k;
подскажите пожалуйста. не могу сообразить как реализовать.
есть переменная типа int принимает значения от 1 до 252 (цвет оттенка (всего 252 оттенков)
далее 255/3 получаем 84. весь смысл в том, что три основных цвета будут задаваться уровнем от 1 до 84
в итоге мне нужно из одной переменной типа int (от 1 до 252)
получить три переменные (от 1 до 64)
я понимаю, что это можно сделать с помощью операций с битами но что то не соображу как.
я понимаю, что это можно сделать с помощью операций с битами но что то не соображу как.
84 не является степенью двойки. Так что битами не получится. Далее, если бы на каждый цвет было бы по 84 градации яркости, то и цветов было бы 84^3=592704
А раз у вас всего оттенков 252, то больше чем по 2-3 бита на цвет не получается. Например:
8×8×4 (R3G3B2) В этой палитре используется 3-битный красный цвет, 3-битный зелёный и 2-битный синий. Бит 07 06 05 04 03 02 01 00 Данные R R R G G G B B (где R-красная, G-зелёная, B-синяя составляющие)А вот их можно обрабатывать структурой
typedef struct colors_st { unsigned char red:3; unsigned char green:3; unsigned char blue:2; } colors_t;я что то совсем ничего не понял (((. что такое структуры не могу осилить.
вы бы не могли пример кода сделать. точнее например функцию. я ей отдаю значение от 1 до 255 а на выходе получаю три значения для трех цветов. от 1 до 255/3 (примерно 84) я потом просто умножку его на три перед записью в порт?
я ей отдаю значение от 1 до 255 а на выходе получаю три значения для трех цветов. от 1 до 255/3 (примерно 84) я потом просто умножку его на три перед записью в порт?
Это невозможно, так неправильно считаете! Тогда уже не делить на три надо, а кубический корень извлекать!
Я же привел выше пример восьмибитного RGB-332. А какая у Вас цветовая модель (RGB, CMY, YUV, YCbCr, RYB и т.п.) и как она кодируется я вообще без понятия.
Глупец! Не делить, а извлекать корень!!!!! Млин!
84 оттенка синего * 84 оттенка красного * 84 оттенка зеленого = 592704 различных цвета, ити его мать!!!
в байт укладывается, иля, по 6 оттенков, 6*6*6 = 216. И еще несколько цветов бонусом.
------------------
ЗЫ:опять школьники-дебилы набежали, спасу от них нет.
ЗЗЫ: ptr, Это, конечно, не Вам!
Цветовая модель RGB.
Цветовая модель RGB.
Для RGB-332 я Вам структуру дал выше. Через нее и можно работать с отдельными цветами. В зависимости от того, как удобней, или через union, или через указатель.
Но у меня есть большие сомнения, что у Вас она. Число 252 наводит на мысль, что у Вас вариация на тему палитры Netscape. 6x7x6=252. В этом случае через биты не поработаете. К тому же в Netscape эта таблица начиналась с 4, а не с нуля. То есть, допустимыми оттенками были от 4 до 255, а не от 0 до 251
если, как полагает ptr, палитра RGB 6x7x6, то
Andry Smart, а откуда родом эта переменная ваша? Какая функция/библа её генерит? Может удобнее будет исходный код подправить, что-б давал по стандарту -3 байта.
значит я так и сделал. храню три переменные и изменяю их. хотя для моих задач такое количество оттенков избыточно.
а вот http://www.getchip.net/posts/118-adjusty_led-podstraivaemyjj-rgb-svetodiod/ например реализовано то, что мне хотелось. на вход АЦП подаем напряжение и меняется цвет. в первой табличке наглядно описано то, что я хотел. правда тут диапазон от 32 до 224.
Andry Smart, вообще интресная тема. По картинке палитры RGB из ссылки выше я попытался примитивными средствами создать алгоритм.
void setup() { pinMode(9,OUTPUT); pinMode(10,OUTPUT); pinMode(11,OUTPUT); } void loop() { static byte R,G,B; byte n=analogRead(A0)>>2; if (n>=0 && n<63){ R=n*4; G=0; B=0; } if (n>64 && n<127){ R= ~((n-64)*4); G=n*4; B=0;} if (n>128 && n<191){ R=0; G= ~((n-128)*4); B=(n-128)*4;} if (n>192 && n<=255){ R=(n-192)*4; G=(n-192)*4; B=255; } analogWrite(9,R); analogWrite(10,G); analogWrite(11,B); }Работает. Но есть подозрение что можно сделать всё проще и оптимальнее, но не хватает мозгов что-б найти формулу и уйти от IF 'фов..
по моему мне именно это и нужно. огромное спасибо.
Andry Smart, вообще интресная тема. По картинке палитры RGB из ссылки выше я попытался примитивными средствами создать алгоритм.
Работает. Но есть подозрение что можно сделать всё проще и оптимальнее, но не хватает мозгов что-б найти формулу и уйти от IF 'фов..
Я немного избыточно расписал как (скопируйте код куда-нибудь, чтобы вошёл по длине):
unsigned char n6 = ( n & 0x40 ) ? 1 : 0; unsigned char n7 = ( n & 0x80 ) ? 1 : 0; /* 0 <= n < 64 64 <= n < 128 128 <= n < 192 192 <= n < 256 */ R = 4 * ( n * !n6 * !n7 - ( n - 127 ) * n6 * !n7 + 0 * !n6 * n7 + ( n - 192 ) * n6 * n7 ); G = 4 * ( 0 * !n6 * !n7 + ( n - 64 ) * n6 * !n7 - ( n - 191 ) * !n6 * n7 + ( n - 192 ) * n6 * n7 ); B = 4 * ( n - 128 ) * !n6 * n7 + 255 * n6 * n7;Это симуляция вывода по моей программе:
void loop() { //byte n = analogRead( A0 ) >> 2; for ( unsigned short n = 0; n < 256; n++ ) { unsigned char n6 = ( n & 0x40 ) ? 1 : 0; unsigned char n7 = ( n & 0x80 ) ? 1 : 0;; 0 <= n < 64 64 <= n < 128 128 <= n < 192 192 <= n < 256 */ R = 4 * ( n * !n6 * !n7 - ( n - 127 ) * n6 * !n7 + 0 * !n6 * n7 + ( n - 192 ) * n6 * n7 ); G = 4 * ( 0 * !n6 * !n7 + ( n - 64 ) * n6 * !n7 - ( n - 191 ) * !n6 * n7 + ( n - 192 ) * n6 * n7 ); B = 4 * ( n - 128 ) * !n6 * n7 + 255 * n6 * n7; analogWrite( 9, R ); analogWrite( 10, G ); analogWrite( 11, B ); delay( 5 ); } }Промоделировано в Proteus 7.7 SP2.
блин замучился я уже. вот выкладываю весь код. помогите довести до ума. это светильник RGB с датчиком движения. к пинам 9,10,11 подключена лента RGB к пинам 2,3,4 клавиши (подтянуты к питанию а при нажатии к минусу) к пину 5 подключен сенсорный датчик (им управляется срабатывание датчика движения) к пину 6 подключен датчик движения к пину 7 подключен светодиод, который подсвечивает сам датчик движения (нужен для индикации включения датчика движения) клавиша на пин 2 переключает режимы свечения по кольцу 1 переливание цветов, 2 имитация горения свечи, 3 режим обычного света при срабатывании датчика движения включается режим 4 яркий свет. клавиши на пинах 3 и 4 изменяются настройки в режиме 1 изменяется яркость. в режиме 2 в небольших пределах яркость свечи (одной клавишей увеличивается другой уменьшается) а вот в режиме 3 нихрена не получается. (задача, что бы одной клавишей изменялся оттенок а другой яркость) уже крышу сносит на фиг, я понимаю, что код у меня ужасен. может кто поможет? //------------------- всякие дефайны ---------------------------------------- #define Rled 9 // Красный #define Gled 10 // Зеленый #define Bled 11 // Синий #define KeySET 2 // Клавиша "настройка" #define KeyPLUS 3 // Клавиша "+" #define KeyMINUS 4 // Клавиша "-" #define Sensor 5 // Датчик сенсорный #define PIR 6 // датчик движения #define Glaz 7 // Подсветка датчика движения unsigned long currentMillis = 0; // unsigned long prevMillis = 0; // unsigned long currentMillisPIR = 0; // unsigned long prevMillisPIR = 0; // unsigned long zaderzhkaF = 60000; // задержка режима яркого света во включенном состоянии (60 секунд) int SENstate=0; int SENflage=0; int PIRstate=0; int key1state=1; // int key1flag=0; int key2state=1; // int key3state=1; // int PIRon=0; // состояние выключателя датчика движения (когда он включен то по сигналу с датчика изменяется режим на яркий свет) int mode=1; // текущий режим: 1 перелив 2 свеча 3 свет 4 вспышка int prevmode=1; // предидущий режим (запоминаем сюда, что бы вернуться к нему) int Rc=0; // текущая яркость красного int Gc=0; // текущая яркость зеленого int Bc=0; // текущая яркость синего int Rtar=0; // целевой уровень красного int Gtar=0; // целевой уровень зеленого int Btar=0; // целевой уровень синего //----------- настройки для режима свеча -------------------------------------------------------------------- int DELAYcandle = 45; // величина задержки в реиме свеча int Mincandle = 16; // минимальный уровень пламени int Maxcandle = 72; // максимальный уровень пламени int BRcandleM=25; // основная яркость свечи (к этой яркости стремится пламя, если нет внешнего воздействия) int Ccounter = 15; // счетчик int delta=17; // изменяет оттенок свечи (больше меньше зеленого) int interval=10; int candlemode=1; // подрежим свечи 1 набор основного уровня яркости, 2 набор заданной внешним воздействием яркости, // , 3 задать случайный уровень яркости int NEWcandle=20; // новое случайное значения внешнего воздействия //------------------------ настройки для режима переливания цвета ---------------------------------------------- int DELpereliv = 20; // величина задержки в режиме перелив int BRpereliv=255; // максимальная яркость режима "радуга" int nextcolor=1; // 1 с голубого до синего, 2 от синего до фиолетового, 3 от фиолетового до красного, // 4 от красного до желтого, 5 от желтого до зеленого, 6 от зеленого до голубого //------------------- настройка режима свет---------------------------------------------------------------------- int BRlithMAX=20; // яркость для режима "свет" int BRlithR=200; // для режима "свет" значение красного int BRlithG=200; // для режима "свет" значение зеленого int BRlithB=200; // для режима "свет" значение синего int DELAYsvet = 10; // величина задержки в режиме свет //------------- настройка режима яркий свет---------------------------------------------------------------------- int BRflash=255; // максимальная яркость режима "вспышка" int DELAYflash1 = 15; // задержка для режима яркий свет int DELAYflash=1500; //-------------------------- нажата клавиша 1 ------------------------------------ void ONkey1 () { if (key1state==LOW&&key1flag==0) { mode++; key1flag=1; if (mode==4) mode=1; if (mode==1) initmode1 (); if (mode==2) initmode2 (); if (mode==3) initmode3 (); } if (key1state==HIGH&&key1flag==1) {key1flag=0;} } //--------------------------- нажата клавиша 2 ------------------------------------ void ONkey2 () { if (mode==1&&BRpereliv<254) {BRpereliv++; initmode1 (); } if (mode==4&&BRflash<254) {BRflash++; initmode4 (); } } //---------------------------- нажата клавиша 3 ------------------------------------- void ONkey3 () { if (mode==1&&BRpereliv>5) {BRpereliv--; initmode1 ();} if (mode==4&&BRflash>3) {BRflash--;initmode4 ();} if (mode==3&&BRlithMAX<254&&key3state==0) {BRlithMAX++; initcolor (); } if (mode==3&&BRlithMAX>254&&key3state==0) {BRlithMAX==1; initcolor (); } } //------------------------------------------ нажат сенсор --------------------------- void ONsensor () { if (SENstate==1&&SENflage==0) { SENflage=1; if (PIRon==LOW) { PIRon=HIGH; } else { PIRon=LOW; returnmode (); } digitalWrite (Glaz,PIRon); } if (SENstate==0&& SENflage==1) SENflage=0; } // ---------------------------------------- сработал датчик движения --------------------- void ONpir () { if (PIRon==1) { prevMillisPIR = millis (); if (mode!=4) {prevmode=mode; mode=4; initmode4 ();} } } //---------------------------------------- проверка нажатия клавиш, срабатывания сенсоров -- void scankey () { SENstate = digitalRead(Sensor); // узнаём состояние сенсора PIRstate= digitalRead (PIR); // копируем состоние датчика движения key1state=digitalRead(KeySET); // читаем состояние клавиши 1 key2state=digitalRead(KeyPLUS); // читаем состояние клавиши 2 key3state=digitalRead(KeyMINUS); // читаем состояние клавиши 3 if (SENstate==HIGH) ONsensor (); if (SENstate==0&& SENflage==1) SENflage=0; if (PIRstate==HIGH) ONpir (); if (key1state==0) ONkey1 (); if (key1state==HIGH&&key1flag==1) key1flag=0; if (key2state==0) ONkey2 (); if (key3state==0) ONkey3 (); } //---------------------------------------- подсчет для следующих преобразований в зависимости от режима void calculator () { // обработка красного if (mode==1) // если включен 1 режим переливание цвета { if (Rc<Rtar) Rc++; if (Rc>Rtar) Rc--; if (Rc==Rtar&&nextcolor==2) {nextcolor=3; Btar=0; } if (Rc==Rtar&&nextcolor==5) {nextcolor=6; Btar=BRpereliv; } // обработка зеленого if (Gc<Gtar) Gc++; if (Gc>Gtar) Gc--; if (Gc==Gtar&&nextcolor==1) {nextcolor=2; Rtar=BRpereliv; } if (Gc==Gtar&&nextcolor==4) {nextcolor=5; Rtar=0; } // обработка синего if (Bc<Btar) Bc++; if (Bc>Btar) Bc--; if (Bc==Btar&&nextcolor==3) {nextcolor=4; Gtar=BRpereliv; } if (Bc==Gtar&&nextcolor==6) {nextcolor=1; Gtar=0; } } // если включен второй режим свеча if (mode==2) { scankey (); if (Rc<Rtar) Rc++; if (Rc>Rtar) Rc--; if (Gc<Gtar) Gc++; if (Gc>Gtar) Gc--; if (candlemode==1) { if (Gc==Gtar&&Rc==Rtar) { Ccounter=random (1,500); if (Ccounter>450) { NEWcandle=random(Mincandle,Maxcandle); } else NEWcandle=BRcandleM; candlemode=2; Rtar=BRcandleM+5; Gtar=BRcandleM-delta; } } if (candlemode=2) { if (Gc==Gtar&&Rc==Rtar) { Rtar=NEWcandle; Gtar=NEWcandle-delta; candlemode=1; } } } if (mode==3) // если включен режим 3 свет { if (Rc<Rtar) Rc++; if (Rc>Rtar) Rc--; if (Gc<Gtar) Gc++; if (Gc>Gtar) Gc--; if (Bc<Btar) Bc++; if (Bc>Btar) Bc--; } if (mode==4) // если включен режим 4 яркий свет { if (Rc<Rtar) Rc++; if (Rc>Rtar) Rc--; if (Gc<Gtar) Gc++; if (Gc>Gtar) Gc--; if (Bc<Btar) Bc++; if (Bc>Btar) Bc--; currentMillisPIR = millis(); if (currentMillisPIR-prevMillisPIR >zaderzhkaF ) { returnmode (); } } } //------------------------------- инициализация режима 1 переливание цвета --------- void initmode1 () { Rc=0; Gc=BRpereliv; Bc=BRpereliv; Gtar=0; Btar=BRpereliv; Rtar=0; nextcolor=1; interval=DELpereliv; } //------------------------------- инициализация режима 2 свеча ----------------------- void initmode2 () { Rc=BRcandleM; Gc=BRcandleM-delta; Bc=0; Rtar=BRcandleM; Gtar=BRcandleM-delta; Bc=0; interval=DELAYcandle; candlemode=1; } //------------------------------- инициализация режима 3 свет ----------------------- void initmode3 () { initcolor(); interval=DELAYsvet; } //------------------------------ инициализация режима 4 яркий свет ------------------ void initmode4 () { Rtar=BRflash; Gtar=BRflash; Btar=BRflash; interval=DELAYflash1; } //-------------------------------------------- возвращаем предидущий режим ----------------- void returnmode () // возврат предидущего режима { mode=prevmode; if (mode==1) initmode1 (); if (mode==2) initmode2 (); if (mode==3) initmode3 (); } //--------------------------------------------- устанавлвиваем значения портов ------------- void drawwing () { digitalWrite (Glaz,PIRon); analogWrite (Rled,Rc); analogWrite (Gled,Gc); analogWrite (Bled,Bc); } //------------------------------------------- инициализация цвета.... ------------------ void initcolor () { if (BRlithR>BRlithMAX) Rtar=BRlithR-BRlithMAX; else Rtar=BRlithR; if (BRlithG>BRlithMAX) Gtar=BRlithG-BRlithMAX; else Gtar=BRlithG; if (BRlithB>BRlithMAX) Btar=BRlithB-BRlithMAX; else Btar=BRlithB; } //---------------------------------------- настраиваем периферию при запуске----------------- void setup() { pinMode(Rled,OUTPUT); pinMode(Gled,OUTPUT); pinMode(Bled,OUTPUT); pinMode(Glaz,OUTPUT); pinMode(KeySET,INPUT); digitalWrite(KeySET,HIGH); // включаем подтягивающий резистор pinMode(KeyPLUS,INPUT); digitalWrite(KeyPLUS,HIGH); // включаем подтягивающий резистор pinMode(KeyMINUS,INPUT); digitalWrite(KeyMINUS,HIGH); // включаем подтягивающий резистор pinMode(Sensor,INPUT); pinMode(PIR,INPUT); initmode1 (); } //------------------------------------ основной цикл -------------------------------------- void loop() { scankey (); drawwing (); calculator (); delay (interval); }короче в моем случае клавишей регулируется яркость в режиме свет (3й режим) но уменьшив ее до конца она опять становится максимум (так и задумано) но перестает дальше регулироваться.
а настройку цвета в 3м режиме я убрал, а то она была очень кривая