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