• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed C, AVR, Wielokrotna deklaracja funkcji, zagnierzdzone makrodefinicje

0 głosów
421 wizyt
pytanie zadane 21 października 2018 w C i C++ przez plebaniahobbitanow Początkujący (470 p.)
zamknięte 21 października 2018 przez plebaniahobbitanow

Witam ostatnio postanowiłem nauczyć się czegoś nowego i przesiadłem się z arduino na AVR (fajna zabawa :) ), ale napotkałem pewien problem. Postanowiłem napisać uniwersalne funkcje, które w argumencie biorą literę (char x) i zwracają wskaźnik na odpowiadający jej DDRx/PORTx/PINx. Problem polega na tym że funkcja z definicji ma być uniwersalna, więc i kompatybilna z wieloma architekturami AVR'ów, w tym celu w pliku util.h (którego uproszczoną formę zamieściłem nirzej ), użyłem konstrukcji makra #ifdef (np #ifdef PORTD), ale mam wrażenie że kłóci się ona z standardową makrodefinicją (która jest szersza) #ifndef NAZWA #define NAZWA i wywala mi błąd:

./main.o: In function `get_PORT(char)':
main.cpp:(.text._Z8get_PORTc+0x0): multiple definition of `get_PORT(char)'
./ds18b20.o:ds18b20.cpp:(.text._Z8get_PORTc+0x0): first defined here
/usr/lib/gcc/avr/4.9.2/../../../avr/bin/ld: Disabling relaxation: it will not work with multiple definitions

i tak dla każdej funkcji znajdującej się w tym pliku .h :/

Stąd moje pytanie czy takie zagnieżdżone makrodefinicje mają rację bytu, a jeśli nie to jak to naprawić?

Zamieszczam uproszczony kod:

main.cpp

/* main.cpp */
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <util/crc16.h>
#include <stdio.h>
#include "util.h"
#include "ds18b20.h"

void test(char port='C')
{
	volatile unsigned char *PORT=get_PORT(port);
	volatile unsigned char *DDR=get_DDR(port);
	if (PORT!=NULL)
		{
		*DDR|=(1<<3);
		*PORT|=(1<<3);
		}
}

int main()
{
test('c');
test1('C');
return 0;
}



util.h:

/* util.h */
#ifndef UTIL_H_
#define UTIL_H_
//#pragma once

volatile unsigned char *get_PORT(char port)
{
switch (port)
	{
	#ifdef PORTA
	case 'A':
	return &PORTA;
	break;
	#endif
	#ifdef PORTB
	case 'B':
	return &PORTB;
	break;
	#endif
	#ifdef PORTC
	case 'C':
	return &PORTC;
	break;
	#endif
	#ifdef PORTD
	case 'D':
	return &PORTD;
	break;
	#endif
	#ifdef PORTE
	case 'E':
	return &PORTE;
	break;
	#endif
	#ifdef PORTF
	case 'F':
	return &PORTF;
	break;
	#endif
	default:
	//return NULL;
	break;
	}
}

volatile unsigned char *get_DDR(char port)
{
switch (port)
	{
	#ifdef DDRA
	case 'A':
	return &DDRA;
	break;
	#endif
	#ifdef DDRB
	case 'B':
	return &DDRB;
	break;
	#endif
	#ifdef DDRC
	case 'C':
	return &DDRC;
	break;
	#endif
	#ifdef DDRD
	case 'D':
	return &DDRD;
	break;
	#endif
	#ifdef DDRE
	case 'E':
	return &DDRE;
	break;
	#endif
	#ifdef DDRF
	case 'F':
	return &DDRF;
	break;
	#endif
	default:
	//return NULL;
	break;
	}
}


void setPort( char port, unsigned char pin, unsigned char stan)
{
	volatile unsigned char *PORT=get_PORT(port);
	if (stan) *PORT |= _BV(pin);
	else *PORT &= ~ _BV(pin);
}

void setPort(volatile unsigned char *PORT, unsigned char pin, unsigned char stan)
{
	if (stan) *PORT |= _BV(pin);
	else *PORT &= ~ _BV(pin);
}


#define SET_IN_PIN(port,pin)	port   &= ~_BV(pin)
#define SET_OUT_PIN(port, pin)	port   |=  _BV(pin)
#endif /* UTIL_H_ */

ds18b20.h

/*  ds18b20.h */
#ifndef DS18B20_H
#define DS18B20_H

void test1(char port);

#endif

ds18b20.cpp

/* Plik ds18b20.c  */

#include <avr/io.h>
#include <util/delay.h>
#include <util/crc16.h>
#include "ds18b20.h"
#include "util.h"
void test1(char port)
{
	volatile unsigned char *PORT=get_PORT(port);
	volatile unsigned char *DDR=get_DDR(port);
	*DDR|=(1<<3);
	*PORT|=(1<<3);
}

Ps używam kompilatora C++ nie C

komentarz zamknięcia: Problem rozwiązany

1 odpowiedź

0 głosów
odpowiedź 21 października 2018 przez j23 Mędrzec (195,220 p.)
wybrane 21 października 2018 przez plebaniahobbitanow
 
Najlepsza

Przenieś implementację tych funkcji do pliku źródłowego.

 

Po co dajesz break po return w switchach?

komentarz 21 października 2018 przez plebaniahobbitanow Początkujący (470 p.)
Wolałbym tego tak nie robić, bo z tych funkcji zamierzam korzystać jeszcze w wielu plikach.

A co do breaków po returnach to faktycznie mój błąd
komentarz 21 października 2018 przez plebaniahobbitanow Początkujący (470 p.)
Przepraszam bardzo, nie zrozumiałem na początku o co ci chodziło... faktycznie przeniesienie funkcji do pliku .cpp pomogło (nie mam pojęcia czemu na początku robiłem inaczej) . Bardzo dziękuję za pomoc, temat uważam za zamknięty :)

Podobne pytania

0 głosów
1 odpowiedź 546 wizyt
pytanie zadane 21 sierpnia 2018 w Inne języki przez Storm Obywatel (1,570 p.)
0 głosów
3 odpowiedzi 788 wizyt
pytanie zadane 2 grudnia 2015 w C i C++ przez Mavimix Dyskutant (8,490 p.)
+1 głos
3 odpowiedzi 936 wizyt
pytanie zadane 14 września 2015 w C i C++ przez Mavimix Dyskutant (8,490 p.)

93,741 zapytań

142,677 odpowiedzi

323,294 komentarzy

63,323 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...