Jak přepsat #define kdekoli v programu??

V programu mám definovaný pin, na kterém bude připojený teploměr:

//ds18b20.h//
//setup connection
#define DS18B20_DQ PA0

Potřeboval bych ale k AVR připojit i další dva teploměry,
nejjednoušší způsob by byl přepsat v main.c tyto definice, aby to fungovalo takhle:

#define DS18B20_DQ PA0
změř t0
#define DS18B20_DQ PA1
změř t1
#define DS18B20_DQ PA2
změř t2

Existuje způsob, jak to udělat??

Díky!!

#define DS18B20_DQ PA0 změř t0 #undefine DS18B20_DQ #define DS18B20_DQ PA1 změř t1 #undefine DS18B20_DQ #define DS18B20_DQ PA2 změř t2 #undefine DS18B20_DQ

Platím ovšem, že VEŠKERÝ kód týkající se daného čidla musí být mezi #define a #undefine, protože #define a #undefine mění hodnotu pro PŘEKLADAČ a NE PRO PROGRAM !!! To znamená, že funkci “změř” musí mít napsanou 3x a ne ji 3x volat.

Nebo připoj všechny čidla na 1 pin a adresuj je. 1-wire sběrnice to umí…

Nedoporučuji. Lépe pomocí proměnných.

to by vypadalo jak??

Ikdyž přímo do ds18b20.c napíšu:

void zmert1(void){
double d1 = 0;
char printbuff1[10];

#define DS18B20_DQ PA0
d1 = ds18b20_gettemp();
dtostrf(d1, 10, 3, printbuff1);
lcd_clrscr();
lcd_gotoxy(0, 0); //znak,radek
lcd_puts(printbuff1);
lcd_putc(0b11011111); //°
lcd_puts("C");
#undef DS18B20_DQ

}

, tak mi Atel studio hlásí "DS18B20_DQ undeclared (first use in this function)

Protože ve funkci ds18b20_gettemp(); nemáš DS18B20_DQ nadefinováno. Jak jsem psal výše - ds18b20_gettemp(); musíš mít mezi #define a #undefine FYZICKY VE ZDROJOVÉM, KÓDU NAPSANOU !!!

!!! FUNKCI - NE JEJÍ VOLÁNÍ !!!

Ale jak to teda mám udělat??
…potřebuju #define DS18B20_DQ měnit z main.c…

Mám obavu, že budeš muset volání funkce upravit z

teplota = ds18b20_gettemp();

na

teplota = ds18b20_gettemp(cislo_cidla);

a funkci vlastní pak na

[code]int ds18b20_gettemp(char cidlo)
{
switch (cidlo)
{
#define DS18B20_DQ PA0
case 0: <obsluha čidla>;
return <teplota čidla>;
break;
#undef DS18B20_DQ
#define DS18B20_DQ PA1
case 1: <obsluha čidla>;
return <teplota čidla>;
break;

#undef DS18B20_DQ
#define DS18B20_DQ PA2
case 2: <obsluha čidla>;
return <teplota čidla>;
break;
#undef DS18B20_DQ

        default: return <nesmyslná hodnota>;
    }

}
[/code]

Obsluhu čidla pak stačí napsat stylem

a=DS18B20_DQ if (DS18B20_DQ== b) atd.

Jen jí ještě musíš pomocí CTRL-C a CTRL-V zkopírovat do všech case - tohle by mělo fungovat.

Možná by šlo kód napsat jako makro :

.macro ObsluhaTeplomeru a=DS18B20_DQ if (DS18B20_DQ== b) atd. .endm

a funkci pak

[code]int ds18b20_gettemp(char cidlo)
{
switch (cidlo)
{
#define DS18B20_DQ PA0
case 0: ObsluhaTeplomeru;
return <teplota čidla>;
break;
#undef DS18B20_DQ
#define DS18B20_DQ PA1
case 1: ObsluhaTeplomeru;
return <teplota čidla>;
break;

#undef DS18B20_DQ
#define DS18B20_DQ PA2
case 2: ObsluhaTeplomeru;
return <teplota čidla>;
break;
#undef DS18B20_DQ

        default: return <nesmyslná hodnota>;
    }

}
[/code]

Ale tím si nejsem 100% jistý. Výhodou by byla jednodušší úprava programu pro čidlo - nemusel bys to fyzicky rozkopírovávat. Jenže teďka nemám u sebe AS a nemůžu tuhle variantu překladu vyzkoušet.

…neorzumím té obsluze…myslel jsem si, že by stačilo gettemp(1);//nebo 2/3

Každopádně to nejde použít!!

Takhle vypadá funkce pro zjištění teploty: (ty podfunkce jsou dost dlouhý…tak by to vypadalo asi dost katastrofálně + počet řádků by se ztrojnásobil…)

[code]
double ds18b20_gettemp() {

#define DS18B20_DQ PA0

uint8_t temperature_l;
uint8_t temperature_h;
double retd = 0;

#if DS18B20_STOPINTERRUPTONREAD == 1
cli();
#endif

ds18b20_reset(); //reset
ds18b20_writebyte(DS18B20_CMD_SKIPROM); //skip ROM
ds18b20_writebyte(DS18B20_CMD_CONVERTTEMP); //start temperature conversion

while(!ds18b20_readbit()); //wait until conversion is complete

ds18b20_reset(); //reset
ds18b20_writebyte(DS18B20_CMD_SKIPROM); //skip ROM
ds18b20_writebyte(DS18B20_CMD_RSCRATCHPAD); //read scratchpad

//read 2 byte from scratchpad
temperature_l = ds18b20_readbyte();
temperature_h = ds18b20_readbyte();

#if DS18B20_STOPINTERRUPTONREAD == 1
sei();
#endif

//convert the 12 bit value obtained
retd = ( ( temperature_h << 8 ) + temperature_l ) * 0.0625;

return retd;

}[/code]

Zbývá teda jenom druhá možnost…a té moc neorzumím

Vždyť v tom kódu DS18B20_DQ nemáš nikde použitý. Tady je Ti jeho definice k ničemu. #define NENÍ proměnná programu, ale musíš na ní koukat jako na proměnnou pro překladač. Překladač “čte” a překládá postupně kód. Když narazí na DS18B20_DQ, tak tam dosadí hodnotu, kterou DS18B20_DQ zrovna obsahuje (pokud není definovaná, vyhodí chybu). Takže přeloží rutinu pro obsluhu a víc už DS18B20_DQ nepotřebuje. To, že pak měníš obsah definice DS18B20_DQ a vkládáš volání obsluhy teploměru už nic neřeší, protože tam už s DS18B20_DQ překladač nepracuje. Jinak jsi správně pochopil, že pro 3 teploměry musíš mít 3 v podstatě identické rutiny (až na ten pin). Tady je pak už jenom jediná možnost - a to vzít rutiny pro teploměr a zkopírovat je jako :

ds18b20_reset_1();
ds18b20_reset_2();
ds18b20_reset_3();

V každém případě musíš mít obsluhu každého teploměru samostatně.

A pokud obsluha teploměru není Tvá vlastní, ale nějaká knihovna, pak budeš muset všechny teploměry pověsit na 1 pin a doufat, že knihovna umí komunikovat s více teploměrama na jednom pinu. Je tam trochu nevýhoda v tom, že si podle adres jednotlivých teploměrů musíš zjistit, který teploměr to fyzicky je.