• 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

VPS Starter Arubacloud
0 głosów
248 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 (194,920 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ź 380 wizyt
pytanie zadane 21 sierpnia 2018 w Inne języki przez Storm Obywatel (1,570 p.)
0 głosów
3 odpowiedzi 460 wizyt
pytanie zadane 2 grudnia 2015 w C i C++ przez Mavimix Dyskutant (8,390 p.)
+1 głos
3 odpowiedzi 740 wizyt
pytanie zadane 14 września 2015 w C i C++ przez Mavimix Dyskutant (8,390 p.)

92,453 zapytań

141,262 odpowiedzi

319,088 komentarzy

61,854 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.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...