CCS compiler: jak předat ukazatel na PIN v parametru funkce?

Stáhnul jsem si knihovničku pro komunikaci s DALLAS chipy po 1wire sběrnici (v mém případě 18B20). Jedná se o zjednodušenou verzi, která umí komunikovat jen s jedním čipem na sběrnici. Já mám připojené čipy tři, každý na jiném pinu a potřebuji s nimi komunikovat postupně. Knihovna definuje PIN, na kterém je zařízení připojeno:

#define ONE_WIRE_PIN PIN_D2

Já ale potřebuji volat její funkce pokaždé ve vztahu k jinému pinu. Obsah knihovny jsem tedy přesunul do main.c a rád bych přišel na způsob, jak funkcím předat pin jako parametr, případně (pře)nastavit globální proměnnou. Nevím ale ani jaký datový typ použít.

Poraďte, prosím.

Zdar, můžeš sem tu knihovnu vložit?
Nepotřebuje ta knihovna i definici pro port, na kterém se pin nachází?
V té knihovně bude pravděpodobně pro manipulaci něco jako
ONE_WIRE_PORT |= 1<<ONE_WIRE_PIN; nebo nějaká fičurka překladače, která ovšem dělá to samé. To “ONE_WIRE_PIN” by mělo jít nahradit normální proměnnou. Její rozsah je 0-7, to se vejde do “unsigned char”.

to uz ma v ty definici, #define ONE_WIRE_PIN PIN_D2 = port D/2 ,PIN_A0 = port A/0

zalezi na ty knihovne co se tam s nim dela,ale melo by stacit jako promena, pokud ho udelas jako normalni promenou jako int ,tak musis ale do ni zapisovat hodnotu ktera ti definuje jak port tak pin , NEE hodnotu urcujici pin 0-7 !

#define PIN_A0  40
#define PIN_A1  41
#define PIN_A2  42
#define PIN_A3  43
#define PIN_A4  44
#define PIN_A5  45
#define PIN_A6  46
#define PIN_A7  47

#define PIN_B0  48
#define PIN_B1  49
#define PIN_B2  50
#define PIN_B3  51
#define PIN_B4  52
#define PIN_B5  53
#define PIN_B6  54
#define PIN_B7  55

#define PIN_C0  56
#define PIN_C1  57
#define PIN_C2  58
#define PIN_C3  59
#define PIN_C4  60
#define PIN_C5  61
#define PIN_C6  62
#define PIN_C7  63

#define PIN_D0  64
#define PIN_D1  65
#define PIN_D2  66
#define PIN_D3  67
#define PIN_D4  68
#define PIN_D5  69
#define PIN_D6  70
#define PIN_D7  71

#define PIN_E0  72
#define PIN_E1  73
#define PIN_E2  74
#define PIN_E3  75

treba takle

[code]int ONE_WIRE_PIN ;

void main ()
{
ONE_WIRE_PIN = 40; //40 pro PIN_A0
OUTPUT_HIGH(ONE_WIRE_PIN);
OUTPUT_LOW(ONE_WIRE_PIN);
ONE_WIRE_PIN = 41; //41 pro PIN_A1
OUTPUT_HIGH(ONE_WIRE_PIN);
OUTPUT_LOW(ONE_WIRE_PIN);
ONE_WIRE_PIN = 66; //66 pro PIN_D2
OUTPUT_HIGH(ONE_WIRE_PIN);
OUTPUT_LOW(ONE_WIRE_PIN);
}[/code]

Nojo, adresa portu, to mě nenapadlo… Doprdele přitom je to tak jasný :slight_smile:

tet nevim jestli s to pochopil nebo blbe napsal, musis tam dat hodnotu KTERA DEFINUJE JAK PORT TAK PIN, jaka hodnota definuje jakej pin/port mas v include pro danej typ PICe

Jo myslel jsem to dobre, ale napsal kravinu. Co ty hodnoty v tom includu vlastne znamenaji?

Jj, proto jsem tu knihovnu chtěl vidět, neboť nevim, jak je dělanej přístup u piců :slight_smile: Je vidět, že je to podobné jako u x51. Využívají se bytové i bitové adresy. Nicméně i tak by měl stačit unsigned char (0-255) :wink: Snažte se používat nejmenší datový typ, program je rychlejší.

Takhle to vypadá v originále:

[code]#define ONE_WIRE_PIN PIN_D2

void onewire_reset() {
output_low(ONE_WIRE_PIN); // pull the bus low for reset
delay_us(500);
output_float(ONE_WIRE_PIN); // float the bus high
delay_us(500); // wait-out remaining initialisation window
output_float(ONE_WIRE_PIN);
}

void onewire_write(int8 data) {
int8 count;

for(count = 0; count < 8; ++count) {
    output_low(ONE_WIRE_PIN);
    delay_us(2);                // pull 1-wire low to initiate write time-slot.
    output_bit(ONE_WIRE_PIN, shift_right(&data, 1, 0)); // set output bit on 1-wire
    delay_us(60);               // wait until end of write slot.
    output_float(ONE_WIRE_PIN); // set 1-wire high again,
    delay_us(2);                // for more than 1us minimum.
}

}

int onewire_read() {
int count, data;

for(count = 0; count < 8; ++count) {
    output_low(ONE_WIRE_PIN);
    delay_us(2);                // pull 1-wire low to initiate read time-slot.
    output_float(ONE_WIRE_PIN); // now let 1-wire float high,
    delay_us(8);                // let device state stabilise,
    shift_right(&data, 1, input(ONE_WIRE_PIN)); // and load result.
    delay_us(120);              // wait until end of read slot.
}
return data;

}

float ds1820_read() {
int8 busy=0, temp1, temp2;
signed int16 temp3;
float result;

//ds1820_configure(0x00, 0x00, 0x00);     //9 bit resolution

onewire_reset();
onewire_write(0xCC);            //Skip ROM, address all devices
onewire_write(0x44);            //Start temperature conversion

while(busy == 0)                //Wait while busy (bus is low)
    busy = onewire_read();

onewire_reset();
onewire_write(0xCC);            //Skip ROM, address all devices
onewire_write(0xBE);            //Read scratchpad
temp1 = onewire_read();
temp2 = onewire_read();
temp3 = make16(temp2, temp1);

//result = (float) temp3 / 2.0;   //Calculation for DS18S20 with 0.5 deg C resolution
result = (float) temp3 / 16.0;    //Calculation for DS18B20

delay_ms(200);
return(result);

}

void main(){
value = ds1820_read();
}[/code]

  • to funguje pro daný pin

No a podle mě potřebuju:

[code]void onewire_reset(int ONE_WIRE_PIN) {
output_low(ONE_WIRE_PIN); // pull the bus low for reset
delay_us(500);
output_float(ONE_WIRE_PIN); // float the bus high
delay_us(500); // wait-out remaining initialisation window
output_float(ONE_WIRE_PIN);
}

void onewire_write(int8 data, int ONE_WIRE_PIN) {
int8 count;

for(count = 0; count < 8; ++count) {
    output_low(ONE_WIRE_PIN);
    delay_us(2);                // pull 1-wire low to initiate write time-slot.
    output_bit(ONE_WIRE_PIN, shift_right(&data, 1, 0)); // set output bit on 1-wire
    delay_us(60);               // wait until end of write slot.
    output_float(ONE_WIRE_PIN); // set 1-wire high again,
    delay_us(2);                // for more than 1us minimum.
}

}

int onewire_read(int ONE_WIRE_PIN) {
int count, data;

for(count = 0; count < 8; ++count) {
    output_low(ONE_WIRE_PIN);
    delay_us(2);                // pull 1-wire low to initiate read time-slot.
    output_float(ONE_WIRE_PIN); // now let 1-wire float high,
    delay_us(8);                // let device state stabilise,
    shift_right(&data, 1, input(ONE_WIRE_PIN)); // and load result.
    delay_us(120);              // wait until end of read slot.
}
return data;

}

float ds1820_read(int ONE_WIRE_PIN) {
int8 busy=0, temp1, temp2;
signed int16 temp3;
float result;

//ds1820_configure(0x00, 0x00, 0x00);     //9 bit resolution

onewire_reset(ONE_WIRE_PIN);
onewire_write(0xCC,ONE_WIRE_PIN);            //Skip ROM, address all devices
onewire_write(0x44,ONE_WIRE_PIN);            //Start temperature conversion

while(busy == 0)                //Wait while busy (bus is low)
    busy = onewire_read(ONE_WIRE_PIN);

onewire_reset(ONE_WIRE_PIN);
onewire_write(0xCC,ONE_WIRE_PIN);            //Skip ROM, address all devices
onewire_write(0xBE,ONE_WIRE_PIN);            //Read scratchpad
temp1 = onewire_read(ONE_WIRE_PIN);
temp2 = onewire_read(ONE_WIRE_PIN);
temp3 = make16(temp2, temp1);

result = (float) temp3 / 16.0;    //Calculation for DS18B20

delay_ms(200);
return(result);

}

void main(){
int ONE_WIRE_PIN;
ONE_WIRE_PIN = 66; // vyčteno z include pro 16f74
value = ds1820_read(ONE_WIRE_PIN);
}[/code]

Což nefunguje vůbec. Pochopil jsem to dobře?

Je docela možné (a pravděpodobné), že instrukce využívající bitové adresování nedokáží místo adresy známé v době překladu využít proměnnou. Potom je nutné sáhnout po jiné programové konstrukci, něco jako jsem psal na začátku. Bude to pomalejší (načíst port, logická operace, zápis zpět), ale mělo by to fungovat. Bude to ovšem pro jednoduchost vyžadovat všechny čidla na stejném portu.

To zní logicky. Adresa je známá jenom kompileru… Takže to adresování budu muset trosicku obejít.

Na druhou stranu když jsem totéž psal v MicroC PRO for PIC, jejich nativní knihovna umožnila volání funkce takto:

tmp = Ow_Read(&PORTA, 5);

A fungovalo to…

ty hodnoty tam sou pro prekladac ,aby vedel s cim ma pracovat kdyz napises PIN_A0, nebo jak vidis da se toho viuzit v tydle situaci, jinak si jich vubec nevsimej, tebe pak jenom zajima to co je cerny, a to to co je napsany za “Functions:”

tet me este napadlo ze se to da s prehlednit

int ONE_WIRE_PIN ;
int Cidlo_1 = 40;		// cidlo pripojeno na pin A0
int Cidlo_2 = 41;       // cidlo pripojeno na pin A1
int Cidlo_3 = 42;		// cidlo pripojeno na pin A2

void Cti_cidlo()
{
// vycteni hodnoty z cidla  
}

void main ()
{
	ONE_WIRE_PIN = Cidlo_1;		    //nastaveni pro cidlo 2 na A0
	Cti_cidlo();
	
	ONE_WIRE_PIN = Cidlo_2;			//nastaveni pro cidlo 2 na A1
	Cti_cidlo()
}

jo prosim te hot sem jeste tu knihovnu kouknu se na ni

Knihovnička:
ds1820.c (1.62 KB)
1wire.c (1.89 KB)

Hele jakmile to celé přehodím na globální proměnnou, komunikace s chipem nefunguje… Stejně jako když to předávám parametrem.

Nemůže to fakt být tím adresováním, které funguje jen pro kompiler?

nemas to nekde v priklade ?? jek se to pouziva , naskoumal sem jak ma vypadat komunikace s 18b20, promin ale to co si tam zbastlil je dlbost, od kat si to stahnul ?? melo by to jit , vydrz kouknu na to

Co je blbost a proč? Rád bych se poučil, víš? Příklad máš výše, ty rutiny fungujou. Volám jenom 18B20_read, což mi vrátí float. Problém je jenom adresování toho pinu.

priklad :
zrejme pro reset je rutina

void onewire_reset() { output_low(ONE_WIRE_PIN); // pull the bus low for reset delay_us(500); output_float(ONE_WIRE_PIN); // float the bus high delay_us(500); // wait-out remaining initialisation window output_float(ONE_WIRE_PIN); }
takze kdyz chces resetovat treba cidlo na A0 tak napises

[code]
int ONE_WIRE_PIN ;
int Cidlo_1 = 40; // cidlo pripojeno na pin A0

void main ()
{

ONE_WIRE_PIN = Cidlo_1;		    //nastaveni pro cidlo 2 na A0
void onewire_reset() ;                  // volani resetu cidla na A0

} [/code]

a nee takle
void onewire_reset(int ONE_WIRE_PIN)

a bohuzel sem este s funkci “output_float” nedelal tak nevim co to dela , treba mi vysvetlit

EDIT: a funguje ti to aspon s jednim cidlem ?? hot sem zdrojak

melo by to vypadat asi nak takle

[code]
int ONE_WIRE_PIN ;
int Cidlo_1 = 40; // cidlo pripojeno na pin A0
int Cidlo_2 = 41; // cidlo pripojeno na pin A1
int Cidlo_3 = 42; // cidlo pripojeno na pin A2

int value_1 ; // hodnota z cidla 1
int value_2; // hodnota z cidla 2
//*****************************************************
void onewire_reset() {
output_low(ONE_WIRE_PIN); // pull the bus low for reset
delay_us(500);
output_float(ONE_WIRE_PIN); // float the bus high
delay_us(500); // wait-out remaining initialisation window
output_float(ONE_WIRE_PIN);
}

void onewire_write(int8 data) {
int8 count;

for(count = 0; count < 8; ++count) {
    output_low(ONE_WIRE_PIN);
    delay_us(2);                // pull 1-wire low to initiate write time-slot.
    output_bit(ONE_WIRE_PIN, shift_right(&data, 1, 0)); // set output bit on 1-wire
    delay_us(60);               // wait until end of write slot.
    output_float(ONE_WIRE_PIN); // set 1-wire high again,
    delay_us(2);                // for more than 1us minimum.
}

}

int onewire_read() {
int count, data;

for(count = 0; count < 8; ++count) {
    output_low(ONE_WIRE_PIN);
    delay_us(2);                // pull 1-wire low to initiate read time-slot.
    output_float(ONE_WIRE_PIN); // now let 1-wire float high,
    delay_us(8);                // let device state stabilise,
    shift_right(&data, 1, input(ONE_WIRE_PIN)); // and load result.
    delay_us(120);              // wait until end of read slot.
}
return data;

}

float ds1820_read() {
int8 busy=0, temp1, temp2;
signed int16 temp3;
float result;

//ds1820_configure(0x00, 0x00, 0x00);     //9 bit resolution

onewire_reset();
onewire_write(0xCC);            //Skip ROM, address all devices
onewire_write(0x44);            //Start temperature conversion

while(busy == 0)                //Wait while busy (bus is low)
    busy = onewire_read();

onewire_reset();
onewire_write(0xCC);            //Skip ROM, address all devices
onewire_write(0xBE);            //Read scratchpad
temp1 = onewire_read();
temp2 = onewire_read();
temp3 = make16(temp2, temp1);

//result = (float) temp3 / 2.0;   //Calculation for DS18S20 with 0.5 deg C resolution
result = (float) temp3 / 16.0;    //Calculation for DS18B20

delay_ms(200);
return(result);

}

void main()
{
ONE_WIRE_PIN = Cidlo_1;
value_1 = ds1820_read();
ONE_WIRE_PIN = Cidlo_2;
value_2 = ds1820_read();

}[/code]

Dobře, tady máme pokrok: Nastrkal jsem to všechno do main(), nepoužívám tedy podprogramy.

Všechno funguje do doby, než řádek:

#define ONE_WIRE_PIN PIN_D2

nahradím řádkem:

int ONE_WIRE_PIN = PIN_D2;

nebo

int ONE_WIRE_PIN = 66;

Dokáže mi to někdo vysvětlit?

A Milo s tim Tvym zdrojakem je stale stejny problem - adresovani nefacha.

Takze : to co sem tady uvadel za zdrojak nefunguje, je tam nakej prikaz kterej neumi pracovat s definici pinu jako cislo, viskouseno prakticky,
int ONE_WIRE_PIN = PIN_D2;
pokud chces priradit ONE_WIRE_PIN nakou hodnotu tak musis cislem nebo necim co je definovany jako cislo, definici pinu k tomu pouzit nejde,
takze bud budes muset :
sehnat knihovnu pro ovladani vice cidel po 1 sbernici
udelat 4 programy pro 4 cidla
nebo je nak spinat na jeden pin

To je teda pěkně trapný, vzhledem k faktu, že microC PRO kompiler nemá problém s předáváním indentifikace PINu parametrem.

BTW ta definice pinu není INTeger?