Объясните как это работает

Тема в разделе "Arduino & Shields", создана пользователем Patriot, 10 окт 2015.

  1. Patriot

    Patriot Нерд

    Ребята, привет! Кто сможет объяснить доступным языком как это работает? Arduino Mega 2560

    Код (C++):
    #define EMASK         0x38
    #define GMASK         0x20
    #define HMASK         0x78
    #define write_8(x)   {  PORTH &= ~HMASK; PORTG &= ~GMASK; PORTE &= ~EMASK; \
                            PORTH |= (((x) & (3<<0)) << 5); \
                            PORTE |= (((x) & (3<<2)) << 2); \
                            PORTG |= (((x) & (1<<4)) << 1); \
                            PORTE |= (((x) & (1<<5)) >> 2); \
                            PORTH |= (((x) & (3<<6)) >> 3); \
                         }

     
    Объявляется функция write_8, которая принимает некое значение и по нему выставляет пины в хай или лоу. PORTx - это некая группа пинов, верно? А вот дальше подробней расскажите что происходит. Что за маска, как она применяется, и что за сдвиги и вычисления делаются. Мне хочется в этом разобраться что бы написать аналогичную функцию с аналогичными портами но для Arduino Due. На ней этих портов нет, там к ним доступ происходит по другому.
     
    egordorichev нравится это.
  2. ИгорьК

    ИгорьК Гуру

    Последнее редактирование: 10 окт 2015
  3. Patriot

    Patriot Нерд

    Справился! Все работает:) Но может кто подскажет, можно ли это еще сильнее оптимизировать?
    Код (C++):
        #define B_MASK  0b000010000000000000000000000000;
        #define C_MASK  0b010111111000000000000000000000;
     
        #define write_8(x)   {  PIOC->PIO_CODR = C_MASK; PIOB->PIO_CODR = B_MASK; \
                                if((0x01 & ((x >> 2)))) PIOB->PIO_SODR = 1<<25; \
                                if((0x01 & ((x >> 3)))) PIOC->PIO_SODR = 1<<28; \
                                if((0x01 & ((x >> 4)))) PIOC->PIO_SODR = 1<<26; \
                                if((0x01 & ((x >> 5)))) PIOC->PIO_SODR = 1<<25; \
                                if((0x01 & ((x >> 6)))) PIOC->PIO_SODR = 1<<24; \
                                if((0x01 & ((x >> 7)))) PIOC->PIO_SODR = 1<<23; \
                                if((0x01 & ((x >> 0)))) PIOC->PIO_SODR = 1<<22; \
                                if((0x01 & ((x >> 1)))) PIOC->PIO_SODR = 1<<21; \
        }

     
    Пробовал так:

    Код (C++):
       
    #define B_MASK  0b000010000000000000000000000000;
        #define C_MASK  0b010111111000000000000000000000;
     
        #define write_8(x)   {  PIOC->PIO_CODR = C_MASK; PIOB->PIO_CODR = B_MASK; \
                                if((0x01 & ((x >> 2)))) PIOB->PIO_SODR = 1<<25; \
                                if((0x01 & ((x >> 3)))) PIOC->PIO_SODR = 1<<28; \
    PIOC->PIO = (x>>4<<23) ^ C_MASK; \
                                if((0x01 & ((x >> 0)))) PIOC->PIO_SODR = 1<<22; \
                                if((0x01 & ((x >> 1)))) PIOC->PIO_SODR = 1<<21; \
        }

     
    Не завелось. :(