Битовые операции

Efim
Offline
Зарегистрирован: 04.05.2018

При такой записи все работает

void dataout(byte x)                          // Выводим данные в SPI, где (x)-количество бит данных
{   
    for (byte i=(x-1); i!=255; i--)           // Определяем количество циклов 
    {
        bitState = bitRead(recievedByte3, i); // Читаем состояние бита (i) в регистре recievedByte3
        if(bitState) PORTB |= (1<<MOSI_PIN);  // Если бит (i) равен 1 то устанавливаем бит в регистре PORTB.0 (MOSI)
        else PORTB &= ~(1<<MOSI_PIN);         // Иначе сбрасываем бит в регистре PORTB.0 (MOSI)
        delay(2);                             // Формируем задержку для CLK
        PORTB |= (1<<SCK_PIN);                // Устанавливаем бит на шине CLK (PORTB.1)
        if (i==0)                             // Проверяем не является ли текущий бит младшим
        {                                     // Если бит младший:
          delay(1);                           // формируем задержку для защелки
          PORTB |= (1<<MOSI_PIN);             // формируем защелку (устанавливаем бит в PORTB.0)
          delay(1);                           // формируем задержку для защелки
        }
        else                                  // Если бит (i) не является младшим
        {
          delay(2);                           // Формируем задержку для CLK
        }        
        PORTB &= ~(1<<SCK_PIN);               // Сбрасываем бит на шине CLK (PORTB.1)  
    }    
    delay(1);                                 // формируем задержку для сброса защелки
    PORTB &= ~(1<<MOSI_PIN);                  // Сбрасываем защелку PORTB.0 (MOSI)
}
При такой записи не могу вывести больше 16 бит информации

void dataout(byte x)                          // Выводим данные в SPI, где (x)-количество бит данных
{   
    for (byte i=(x-1); i!=255; i--)           // Определяем количество циклов 
    {        
        if(recievedByte3&(1<<i)) PORTB |= (1<<MOSI_PIN);  // Если бит (i) равен 1 то устанавливаем бит в регистре PORTB.0 (MOSI)
        else PORTB &= ~(1<<MOSI_PIN);         // Иначе сбрасываем бит в регистре PORTB.0 (MOSI)
        delay(2);                             // Формируем задержку для CLK
        PORTB |= (1<<SCK_PIN);                // Устанавливаем бит на шине CLK (PORTB.1)
        if (i==0)                             // Проверяем не является ли текущий бит младшим
        {                                     // Если бит младший:
          delay(1);                           // формируем задержку для защелки
          PORTB |= (1<<MOSI_PIN);             // формируем защелку (устанавливаем бит в PORTB.0)
          delay(1);                           // формируем задержку для защелки
        }
        else                                  // Если бит (i) не является младшим
        {
          delay(2);                           // Формируем задержку для CLK
        }        
        PORTB &= ~(1<<SCK_PIN);               // Сбрасываем бит на шине CLK (PORTB.1)  
    }    
    delay(1);                                 // формируем задержку для сброса защелки
    PORTB &= ~(1<<MOSI_PIN);                  // Сбрасываем защелку PORTB.0 (MOSI)
}

Все что старше 16 бита забивается нулями.

Может кто сталкивался?

recievedByte3 тип unsigned long

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

В байте нет "старше 16 бита".

А разрядность bitState нам неизвестна.

Но единица в 5 строке второго фрагмента имеет длину 16 разрядов

Efim
Offline
Зарегистрирован: 04.05.2018

Переменная recievedByte3 у меня 4-х байтная, а условие if(recievedByte3 & (1<<i)) выше 2-го байта ничего не видит. То есть постоянно false.

bitState у меня boolean

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

И не должно. Повторюсь: единица 16-разрядная. Вместо 1 напишите 1UL.

sadman41
Offline
Зарегистрирован: 19.10.2016

Думаю, что тут имеется в виду стандарт, следуя которому, константы при битовых операциях по дефолту приводятся к 16-bit number (что-то такое припоминаю). Заведите uint32_t  переменную равную 1 и шифтуйте ее влево на каждой итерации, например.

Efim
Offline
Зарегистрирован: 04.05.2018

andriano

Спасибо огромное! Век живи, век учись.

sadman41

И Вам огромное спасибо!

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

sadman41, по стандарту длина int должна выбираться разработчиком компилятора, основываясь на длине процессорного слова, но не менее 16 разрядов. По факту: для 8-разрядных процессоров принимается 16 разрядов, а для 32-разрядный процессоров, соответственно, 32.

И в данном случае лучше пользоваться константой нужного типа, а не переменной.

sadman41
Offline
Зарегистрирован: 19.10.2016

Спорить не буду, с телепона код не читал, просто решил пояснить почему единица равна 16-бит.

Efim
Offline
Зарегистрирован: 04.05.2018

Красота