Práce bez ukazatele

ahoj, poradil by mi někdo jak se zbavit toho ukazatele *buffer, abych to měl bez něho tuto funkci?

void read_temperature(char *buffer){
uint8_t temperature[2];
//**Reset, skip ROM and start temperature conversion
therm_reset();
therm_write_byte(SKIP_ROM);
therm_write_byte(CONVERT_T);

//**Wait until conversion is complete
while(!therm_read_bit()); //DS18B20 send 1 for conversion is done

//**Reset, skip ROM and send command to read Scratchpad
therm_reset();
therm_write_byte(SKIP_ROM);
therm_write_byte(READ_SCRAT);

//**Read Scratchpad (only 2 first bytes)
temperature[0]=therm_read_byte();        //low byte
temperature[1]=therm_read_byte();        //high byte
therm_reset();

//**conversion 2 byte to digit and decimal
uint8_t digit;
uint16_t des;

digit = (temperature[1]<<4)&0xf0;        //form 2 bytes to byte for conversion
digit |= (temperature[0]&0xf0)>>4;

des = (temperature[0]&0xf)*625;        //625 create whole number (over 8b therefore uint16_t)
des = des/100;   

}

Musel by sis nadefinovat globální proměnnou. Proč ti tam vadí ten ukazatel? Je to efektivní způsob…

protože s ním neumím pracovat a potřeboval bych, aby tato funkce měla jako argument channel (kanál, který by mi definoval jaké čidloz jakého pinu má číst tato fce).

Tak to uděláš v podstatě stejným způsobem, jako je to v té části “Read scratchpad” - nadefinuješ si pole proměnných pro ta čidla (uint16_t, samozřejmě nad touto funkcí, tuto necháš jak je, kromě toho ukazatele), a pak můžeš pokračovat dvěma způsoby - buď načteš všechna čidla najednou a konkrétní tě bude zajímat až při zobrazování, a nebo si opravdu načteš jen jedno čidlo… to bude záležet na tom, jakým způsobem pak tuto funkci budeš volat.

Asi bych si to udělal, že konkrétní čidlo mě bude zajímat až při zobrazování, ale úplně nevím jak udělat to s tím polem a ukazatelem.

Neumím moc dobře v c nemohl by jsi mi ukázat jak to myslíš??
chápu jak udělat pole s těmi čidly, ale už nevím jak to pak udělat, aby to vybíralo to konkrétní čidlo např na pc0, pc1 atd. Nepoužívám adresy čidel pro jejich hledání, protože mám každé čidlo na jiném pinu.

Mám pocit, že ta funkce není celá, takže nevím, jakým způsobem ukládá výsledky, ale:
Hned v úvodu programu (aby to nebylo v žádné funkci, ale přístupné pro všechny) si nadefinuješ to pole, jménem třeba “cidla” uint16_t cidla[4], a taky ještě jednu proměnnou, která bude určovat, které čidlo nás zrovna zajímá (v podstatě obrazně “přepínat” ta čidla), třeba “konkr_cidlo” a uint8_t konkr_cidlo. Volání této funkce na vyčtení čidla pak bude void read_temperature(cidla[konkr_cidlo]). Není to úplně čisté, například budeš muset provádět kontrolu na zapsanou hodnotu té proměnné (kdybys jako požadavek na vyčtení čidla omylem někde zapsal třeba hodnotu 7 tak to nedopadne úplně dobře). Čistší by bylo, kdybys při volání funkce uváděl (místo void) jaké parametry má funkce po provedení vracet a při ukončení je vrátil (return(neco);), ale jelikož to “něco” mi tu teď není známo, těžko to tak upravím…

Ještě jedna užitečná informace k tomu čidlu, když to máš jako semestrálku: To čidlo se při své aktivitě ohřívá svým vlastním teplem, takže při častém použití (umožňuje jako maximum cca. jedno čtení za sekundu) sice měří s přesností plusmínus půl stupně, ale svoji vlastní teplotu - ujede po pár desítkách minut klidně o stupeň, i víc. Ve svém teploměru jsem vyčítal jednou za 30 sekund, a pořád ještě to bylo trošku znát (ale už žádné drama), takže čtení jednou za 30 sekund je vyzkoušená minimální perioda, pokud chceš fakt měřit teplotu prostředí.

U svého teploměru si asi používal adresy, že?

Ne, já měl jenom jedno čidlo, a navíc jsem si zrovna tohle psal v ASM. Nemáš celý program, nebo odkaz, odkud jsi čerpal?

Myslím, že by nebylo od věci si Cčko nacvičit poněkud lépe, než se pustiš do něčeho složitějšího. Ukazatele jsou v Cčku mocný nástroj, bez kterého se občas neobejdeš. Například řetězce (texty). Je to jako by jsi chtěl řídit auto, ale nechtěl používat volant, protože s ním neumíš …

1 Like

já se do toho pouštět nechtěl já musel … a teď nevím jak vypsat na segmentovku jelikož tam je ten pointer…

Bude to podobné… Dej sem prosímtě zip s celým tím programem, nebo pošli odkaz, mrkneme se na to :wink: Jo, a nic si z toho nedělej, elektronika není to hlavní, o co v životě běží, spíš je to žrout času, kvůli kterému může člověk minout něco důležitějšího.

semestralka_final.zip (76.2 kB)
Teď jsem to udělal takhle, ale je to dost na “prasáka”

a vůbec mi to nefunguje, když to chci zobrazit na segmentovém displeji… a už nevím vůbec proč…

Protože jsi to napsal úplně jinak než jsem psal, nepotřebuješ tu rutinu 4x, a protože na segmentovém LED displeji nezobrazíš nic pomocí sprintf, to se dělá jinak. Ladění si vypisuješ na sériovou konzoli? Jestli jo, tak si tam ten sprintf zase odkomentuj… Dál: Jestli máš na vstupu pro přerušení tlačítko (kterým měníš proměnnou CISLO), je potřeba mít tlačítko ošetřené proti zákmitům. Jinak jsem to ještě trochu poupravil, rutiny obsluhy přerušení je obvyklé mít na začátku (a main obvykle zas na konci, ale to jsem teď tak neudělal), a je dobré si to pomocí komentářů nejenom bohatě komentovat, ale i zpřehledňovat.

Dodej prosímtě i schéma a fotky, ať víme jak to máš zapojené, pro začátek je potřeba vědět aspoň podrobnosti o tom LED displeji a čidlech - ta máš čtyři na každém pinu zvlášť? A kde? Zatím jsem to jen poopravil, fungovat to teď ještě nebude. Uvědom si prosím, že to pole cidla[] je ten buffer, takže zde jsme si neporozuměli (hlavně proto, že nebyl celý program, takže nebyly vidět definice). Je jedno, jestli se to bude jmenovat buffer nebo cidla, ale pokud obsah hned zobrazíš, bude stačit jen jedno pole (a i pokud budou ta pole čtyři, pořád je potřeba ta rutina na vyčtení z čidla jenom jednou!). Zkus si prosímtě zbytek programu sjednotit*

Zároveň tímto prosím někoho, kdo má na stole vybavení a umí C (nebo si to aspoň může zkontrolovat a zkompilovat), aby taky pomohl, protože já to jedu “nasucho” a nejsem původně “atmelák”.

Edit: Ach jo… Jak se sem prosímvás nahrává soubor? :roll_eyes:
*Edit2: Máš tam pole znaky, které ale nikde neplníš jestli dobře vidím, proto se ti na displeji nic nezobrazuje.

#define F_CPU 16000000UL
#include "DS18B20.h"
#include <util/delay.h>
#include <stdio.h>
#include <avr/interrupt.h>


void ZobrazCislo(uint8_t anody, char znak);
void zobraz(char *znaky);

uint16_t cidla[4];
//uint8_t konkr_cidlo;

int CIDLO = 0;

char buffer1[16];
/*char buffer2[16];
char buffer3[16];
char buffer4[16];*/

void ioinit(void);

void read_temperature(cidla[konkr_cidlo);
/*void read_temperature2(char *buffer2);
void read_temperature3(char *buffer3);
void read_temperature4(char *buffer4);*/

//*********************************************

ISR(INT0_vect) {
	CIDLO++;
	if (CIDLO>3)
	{
		CIDLO = 0;
	}
}

//---------------------------------------------

ISR (TIMER0_OVF_vect) {
	TCNT1=49911;
	
	read_temperature1(buffer1);
	read_temperature2(buffer2);
	read_temperature3(buffer3);
	read_temperature4(buffer4);
	
	
}

//*********************************************
//=============================================

int main( void ){
	
	ioinit();
	
	while (1) {
		switch(CIDLO) {
			case 0:	zobraz(buffer1);  PORTA &=~(1<<PORTA0); break;
			case 1:	zobraz(buffer2);  PORTA &=~(1<<PORTA1); break;
			case 2:	zobraz(buffer3);  PORTA &=~(1<<PORTA2); break;
			case 3:	zobraz(buffer4);  PORTA &=~(1<<PORTA3); break;
	}

}
}

//=============================================

void read_temperature(cidla[CIDLO]) {
	uint8_t temperature[2];
	//**Reset, skip ROM and start temperature conversion
	therm_reset_0();
	therm_write_byte_0(SKIP_ROM);
	therm_write_byte_0(CONVERT_T);


	//**Wait until conversion is complete
	while(!therm_read_bit_0()); //DS18B20 send 1 for conversion is done

	//**Reset, skip ROM and send command to read Scratchpad
	therm_reset_0();
	therm_write_byte_0(SKIP_ROM);
	therm_write_byte_0(READ_SCRAT);

	//**Read Scratchpad (only 2 first bytes)
	temperature[0]=therm_read_byte_0();         //low byte
	temperature[1]=therm_read_byte_0();        //high byte
	therm_reset_0();

	//**conversion 2 byte to digit and decimal
	uint8_t digit;
	uint16_t des;

	digit = (temperature[1]<<4)&0xf0;        //form 2 bytes to byte for conversion
	digit |= (temperature[0]&0xf0)>>4;

	des = (temperature[0]&0xf)*625;        //625 create whole number (over 8b therefore uint16_t)
	des = des/100; 
	
	cidla[CIDLO] = des;
    // sprintf(buffer1, "%+d.%04u C", digit, des);
	
}

//---------------------------------------------

void ioinit(void)
{
	sei();			// Global Interrupt
	
	//Nastaveni portù
	DDRB = 0b11111111;      //displej 
	PORTB = 0b00000000;
	
	DDRD = 0b11110000;     //anody, sw
	PORTD = 0b11110000;
	
	DDRC = 0b00000000;     //èidla
	PORTB = 0b00000000;
	
	DDRA |=(1<<DDA1) | (1<<DDA0) | (1<<DDA2) | (1<<DDA4);
	PORTA |=(1<<PORTA1) | (1<<PORTA0) | (1<<PORTA2) | (1<<PORTA4);
	
	TCCR0 = (1<<CS00)|(1<<CS01);	// Timer0 - pøeddìlièka
	TIMSK |= (1<<TOIE0)|(1<<TOIE1);	// povolení
	
MCUCR = (1<<ISC11)|(1<<ISC01);
GICR = (1<<INT0)|(1<<INT1);
}

//---------------------------------------------
	
void zobraz(char *znaky){
	ZobrazCislo(0,znaky[0]);
	_delay_ms(2);
	ZobrazCislo(1,znaky[1]);
	_delay_ms(2);
	ZobrazCislo(2,znaky[2]);
	_delay_ms(2);
	ZobrazCislo(3,znaky[3]);
	_delay_ms(2);
}

//---------------------------------------------

void ZobrazCislo(uint8_t anody, char znak)
{
	
	switch(anody)
	{
		case 0:
		PORTD = 0b01110000;
		break;
		case 1:
		PORTD = 0b10110000;
		break;
		case 2:
		PORTD = 0b11010000;
		break;
		case 3:
		PORTD = 0b11100000;
		break;
	}
	
	switch(znak)
	{
		case '0':
		PORTB = 0b10000001;
		break;
		case '1':
		PORTB = 0b11110011;
		break;
		case '2':
		PORTB = 0b01001001;
		break;
		case '3':
		PORTB = 0b01100001;
		break;
		case '4':
		PORTB = 0b00110011;
		break;
		case '5':
		PORTB = 0b00100101;
		break;
		case '6':
		PORTB = 0b00000101;
		break;
		case '7':
		PORTB = 0b11110001;
		break;
		case '8':
		PORTB = 0b00000001;
		break;
		case '9':
		PORTB = 0b00100001;
		break;
		case '.':
		PORTB = 0B01111111;  
		break;
		
	}
}

Ne, mám to na evb kitu kde mám to čidlo a zbylá čidla na nepájivém poli. Segmentovku mám na Pb cidla na Pc tlacitko na Pd2 a segmenty na Pd7-4. teď už mi nefunguje an zobrazování teploty co předtím fungovalo…

Už si nevím fakt rady, je tu někdo kdo by byl ochotný mi to za finanční odměnu naprogramovat??

Nevzdávej to, když to potřebuješ, tak to nakonec bude, uvidíš. Prosímtě, aspoň jednu fotku toho kitu sem dej - EVB kit jake verze to je? Odkud zhruba jsi? Já jsem teď doma marod, napíšu ti i do SZ.

Určitě máš původní verzi (každou úpravu si určitě ukládáš jako nový soubor), tak se vrať k verzi která fungovala aspoň nějak (a kdyžtak ji sem i postni, když se ti bude chtít, porovnám si to). Hlavně klid :wink:

Jestli máš víc čidel všechny na jednom drátu a pinu, tak je budeš muset adresovat, což v té rutině nevidím (a naopak tam vidím poslání příkazu SKIP ROM, což se používá, když je jen jedno čidlo na jednom pinu), takhle to asi nebude fungovat. Jaké máš přesně zadání?