Смещение бита из регистра с >>1

#c #bit-shift #atmega

#c #смещение бита #atmega

Вопрос:

Я использую Atmega 16 на плате программатора STK500. я пытаюсь включить светодиоды на DDRA, начиная с Led0 с 0b00000001 до Led7 с 0b1000000. Кажется, что я выталкиваю установленный бит из регистра с помощью >> сдвига. Не следует ли просто переместить 1 вправо? У меня есть этот фрагмент

 # define F_CPU 8000000UL
#include <util/delay.h>
#include <avr/io.h>

int main(void)
{
    DDRA=0xFF;
    char leds=0x01;
    while(1)
    {
        if (leds==0x01)
        {
            for (int i=0;i<8;i  )
            {
                PORTA=~leds;
                leds=leds<<1;
                _delay_ms(300);
            }
        }
        else
        for (int x=0;x<8;x  )
        {
            leds=leds>>1;
            PORTA=~leds;
            _delay_ms(300);
        }

    }
}
  

похоже, что эта часть

 for (int x=0;x<8;x  )
            {
                leds=leds>>1;
                PORTA=~leds;
                _delay_ms(300);
            }
  

выталкивает бит из регистра, но этого не должно быть. я совершаю ошибку?

Комментарии:

1. Какой дисплей вы получаете и какой дисплей вы ожидаете?

2. Прежде чем пытаться заставить это работать на микроконтроллере, попробуйте это на своем компьютере, просто распечатывая биты leds на каждой итерации. Вы быстро увидите, насколько ваши ожидаемые результаты отличаются от того, что на самом деле делает математика.

3. @Sneftel Нет. Просто проверьте фактическое значение регистра с помощью встроенного отладчика…

4. подсказка: каково значение светодиодов после первого раза с помощью инструкции while. Как это будет обработано во второй раз в цикле while? И, насколько я вижу, else выполняется во второй раз.

5. Здесь у вас есть некоторые ошибки, которые не обязательно связаны с проблемой. Ошибка 1) Вы никогда не должны использовать char для 8-битной арифметики, поскольку она имеет определяемую реализацией подписанность. Используйте uint8_t вместо этого. Ошибка 2) Ваш MCU содержит 16-битные целые числа, и все типы малых целых чисел будут неявно переведены в signed int . В случае, если leds для индикатора MSB установлено значение 0x80, вы вызываете неопределенное поведение путем сдвига leds в 8 раз влево. Вы вызываете поведение, определяемое реализацией, путем сдвига leds 8 раз вправо. Всегда приводите leds к uint16_t перед сдвигом.

Ответ №1:

Вы смещаете 1 в первом цикле. И вы не видите, потому что вы обновляете отображение перед сдвигом.

В конце итерации с i = 0 значения leds будут равны 0x02. Итак, следуя этой логике, вы получаете:

 i, leds (end of the loop)
0, 0x02
1, 0x04
2, 0x08
3, 0x10
4, 0x20
5, 0x40
6, 0x80
7, 0x00
  

Комментарии:

1. Да, я надеялся, что OP сможет решить это самостоятельно.

2. да, моей проблемой было обновление дисплея перед переключением. я предположил, что светодиоды будут указывать, какой бит установлен.

3. @barny, извините, я не видел вашего комментария.