Definiowane portów/flag w C

Cześć,

Może nie do końca ta grupa ale wielu z Was pisze w C i może mi podpowie :)

Korzystam z takich makr, które pracują na bitach, np.:

#define setbit(VAR,Place) ( (VAR) |= (uint8_t)((uint8_t)1<<(uint8_t)(Place)) )

w programie mam zdefiniowane np.:

#define PORT_LED GPIOA #define LED_R 0

uint8_t main_flags1, main_flags2, main_flags3; #define FLAGA1 0 #define FLAGA2 0

i później takie wykorzystanie np.:

setbit(PORT_LED, LED_R); setbit(main_flags, FLAGA1); setbit(main_flags2, FLAGA2);

Przy portach to jeszcze nie jest problemu ale przy flagach trzeba ręcznie panować nad tym w której zmiennej leży jaka flaga. Już kilka razy szukałem przez to błędów.

Jak zrobić, żeby odwołanie do flagi było jednoznaczne, chodziło by mi o coś takiego (co nie działa przez ten przecinek):

#define F_LED_R PORT_LED,LED_R

setbit(F_LED_R);

Wtedy w programie nie muszę się już zastanawiać gdzie leży jaki bit.

Zawsze tak pisałem w asm, a teraz mi tego brakuje :)

Pozdrawiam,

Reply to
sword
Loading thread data ...

#define led_set() set_bit(PORT_LED, LED_R)

Reply to
Adam Wysocki

Ja tych makr mam więcej, to był tylko przykład z 'setbit'. Chodzi o to, żeby w dowolnym makrze można było podstawić port lub flagę nie generując przy tym osobnego makra dla każdego przypadku, np.:

setbit(F_LED_R); clrbit(F_LED_R); chgbit(F_LED_R); if (valbit(F_LED_R))

Reply to
sword

a czemu upierasz się przy makrach? Nie możesz dać inline function?

Waldek

Reply to
Waldemar

Nie musisz jesli użyjesz C++. Nie mam stosownego przykładu pod reką w tej chwili ale kilka lat temu mając ochote ukręcić leb idiotom od definicji rejestrow SAM7 narzeźbilem coś takiego i "sprzedałem" kod. Napisanie tego na nowo jest w zasadzie osiągalne.

Oczywiście od razu informacja dla wszystkich co podskoczyli na hasło C++

- ten mechanizm nie genaruje ani bajta więcej w kodzie. To metaprogramowanie na szablonach, operatorach itd, na końcu wychodzi to samo tylko pewne i bez głupich pomyłek i wygląda prawie identycznie.

Reply to
Sebastian Biały

Hmm, mogę dać inline ale wydaje mi się, że jestem w tym samym punkcie co z makrami.

static inline void setbit (u8 port, u8 pin) { port |= 1<<pin; }

No i co dalej? Chciałbym ją tak samo wywołać, np.:

setbit(F_LED)

Reply to
sword

Ja mam C na sztywno w tym projekcie i nie dam rady przeskoczyć na C++.

Reply to
sword

Z powodu jakiego? Technicznego czy białkowego?

Reply to
Sebastian Biały

sword snipped-for-privacy@poczta.onet.pl> napisał(a):

Musisz stworzyć coś, co oprócz bitu będzie nisło też informację o porcie, np.

#include <stdio.h>

#define PINA1 0x01 #define PINA2 0x02 #define PINB2 0x02 #define PINB3 0x03

#define F_PINA1 (0x0000 | PINA1) #define F_PINA2 (0x0000 | PINA2) #define F_PINB2 (0x0100 | PINB2) #define F_PINB3 (0x0100 | PINB3)

int porta = 0, portb = 0;

void setpin(unsigned int fpin);

int main() { setpin(F_PINA1); setpin(F_PINA2); setpin(F_PINB2); setpin(F_PINB3); printf("%x %x\n", porta, portb); return 0; }

void setpin(unsigned int fpin){ int port = fpin >> 8; int pin = 0x00ff & fpin; switch(port) { case 0x00: porta |= 1 << pin; break; case 0x01: portb |= 1 << pin; break; } }

Reply to
Grzegorz Niemirowski

Czyli białkowy. Nadzieja w tym że problemy białkowe czasami rozwiązują się szybciej niż komercyjne kompilatory dostają wsparcie C++, ale to rodzaj czarnego humoru.

To nie pomogę bo każde rozwiązanie w C będzie gówniane.

Reply to
Sebastian Biały

W dniu 19.10.2017 o 13:01, sword pisze:

Problem moim zdaniem nie leży ani w wybranym w języku programowania, ani w sposobie implementacji tylko "wyżej" - zagadnienie nazywa się semantyka.

Rozwiązanie banalne - stosuj nazwy zmiennych, funkcji, makr i definicji, które będą JEDNOZNACZNE i SAMOKOMENTUJĄCE SIĘ. Dobrym przykładem mogą być biblioteki dostarczane przez ST do ich procków, bo tam przyjęto regułę, że jeśli rejestr nazywa się REG_BLA_BLA to bity w nim nazywają się REG_BLA_BLA_ENABLE_COŚTAM, REG_BLA_BLA_DISABLE_INNE_COŚTAM itd.

Reply to
Jakub Rakus

Dnia Thu, 19 Oct 2017 21:38:58 +0200, Grzegorz Niemirowski napisał(a):

[...]

A na bezczelnego ?

#define F_LED GPIO,7

... setbit(F_LED) ...

formatting link

J.

Reply to
J.F.

Do takiego zadzialania potrzeba "podwojnego makra":

#define _test_set_bit(port,pin) do{ (port)->PDOR |=(1<<(pin)); }while(0) #define test_set_bit(x) _test_set_bit(x) #define LEG_G_7 GPIOB,7

i wtedy test_set_bit(LEG_G_7); preprocesor rozwinie poprawnie: do{ (((GPIO_Type *)(0x400FF040u)))->PDOR |=(1<<(7)); }while(0);

Przy pojedynczym makro (jak pierwsze) arm-none-eabi-gcc zglasza blad ze makro ma miec 2 parametry a przekazany jest tylko 1.

$ arm-none-eabi-gcc -E -mcpu=cortex-m0plus makro.c -o makro2.lst makro.c:14:23: error: macro "test_set_bit" requires 2 arguments, but only 1 given test_set_bit(LEG_G_7);

Marcin

Reply to
Marcin

W dniu 2017-10-19 o 13:01, sword pisze:

Ja to robię tak wpierw definicje makr #define SET_(p, m) (p |= (1 << (m))) #define CLR_(p, m) (p &= ~(1 << (m))) #define TEST_(p,m) (p & (1 << (m))) #define TOGGLE_(p, m) (p ^= (1 << (m)))

#define SET(x) SET_(x) #define CLR(x) CLR_(x) #define TEST(x) TEST_(x) #define TOGGLE(x) TOGGLE_(x)

potem właściwa konfiguracja

#define ZIELONA PORTB,1

i potem w programie

SET(ZIELONA);

Reply to
Janusz

Fajny przykład ale do pracy z bitami to za dużo kodu.

Reply to
sword

Niekoniecznie.

Nie wiem na jaką platformę piszesz, ale na AVR port nie ma typu u8 (uint8).

Spróbuj tak:

[gof@pi /tmp]$ cat test.c #include <inttypes.h>

#include <avr/io.h>

// bez nawiasów, żeby nie rozwinęło się tylko do jednego argumentu #define MAKE(port, bit) &port, _BV(bit)

// podejście z MAKE #define LED1 MAKE(PORTB, 3) #define BUZZER1 MAKE(PORTC, 0)

// podejście bez MAKE - bez nawiasów! #define LED2 &PORTB, _BV(3) #define BUZZER2 &PORTC, _BV(0)

static inline void setbit(volatile uint8_t *port, uint8_t mask) { *port |= mask; }

int main(void) { setbit(LED1); setbit(BUZZER1); setbit(LED2); setbit(BUZZER2);

return 0; } [gof@pi /tmp]$ avr-gcc -mmcu=atmega8 -Wall -Wextra test.c [gof@pi /tmp]$

Reply to
Adam Wysocki

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.