Биты и преобразование
- Войдите на сайт для отправки комментариев
Чт, 14/06/2012 - 09:55
Помогите пожалуйста с кодом, что то я не понимаю. Мне нужно инвертировать текущий бит в одном массиве байт, если в другом массиве отмечена переменная. И так каждый раз в цикле. Мигание одной лампочкой в наборе байт.
void DoBlinking()
{
int data_size = sizeof(main_data);
int blink_size = sizeof(blink_data);
if(data_size != 0 && blink_size != 0)
{
for(int i=0; i<data_size; i++)
{
byte m_d = main_data[i];
byte b_d = blink_data[i];
if(b_d > 0x00)
{
for(int b=0; b<8; b++)
{
byte curr_bit_data = bitRead(m_d,b);
byte curr_bit_blink = bitRead(b_d,b);
if(curr_bit_blink == 1)
{
//Был 1
Serial.print("was ");
Serial.print(curr_bit_data);
bitWrite(curr_bit_data, b, ~curr_bit_data );
Serial.print(" set ");
Serial.print(curr_bit_data);
// а становится черти-чем 9, 17, 33, 65, 129 итд..
}
Serial.println("~~~~~~~~~~~~~~~");
delay(1000);
}
}
}
}
}
Благодарю.
Вместо Serial.print(curr_bit_data);
Сделайте Serial.println(curr_bit_data,BIN); - тогда число выведется в двоичном виде. Проще будет понять какие биты установились.
А вместо
bitWrite(curr_bit_data, b, ~curr_bit_data );
Попробуйте
curr_bit_data ^= 1 << b;
И еще, строка 16-ть.
Зачем она? У вас же получается что curr_bit_data всегда только 0 или 1. Только первый бит установлен. Наверное логичней будет
curr_bit_data=m_d
Благодарю за помощь, опять вы меня выручаете.
Serial.print("was "); Serial.print(curr_bit_data,BIN); curr_bit_data ^= curr_bit_data; // XOR текущего бита Serial.print(" set "); Serial.print(curr_bit_data,BIN);Я сделал вот так.
Я использую 13 сдвиговых регистров чтобы управлять большим массивом Пираний.
Строка 16 нужна чтобы понимать что из себя представлеят текуший бит. Был ли он зажжен ранее. Все 8 бит задейсвованны в этом байте - ведь они двигаются как паровозик по микросхемам при заливке новых данных. Каждый бит - это 1 из 8 ножек.
P.S. Мне очень хочется стать "пилотом F1". Думаю что я на верном пути, благодарю Вас еще раз. С вашей помощью это происходит быстрее.
И у вас так заработало? По идее же XOR в этом случае должен всегда тупо сбрасывать curr_bit_data в ноль. А вы, вроде, хотели инвертирование. Если же это "то что нужно", то не проще ли просто написать curr_bit_data=0;? А если инвертировать, то нужно было not логический делать curr_bit_data = !curr_bit_data;
Кстати не обязательно менять каждый бит отдельно менять. Можно "одним махом восьмерых побивахом" (а в случае int сразу 16-ть). Причем менять только "те которые нужно". Смотрите:
void setup(){ Serial.begin(9600); byte inputData=B10101010; // выходные данные byte mask= B00001111; // маска по которой будем инвертировать. нужно поменять только младшие четыре бита byte outputData=(inputData & ~mask) | (~inputData & mask); // инвертируем только те биты, которые в mask равны 1 Serial.print("Input:");Serial.println(inputData,BIN); // выведет Input: 10101010 Serial.print("Outout:");Serial.println(outputData,BIN); // выведет Outout:10100101 } void loop(){}Вообщем весь этот DoBlinking(), если выкинуть Serial.print-ты можно ужать до одной строчки (там еще и куча If-фов лишняя, которые никакой погоды не делает).
void DoBlinking() { for(int i=0; i<sizeof(main_data); i++)main_data[i]=(main_data[i] & ~blink_data[i]) | ( ~main_data[i] & blink_data[i] ); // а тут уже можем блинкать исходя из новых, инвертированных значений. }А если, потом почитать http://arduino.ru/Tutorial/Upravlenie_portami_cherez_registry
То можно сразу, без циклов и светики устанавливать "пачкой". По 8-мь штук за раз. Одним присваиванием байта.
Да, вы как всегда правы. Ступил. Конечно curr_data = !curr_data не XOR a NOT
Проверил. теперь все работает как нужно.
void DoBlinking() { int blink_size = sizeof(blink_data); if(blink_size != 0) { for(int i=0; i<blink_size; i++) { byte m_d = main_data[i]; byte b_d = blink_data[i]; if(b_d > 0x00) { for(int b=0; b<8; b++) { byte curr_bit_data = bitRead(m_d,b); byte curr_bit_blink = bitRead(b_d,b); if(curr_bit_blink == 1) { curr_bit_data = !curr_bit_data; bitWrite(m_d, b, curr_bit_data); } } main_data[i] = m_d; } } } }Благодарю за ссылку. Обязательно разберусь.
>Благодарю за ссылку. Обязательно разберусь.
Вначале дожмите код который есть. Строка 04 повторяет условие в строке 06. Ничего полезного, кроме захламления кода - не делает.
Строку 11 - тоже можно убрать. Без нее поведение не изменится. Ну съэкономится пара микросекунд в случае если b_d=0 ну и что? Строка 17 - все равно ничего неправильного не даст сделать. Так что можно спокойно убрать что-бы код был легче. Тем более что во всех других случаях, эти микросекунды будут тратится на проверку этого условия.
> Ступил. Конечно curr_data = !curr_data не XOR a NOT
А не зря он вам тут премерещился. Только применять его нужно не к одному биту, а ко всему байту. Еще раз вгляделся в то что получилось итогово: да мы же изобрели велосипед!!! Всмотритесь: вы, многословно, через цикл, я, чуть компактней, но все равно не идеально, заново реализовали XOR!!!!!
Пустите такой скетч:
void setup(){ Serial.begin(9600); byte inputData=B10101010; // выходные данные byte mask= B00001111; // маска по которой будем инвертировать. нужно поменять только младшие четыре бита byte outputData=(inputData & ~mask) | (~inputData & mask); // инвертируем только те биты, которые в mask равны 1 byte outputData2=inputData ^ mask; // по идее то же самое, только короче Serial.print("Input :");Serial.println(inputData,BIN); // выведет Input :10101010 Serial.print("Output :");Serial.println(outputData,BIN); // выведет Output :10100101 Serial.print("Output2:");Serial.println(outputData2,BIN); //выведет Output2:10100101 } void loop(){}Учитывая это, ваш блин можно сделать еще проще
void DoBlinking(){ for(int i=0; i<sizeof(main_data); i++)main_data[i]^=blink_data[i]; }Попробуйте. По идее должно вести себя так же как и ваша текущая версия.