Операции с битовыми масками[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 или ускоряем работу платы"