#1 2025-02-22 18:07:45

swq
Учасник
Зареєстрований: 2025-02-22
Повідомлень: 4

Потрібна допомога

Допоможіть будь ласка аматору .
Маю змінну byte D . Хочу привязати біти D до пінів частково порту В та D  щоб змінювать стан портів виразом
на приклад  D = B01010101 .
Моя фантазія типу
#define PORTB0  D_BIT0
#define PORTD1  D_BIT1
не працюе
Підкажить будь ласка, як привязати змінну до портів?

Неактивний

#2 2025-02-22 19:38:46

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 316

Re: Потрібна допомога

swq пише:

Маю змінну 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;

Але навіщо вам це? Яку проблему намагаєтесь вирішити такою конструкцією?

Активний

#3 2025-02-22 20:09:30

jokeer
Гість

Re: Потрібна допомога

#define це не присвоювання. Та ваша конструкція працює, але схоже, не так як вам хочеться. А що саме хочеться не зрозуміло. digitalWrite гарна абстракція, вона 100% працює. Чи вам потрібні саме бітові операції над бітами порту?

#4 2025-02-22 20:43:45

swq
Учасник
Зареєстрований: 2025-02-22
Повідомлень: 4

Re: Потрібна допомога

Хочу міняти стан пінів порту  через  змінну D. При зміні значення D  мае мінятись стан пінів порту B i D . молодші біти D Змінюють молодші біти порту В , старші біти D змінюють старші біти порту D .

Як взагалі написати змінна А дорівнюе третьому біту змінноі D ?

Неактивний

#5 2025-02-22 21:09:39

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 316

Re: Потрібна допомога

swq пише:

Хочу міняти стан пінів порту  через  змінну D. При зміні значення D  мае мінятись стан пінів порту B i D . молодші біти D Змінюють молодші біти порту В , старші біти D змінюють старші біти порту D .

Зміна стану пінів порта - це запис значень в регістр ввода-вивода, який знаходиться за певною адресою. Присвоєння значення звичайній змінній фундаментального типу (яким є unsigned char aka byte) - це запис значення в іншу адресу, де ця змінна розташована. Хоча фактичного запису в ОЗУ може і не бути, якщо компілятор так вирішить wink

Якщо ви хочете перехоплювати звернення до певних адрес ОЗУ, то на процесорі без MMU, яким є Atmega, це неможливо.

Якщо ви хочете, щоб при присвоєнні виконалась певна _дія_ (бітові операції над значенням та запис в регістр ввода-вивода), то створюйте клас і перевантажуйте оператор присвоєння, як у прикладі вище.

swq пише:

Як взагалі написати змінна А дорівнюе третьому біту змінноі 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)

Активний

#6 2025-02-22 21:19:39

jokeR
Учасник
Зареєстрований: 2024-12-12
Повідомлень: 49

Re: Потрібна допомога

Не треба робити бітову магію там де вона не потрібна. Вам, напевно, потрібно виконати якийсь ногодриг з пінами порту? Ну так зробіть функцію з промовною назвою, rotate_left() наприклад, і всередині поставте одиниці і нулі як вам потрібно. Не ускладнюйте.

Неактивний

#7 2025-02-22 21:40:05

jokeR
Учасник
Зареєстрований: 2024-12-12
Повідомлень: 49

Re: Потрібна допомога

Як взагалі написати змінна А дорівнюе третьому біту змінноі 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;

Можна ще придумати кілька способів wink

Неактивний

#8 2025-02-23 06:34:58

swq
Учасник
Зареєстрований: 2025-02-22
Повідомлень: 4

Re: Потрібна допомога

Дякую за корисні пояснення . Але я вважав що існуе тип данніх біт і можливо поставити у відповідність кожен біт  змінноі  любому біту іншоі змінноі або порту без бубна.
Якщо чесно , то я здивований .
Маю железяку з камнем 8515 та 7-сегм. індікатором, ноги якого розведені на різні порти. от і  горожу город, а він не городится.

Неактивний

#9 2025-02-23 08:37:53

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 316

Re: Потрібна допомога

swq пише:

Маю железяку з камнем 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)

Активний

#10 2025-02-24 06:47:37

swq
Учасник
Зареєстрований: 2025-02-22
Повідомлень: 4

Re: Потрібна допомога

Подякував.
"В лоб" це просто і зрозуміло . Так і зроблю.
Ще раз подякував

Остання редакція swq (2025-02-24 07:05:31)

Неактивний

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму