Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Макроопределение
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Nixon83
Доброго времени суток помогите разобраться в коде, если не трудно объясните пожалуйста в двоичном коде!!!
CODE
//порт, к которому подключены кнопки
#define PORT_BUTTON PORTA
#define PIN_BUTTON PINA
#define DDRX_BUTTON DDRA

//номера выводов, к которым подключены кнопки
#define DOWN 4
#define UP 5
#define ENTER 6

#define MASK_BUTTONS ((1<<DOWN)|(1<<UP)|(1<<ENTER)) // обясните это выражение в двоичном коде
#define BitIsClear(reg, bit) ((reg & (1<<(bit))) == 0) // обясните это выражение в двоичном коде


//volatile unsigned char pressedKey = 0;
unsigned char comp = 0;

//_______________________________________
void BUT_Init(void) // что мы получаем здесь? Если можно тоже в двоичном коде???
{
DDRX_BUTTON &= ~(MASK_BUTTONS);
PORT_BUTTON |= MASK_BUTTONS;
}

//_______________________________________
//#pragma inline = forced
void BUT_Debrief(void)
{
unsigned char key = 0;

//последовательный опрос выводов мк
if (BitIsClear(PIN_BUTTON, UP))
key = KEY_UP;
else if (BitIsClear(PIN_BUTTON, DOWN))
key = KEY_DOWN;
else if (BitIsClear(PIN_BUTTON, ENTER))
key = KEY_ENTER;
else {
key = KEY_NULL;
}
Genius1
1) #define MASK_BUTTONS ((1<<DOWN)|(1<<UP)|(1<<ENTER)) // обясните это выражение в двоичном коде
(1<<DOWN) - сдвиг 1 влево на 4. Т.е. из 0b00000001 получаем 0b00010000
(1<<UP) - сдвиг 1 влево на 5. Т.е. из 0b00000001 получаем 0b00100000
(1<<ENTER) - сдвиг 1 влево на 6. Т.е. из 0b00000001 получаем 0b01000000

((1<<DOWN)|(1<<UP)|(1<<ENTER)) - побитная операция или полученных выше результатов.
Т.е. 0b00010000 ИЛИ 0b00100000 ИЛИ 0b01000000 = 0b01110000
Таким образом, вместо MASK_BUTTONS в программе будет подставляться число 0b01110000

2) #define BitIsClear(reg, bit) ((reg & (1<<(bit))) == 0)
Это проверка на равенство нулю выражения reg & (1<<(bit)). Величины reg и bit задаются в программе. Сначала мы сдвигаем 1 влево bit раз и с полученным результатом производим операцию побитовое И с числом reg. Для примера возьмем reg = 0b01000000, bit = 5
Сдвигаем 1 влево на 5(bit) = 0b00100000
Побитовове И = 0b01000000 & 0b00100000 = 0. В этом случае общий результат выражения ((reg & (1<<(bit))) == 0) будет ИСТИНА(=1)


Палыч
Цитата(Nixon83 @ Oct 19 2011, 11:52) *
#define MASK_BUTTONS ((1<<DOWN)|(1<<UP)|(1<<ENTER)) // обясните это выражение в двоичном коде
Не понимаю, что значит "объяснить в двоичном коде"...
Выражение вида (1<<X) в языке Си означает сдвиг единицы влево на Х разрядов. Т.е. получаем результат: единица в разряде Х, а остальные разряды - ноль.
Например, (1<<DOWN). Выше определено, что DOWN то же самое, что и 4. Т.е. это то же сомое, что (1 << 4), или единица сдвинутая влево на четыре разряда (00010000).
Аналогично с остальными частями выражения.
Все три части побитово складываются (побитовое ИЛИ), и получаем результат, где в разрядах 4,5 и 6 единицы, а в остальных - нули (01110000).

Цитата(Nixon83 @ Oct 19 2011, 11:52) *
#define BitIsClear(reg, bit) ((reg & (1<<(bit))) == 0) // обясните это выражение в двоичном коде
Выше было объяснено (1 << (bit) ). Затем reg побитово умножается (побитовое И) на число с единицей в бите bit и остальными нулями, и получаем результат: в бите bit тот же бит, что был в reg, а остальные биты - нули. Это число сравнивается с нулём и получаем "истина/ложь". Таким образом BitIsClear(reg, bit) - истина, если бит bit числа reg равен нулю, и ложь в противном случае.


Цитата(Nixon83 @ Oct 19 2011, 11:52) *
void BUT_Init(void) // что мы получаем здесь? Если можно тоже в двоичном коде???
{
DDRX_BUTTON &= ~(MASK_BUTTONS);
PORT_BUTTON |= MASK_BUTTONS;
}
Выражение типа A &= B, эквивалентно А= А & B. Операция & - побитовое И, ~ - побитовая инверсия (т.е. 0 -> 1, 1 -> 0). Первое выражение очищает (сбрасывает в ноль) все биты DDRX_BUTTON для которых в MASK_BUTTONS установлены единицы (т.е. биты 4,5,6), остальные биты DDRX_BUTTON остаются неизменными.
Второе выражение, напротив, в PORT_BUTTON устанавливает биты в единицу, для которых в MASK_BUTTONS установлены единицы (т.е. биты 4,5,6), остальные биты - остаются неизменными

Nixon83
Понятно а как дальше работает эта схема, для чего вообще нужна маска????
void BUT_Init(void) // что мы получаем здесь? Если можно тоже в двоичном коде???
{
DDRX_BUTTON &= ~(MASK_BUTTONS);
PORT_BUTTON |= MASK_BUTTONS;
}
Genius1
3) void BUT_Init(void)

1. DDRX_BUTTON &= ~(MASK_BUTTONS);
тоже что и выражение DDRX_BUTTON =DDRX_BUTTON & (~(MASK_BUTTONS));

~ - побитная инверсия. Т.е. сначала инвертируем MASK_BUTTONS (а оно = 0b01110000). ~0b01110000 = 0b10001111
Проводим операцию ПОБИТОВОЕ И с DDRX_BUTTON и сохраняем результат в DDRX_BUTTON.
Т.е. DDRA = DDRA & 0b10001111. Здесь результат зависит от значения регистра DDRA

2.PORT_BUTTON |= MASK_BUTTONS;
тоже что и выражение PORT_BUTTON = PORT_BUTTON | MASK_BUTTONS;

Т.е. PORTA = PORTA | 0b10001111


Цитата(Nixon83 @ Oct 19 2011, 12:54) *
Понятно а как дальше работает эта схема, для чего вообще нужна маска????
void BUT_Init(void) // что мы получаем здесь? Если можно тоже в двоичном коде???
{
DDRX_BUTTON &= ~(MASK_BUTTONS);
PORT_BUTTON |= MASK_BUTTONS;
}


с авр не работал, но по логике:
С помощью маски устанавливаешь в регистре DDRA 3 ножки PORTА (4,5,6) на вход для анализа состояния кнопок.
В регистре PORTA устанавливаешь соответствующие биты в 1.
Nixon83
А если без маски сразу вычислить и записать в шеснадцатеричное число ничего не изменится????
DDRX_BUTTON = шеснадцатеричное число
PORT_BUTTON = шеснадцатеричное число
Палыч
Цитата(Nixon83 @ Oct 19 2011, 13:06) *
А если без маски сразу вычислить и записать в шеснадцатеричное число ничего не изменится????
DDRX_BUTTON = шеснадцатеричное число
PORT_BUTTON = шеснадцатеричное число
Возможно, изменится... Выражения, что были изначально, не затрагивают (не изменяют) значений битов, с номерами отличных от 4,5 и 6. выражения типа DDRX_BUTTON = шеснадцатеричное число установят все биты регистра DDRX_BUTTON.
Nixon83
Спасибо огромное за помощь!!! Теперь все понятно cheers.gif cheers.gif
Alex11
Изменится. Операции &= и |= отличаются от =. Первые изменяет только указанные биты, вторая - все.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.