Ви не увійшли.
Сторінки 1
Допоможіть будь ласка аматору .
Маю змінну byte D . Хочу привязати біти D до пінів частково порту В та D щоб змінювать стан портів виразом
на приклад D = B01010101 .
Моя фантазія типу
#define PORTB0 D_BIT0
#define PORTD1 D_BIT1
не працюе
Підкажить будь ласка, як привязати змінну до портів?
Неактивний
Маю змінну byte D . Хочу привязати біти D до пінів частково порту В та D щоб змінювать стан портів виразом
на приклад D = B01010101 .
Що значить "привʼятази біти"? Ви хочете, щоби при присвоєнні значення змінній виконувався певний код? Зі змінною фундаментального типу так не вийде. Можете створити клас із перевантаженим оператором присвоєння, наприклад:
struct composite_port
{
unsigned char operator=(unsigned char v)
{
PORTB = (PORTB & ~0x20) | ((v << 5) & 0x20); // 0-й біт значення у 5-й біт PORTB
PORTD = (PORTD & ~0x08) | ((v << 2) & 0x08); // 1-й біт значення у 3-й біт PORTD
return v;
}
};
Потім
composite_port D;
D = 0x3;
або просто
composite_port{} = 0x3;
Але навіщо вам це? Яку проблему намагаєтесь вирішити такою конструкцією?
Неактивний
#define це не присвоювання. Та ваша конструкція працює, але схоже, не так як вам хочеться. А що саме хочеться не зрозуміло. digitalWrite гарна абстракція, вона 100% працює. Чи вам потрібні саме бітові операції над бітами порту?
Хочу міняти стан пінів порту через змінну D. При зміні значення D мае мінятись стан пінів порту B i D . молодші біти D Змінюють молодші біти порту В , старші біти D змінюють старші біти порту D .
Як взагалі написати змінна А дорівнюе третьому біту змінноі D ?
Неактивний
Хочу міняти стан пінів порту через змінну D. При зміні значення D мае мінятись стан пінів порту B i D . молодші біти D Змінюють молодші біти порту В , старші біти D змінюють старші біти порту D .
Зміна стану пінів порта - це запис значень в регістр ввода-вивода, який знаходиться за певною адресою. Присвоєння значення звичайній змінній фундаментального типу (яким є unsigned char aka byte) - це запис значення в іншу адресу, де ця змінна розташована. Хоча фактичного запису в ОЗУ може і не бути, якщо компілятор так вирішить
Якщо ви хочете перехоплювати звернення до певних адрес ОЗУ, то на процесорі без MMU, яким є Atmega, це неможливо.
Якщо ви хочете, щоб при присвоєнні виконалась певна _дія_ (бітові операції над значенням та запис в регістр ввода-вивода), то створюйте клас і перевантажуйте оператор присвоєння, як у прикладі вище.
Як взагалі написати змінна А дорівнюе третьому біту змінноі D ?
A = (D >> 3) & 1;
Також можна:
A = (D & 8) >> 3;
що можна записати як
A = (D & (1u << 3)) >> 3;
Загальний випадок для будь-якого біта n:
A = (D >> n) & 1;
Остання редакція dimich (2025-02-22 21:27:38)
Неактивний
Не треба робити бітову магію там де вона не потрібна. Вам, напевно, потрібно виконати якийсь ногодриг з пінами порту? Ну так зробіть функцію з промовною назвою, rotate_left() наприклад, і всередині поставте одиниці і нулі як вам потрібно. Не ускладнюйте.
Неактивний
Як взагалі написати змінна А дорівнюе третьому біту змінноі D ?
По ардуінівськи:
є спеціальні функції
https://doc.arduino.ua/ru/prog/BitRead
По avr-івськи
Є макрос
#define _BV(bit) (1 << (bit))
десь так тоді
// якщо вам конче потрібно отримати саме 1 або 0
uint8_t A = D & _BV(bit) ? 1 : 0;
// якщо вас задовольняє те що змінна просто !=0
uint8_t A = D & _BV(bit);
А то можна і так, якщо хочеться байти економити
#define BIT0 1
#define BIT1 (1<<1)
#define BIT2 (1<<2)
#define BIT3 (1<<3)
#define BIT4 (1<<4)
#define BIT5 (1<<5)
#define BIT6 (1<<6)
#define BIT7 (1<<7)
uint8_t A = D & BIT7;
Можна ще придумати кілька способів
Неактивний
Дякую за корисні пояснення . Але я вважав що існуе тип данніх біт і можливо поставити у відповідність кожен біт змінноі любому біту іншоі змінноі або порту без бубна.
Якщо чесно , то я здивований .
Маю железяку з камнем 8515 та 7-сегм. індікатором, ноги якого розведені на різні порти. от і горожу город, а він не городится.
Неактивний
Маю железяку з камнем 8515 та 7-сегм. індікатором, ноги якого розведені на різні порти. от і горожу город, а він не городится.
Класичний приклад проблеми XY. "Привʼязувати біти змінної" для цієї задачі зовсім не потрібно.
Навіщо вам змінна? Напишіть просту функцію, яка розпихує біти в різні порти.
Наприклад, нехай індикатор підʼєднаний наступним чином:
A - PORTB.0
B - PORTB.1
C - PORTB.2
D - PORTD.0
E - PORTD.1
F - PORTD.3
G - PORTD.2
У вас є значення, в якого біт 0 відповідає сегменту A, біт 1 - сегменту B і т.п.
Тоді просте рішення "в лоб":
void display(byte v)
{
PORTB = (v & 0b0000111) | (PORTB & ~0b0000111);
PORTD = ((v & 0b0011000) >> 3) |
((v & 0b0100000) >> 2) |
((v & 0b1000000) >> 4) | (PORTD & ~0b0001111);
}
Потім викликаєте цю функцію. Наприклад, цифрі "4" відповідає значення 0x66:
display(0x66);
// або, те ж саме
display(0b1100110);
Якщо потрібно мінімізувати затримку між оновленням сегментів, тоді спочатку обчислюєте значення, потім їх записуєте в регістри:
void display(byte v)
{
byte portb = (v & 0b0000111) | (PORTB & ~0b0000111);
byte portd = ((v & 0b0011000) >> 3) |
((v & 0b0100000) >> 2) |
((v & 0b1000000) >> 4) | (PORTD & ~0b0001111);
PORTB = portb;
PORTD = portd;
}
Якщо сегменти вмикаються нулем (спільний анод), тоді просто передаєте інвертоване значення.
Якщо у вас труднощі з бітовими операціями, то напишіть який сегмент до якого піна підключений, допоможемо.
Також можна написати більш універсальну функцію, для якої мапінг сегментів на піни задається у вигляді таблиці.
EDIT: виправив бітові маски та вирівняв відступи для наглядності.
Остання редакція dimich (2025-02-23 10:56:36)
Неактивний
Сторінки 1