Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Микроконтроллеры (MCU) и микропроцессоры (MPU) > Сдвиг бита в части регистра


Автор: supercelt 24.7.2016, 13:39
Здравствуйте.

Есть порт В микроконтроллера stm32

Я задействую 5,6,7,8 пины. Остальные служат под другие нужды.

В цикле for надо на 5 пин подать 1, а при следующем  заходе в цикл - сдвигать ее влево. Получится, что цикл проворачивается и  каждый раз нужно ставить 1 с 5 по 8 пин, при этом что бы остальные пины были 0.


Можно конечно сделать вот так

Код

for(i=0; i<4; i++){
    if(i == 0){
        GPIO->BSSR |= (1 << 5);
        GPIO->BRR |= (1 << 6) | (1 << 7) | (1 << 8);
        } else if(i == 1){
        GPIO->BSRR |= (1 << 6);
        GPIO->BRR |= (1 << 5) | (1 << 7) | (1 << 8);
    } else if(i == 2){
        GPIO->BSRR |= (1 << 7);
        GPIO->BRR |= (1 << 5) | (1 << 6) | (1 << 8);
    } else if(i == 3){
        GPIO->BSRR |= (1 << 8);
        GPIO->BRR |= (1 << 5) | (1 << 6) | (1 << 7);
    }

}


Но это быдлокодирование не катит. Затык, не могу сообразить. Я уверен, что программеры с опытом делают это в 1 - 2 строчки. Как?

Автор: Mikron 24.7.2016, 17:49
Код

for(i=0; i<4; i++){
GPIO->BSRR |= ((1<<i)<<5)|((0xf&(~(1<<i)))<<5<<16)
}

Автор: Курсант 25.7.2016, 09:24
Эммм.. Простите, не понял проблемы. У Вас есть число, неважно, что там записано в какой пин. Для сдвига Вы просто делаете такую операцию:
Код

src = (src << 1) & 0x000001E0;

Это если нужно все остальные биты числа оставить нулевыми.
Если нужно оставить биты без изменения, то так
Код

src = ( src & ( 0xFFFFFE1F) ) | ( (src << 1) & 0x000001E0 );


Можно набросать такую функцию:
Код

void PushAndShift ( uint32_t* Dst, uint32_t PushedValue ) {
Dst* = ( Dst* src & ( 0xFFFFFE1F) ) | ( ( Dst* << 1) & 0x000001E0 )
if ( PushedValue ) {
Dst* |= ( 1 << 5 );
}
}

Автор: baldman88 25.7.2016, 11:20
Mikron все верно написал. Только "или" перед знаком равенства излишне и можно это все упростить:
Код
for (i = 5; i <= 8; i++) {
    GPIOX->BSRR = (1 << i) | ((0x1E0 & (~(1 << i))) << 16);
}
По сути нужно в первые 16 бит записать единицу туда, где нужно выставить пин:
Код
(1 << i)
а в старшие 16 -- единицы туда, где сбросить:
Код
((0x1E0 & (~(1 << i))) << 16)
Дальше сделать логическое "или" и результат присвоить BSRR.

Автор: qwerty4 28.7.2016, 16:51
Понаплодили тут извращенств  smile 

Код

for(int i = 1; i <= 8; i=i<<1)
    GPIOx_ODR = (GPIOx_ODR&0xFFFFFE1F)|(i<<5);

Автор: Mikron 28.7.2016, 17:14
Цитата(qwerty4 @ 28.7.2016,  16:51)
Понаплодили тут извращенств  smile 

Код

for(int i = 1; i <= 8; i=i<<1)
    GPIOx_ODR = (GPIOx_ODR&0xFFFFFE1F)|(i<<5);

Все же рекомендуется регистр BSRR как я понимаю

user posted image

Автор: supercelt 28.7.2016, 18:50
Да, рекомендуют работать именно с BSRR и BRR

Автор: qwerty4 29.7.2016, 13:48
Цитата(Mikron @  28.7.2016,  17:14 Найти цитируемый пост)
рекомендуется

Цитата(supercelt @  28.7.2016,  18:50 Найти цитируемый пост)
рекомендуют


Странные вы оба. Слышу звон, да не знаю где он. Перевожу на русский язык это ваше "рекомендуется":

Если не хотите заморачиваться с обеспечением атомарности чтения с последующей записью, то можете  использовать регистр B(S)RR. Если нет требований (как в исходном вопросе) к атомарности, то можете не использовать.

Автор: supercelt 28.8.2016, 14:13
Голова уже кипит. Поделитесь пож опытом. Почему вот так работает

Код

unsigned char i, j;
                for(i = 0; i < 4; i++){
                        GPIOB->ODR = (1 << (i + 5));
                        for(j = 0; j < 4; j++){
                                if(GPIOB->IDR & 1 << (j + 11)){
                                        key = (1 << i);
                                        key |= (1 << j) << 4;
                                }
                        }
                }


А вот так не работает

Код

unsigned char i, j;
                for(i = 0; i < 4; i++){
                        GPIOB->BSRR = (uint32_t)(1 << (i + 5));
                        for(j = 0; j < 4; j++){
                                if(GPIOB->IDR & 1 << (j + 11)){
                                        key = (1 << i);
                                        key |= (1 << j) << 4;
                                }
                        }
                }


Я хочу через BSRR, а единица не скачет по битам а всё время стоит на последнем 8. Работает только когда использую ODR. Я уверен, что причина как всегда в какой-нибудь фигне. Просто пока у меня мало опыта)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)