Операции с битовыми масками[1]
Для того чтобы все-таки максимально обезопасить себя от неприятностей при использовании этого метода, можно использовать:
- для включения (HIGH) бита регистра порта — операцию побитового ИЛИ — PORTB |= B00100000; (при побитовом ИЛИ ноль не меняет значения бита, а 1 — присваивает биту значение единицы),
- для выключения (LOW) бита регистра порта — операцию побитового И — PORTB &= ~B00100000; (при побитовом И единица не меняет значения бита, а 0 — присваивает биту нулевое значение).
Маску в большинстве случаев удобнее задавать битовым сдвигом вида byte mask = (1 << номер_бита). Таким образом приведенные выше примеры приобретут вид:
PORTB |= (1 << 5);
PORTB &= ~ (1 << 5);
Для присвоения значения сразу нескольким битам с использованием операции битового сдвига можно воспользоваться логическим OR (|):
PORTB |= (1 << 5) | (1 << 2) | (1 << 0); // Присвоить значения 5, 2 и 0 битам
PORTB &= ~ ((1 << 5) | (1 << 2) | (1 << 0)); // Присвоить значения 5, 2 и 0 битам
 
Код для управления сервомоторами с поиощью двух джойстиков
#include <Servo.h>
int X = 0;
int Y = 0;
int Z = 0;
int U = 0;
Servo servo_0;
Servo servo_1;
Servo servo_2;
Servo servo_3;
void setup()
{
  DDRB = 0xFF;
  DDRC = 0x00; 
  ADCSRA = 0;             // Сбрасываем регистр ADCSRA
  ADCSRB = 0;             // Сбрасываем регистр ADCSRB
  ADMUX |= (1 << REFS0);  // Задаем ИОН
  
 ADCSRA |= (1 << ADPS2); //Биту ADPS2 присваиваем единицу - коэффициент деления 16
  ADCSRA |= (1 << ADEN)|(1 << ADPS2)|(1 << ADPS1)|(1 << ADPS0);
 ADMUX |= (0 << REFS1)|(0 << REFS0)|(0 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3); 
  servo_0.attach(8);
  servo_1.attach(9);
  servo_2.attach(10);
  servo_3.attach(11);
}
void loop()
{
L0:;
ADCSRA |= (1 << ADSC);  // Начинаем преобразование
L1:; 
if((ADCSRA & (1 << ADIF)) == 0) goto L1;  
int XX = (ADCL|ADCH << 8); // Считываем полученное значение
X = map(XX,0,1023,0,180);
servo_0.write(X);
ADMUX |= (1 << MUX0);   //Переключаемся на А1
ADCSRA |= (1 << ADSC);  // Начинаем преобразование 
L2:; 
if((ADCSRA & (1 << ADIF)) == 0) goto L2;  
int YY = (ADCL|ADCH << 8); // Считываем полученное значение
Y = map(YY,0,1023,0,180);
servo_1.write(Y);
ADMUX &= ~(1 << MUX0);
ADMUX |= (1 << MUX1);//Переключаемся на А2
ADCSRA |= (1 << ADSC);  // Начинаем преобразование
L3:; 
if((ADCSRA & (1 << ADIF)) == 0) goto L3;  
int ZZ = (ADCL|ADCH << 8); // Считываем полученное значение
Z = map(ZZ,0,1023,0,180);
servo_2.write(Z);
ADMUX |= (1 << MUX0);   //Переключаемся на А3
ADCSRA |= (1 << ADSC);  // Начинаем преобразование 
L4:; 
if((ADCSRA & (1 << ADIF)) == 0) goto L4;  
int UU = (ADCL|ADCH << 8); // Считываем полученное значение
U = map(UU,0,1023,0,180);
servo_3.write(U);
ADMUX &= ~(1 << MUX0); //Переключаемся на А0
ADMUX &= ~(1 << MUX1);
delay(10);
goto L0;
}
Оптимизированный вариант управления
[1]Кравченко Виктор "Тюнинг Arduino или ускоряем работу платы"
