Nastavení bitu, čtení stavu na 18B20 příkazy if bit_is_set

Zdravím,
předem upozorňuju že jsem začátečník, tak mě snad hned neukamenujete. Kdysi na škole jsem se učil ASM pro 8051, teď si pořídil vývojový kit s AVR 644P a snažím se učit C-čko. Zatím jsem zprovoznil PWM na diodě, tlačítka, 7segmentovky v multiplexu a začal jsem si hrát s teplotním čidlem 1820. Bohužel jediné co mi asi funguje je reset :slight_smile:.

Chci se zeptat zda je možné nastavovat piny na portech tímto způsobem:

PORTA=(1<<P2); //zapíše 1 na pozici P2

PORTA=(0<<P2); //zapíše 0 na pozici P2
nebo musí být takto?:
PORTA=~(1<<P2); //zapíše 0 na pozici P2.

Ještě se chci zeptat zda je možné číst stav na výstupu 18b20 příkazy if bit_is_set/clear(PINx,x)…?

Díky, Honza

:arrow_right: administrator: přejmenováno z "Nastavení bitu, ds18b20"

Na první otázku si odpovím sám. Dělám to špatně, nula se musí zapisovat jako negace 1, takže takto: PORTA=~(1<<P2). To bude asi celý problém proč mi nefunguje zápis a čtení z čidla. Večer vyzkouším.
Pochopil jsem to až teď že to je jen posun v rámci 8mi bitů. Proto, jestli to chápu správně, když bych chtěl na bit 5 portu A dostat nulu bez ovlivnění ostatních bitů, bude to vypadat následovně?
PORTA&=~(1<<P5); 00100000 - to s zneguje na 11011111 a provede logický součin s portem A.

Ahoj.
Ja pouzivam toto a je to jasne

#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT)) #define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT)) #define FLIPBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT)) #define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))

Pro nastaveni je nutno nastavit DDR a PORT, pro cteni ctes jako PIN v PORT si nastavis jestli jsou tam pull-up nebo ne

Díky, to vypadá nejrozumněji. U teplotního čidla je pull-up rezistor, takže na čtení z čidla by mi mělo stačit nastavit DDR pro příslušný pin na 0 a pin už nijak nenastavovat.

Ahoj.
Mas to napul spravne.
DDR samozrejme na 0 ale s PIN nesmis nic delat to je jenom na cteni.
Asi si mel na mysli PORT ten musi bit na 0 v pripade ze DS uz ma vnitrni pull-up.
V tom pripade logika PIN bude 0=sepnuto 1=rozepnuto

Budes to mit tedy takto napriklad

SETBIT(DDRB,0);            //Nastavi pinB0 jako vystupni
SETBIT(DDRB,1);            //Nastavi pinB1 jako vystupni
CLEARBIT(DDRB,2);        //Nastavi pinB2 jako vstupni
CLEARBIT(DDRB,3);        //Nastavi pinB3 jako vstupni

SETBIT(PORTB,0);            //Pusti 5V do pinB0
CLEARBIT(PORTB,1);        //Uzemni pinB1
SETBIT(PORTB,2);           //Nastavi vnitrni pull-up na pinB1
CLEARBIT(PORTB,3);      // Pro spravnou funkci je potreba pripojit vnejsi pull-up nebo pull-down

//Vyhodnoceni

if (CHECKBIT(PINB,2)==0)   //Je sepnuto 
else //Je rozepnuto

if (CHECKBIT(PINB,3)==0)   //Je rozepnuto (pull-down) nebo sepnuto (pull-up)
else //Je rozepnuto (pull up) nebo sepnuto (pull down)




Děkuju moc za rady. Teď už mi to je jasný. Večer se to pokusím zprovoznit a podám info.

pokud vím, tak čidlo DS1820 vůj pullup nemá - dává se jeden na linku, kde těch čidel může být - teď nevím kolik, ten vnější pullup je navíc řádově menší než pullup v MCU - mně to myslím nechtělo chodit s interním pullupem.

Mám tam 10k externí pull-up na vývojovém kitu u ds18b20. Čidlo připojený na PORTA, bit0. Nemůžu to za boha rozchodit :frowning:. Přikládám základní funkce, jestli jsou vůbec použitelný. Chtěl bych se v tom pohrabat sám abych to pochopil a ne si někde stáhnout rutinu…

unsigned char cidlo_reset (void)
{
unsigned char stav=0;
DDRA|=0x01;
PORTA&=~(1<<PINA0);
_delay_us(480);
DDRA&=0xfe;
_delay_us(70);
if bit_is_clear(PINA,0) stav=0;
else stav=1;
_delay_us(410);
return(stav);
}


unsigned char cidlo_read(void)
{
unsigned char i;
unsigned char value=0;
DDRA|=0x01;
for (i=8;i>0;i–)
{
value>>=1;
PORTA&=~(1<<PINA0);
_delay_us(6);
DDRA&=0xfe;
_delay_us(9);
if (PORTA&(1<<PINA0)) value|=0x80;
_delay_us(55);
}
return(value);
}


void cidlo_write(unsigned char val)
{
DDRA|=0x01;
unsigned char i;
for (i=8; i>0; i–)
{
PORTA&=~(1<<PINA0);
_delay_us(6);
if (val&0x01)
{
DDRA&=0xfe;
_delay_us(64);
}
else
{
_delay_us(54);
DDRA&=0xfe;
_delay_us(10);
}
val=val/2;
}
}

Jak tak na to koukám tak ještě asi dělám chybu v tomto:
PORTA&=~(1<<PINA0);

PINA0 musím nahradit jen nulou? To by přece nemělo vadit, pozici bitu to určuje.

Jsem vůl, čtu z portu příkazem PORTA namísto PINA :frowning:((. Večer dám další pokus.

v DS je uvadeno 4K7 , a nekdo tu psal ze cidlo nechtelo fungovat az s < nez 2K2 tusim. tak pozor na to …

musi behat aj s 1K odporom inak su zle casy alebo nieco ine… samozrejme nebavime sa o parazitnom napajani.

Ja sa hlasim, mne cidlo nechcelo (kablik cca 5cm, jedine zariadenie na pine) komunikovat na 4k7. Tak som dal 2k2 a vsetko je na mnohych kusoch v poriadku. :slight_smile:

Mnohdy je třeba kontrolovat přechodový děj na čidle osciloskopem a případně jej upravit pull up odporem. Dá se předpokládat, že nižší hodnota odporu a vyšší parazitní kapacita (zvláště když je čidlo na dlouhém kabelu) způsobí vyšší tepenou ztrátu v čidle, která pak ovlivní měření teploty.
Divím se, že se vám to podařilo napsat v céčku a funguje to. Dělal jsem to v ASM a časování jsem dolaďoval vkládáním instrukcí NOP, aby časování přesně sedlo dle ds. Záleží i na 0,1us. V některých úsecích programu nesmí nastat přerušení.
Pokud komunikace s čidlem zlobí, může to být právě proto, že časování hran je někde na hranici únosnosti a pak je úspěšnost čtení závislá na kdečems.

Možná by pro přehlednost kódu bylo dobré definovat výstupní úrovně např

[code]#define out0 (DDRA |= (1<<0)) //výstup v úrovni 0
#define out1 (DDRA &= ~(1<<0)) //výstup v úrovni 1 přes pull-up

unsigned char cidlo_reset (void)
{
unsigned char stav=0;

out0;
_delay_us(480);
out1;
_delay_us(70);

}

main()
PORTA &= ~(1<<0); //PORTA.0=0

…[/code]

Pokud se chceme vyhnout zápisu s bitovými operátory, můžeme kromě uvedených možností
použít pro nastavení a nulování bitů i funkce z knihovny “deprecated.h”

[code]#include <compat/deprecated.h>

int main()
sbi(PORTB,1); //nastav bit
cbi(PORTB,1); //nuluj bit[/code]

V každé nové verzi WINAVR se sice vyhrožuje, že tato knihovna je zastaralá
a může být v některé další verzi vynechaná, ale to trvá už asi 10 let a je tam pořád.

Toho ze se zmeni verze WinAVR bych se nebal. Evidentne kvuli avrtoolchain se na vyvoji od roku 2010 nepracuje.
Nicmene nechapu, proc to ten chlapec neprepsal do tech maker, co jsem mu napsal… Z nich je to uplne jasne…
No nic, je to jeho volba

Ten chlapec :slight_smile: už to předělal, ale stejně to nepomáhá. Přikládám upravený kód. Pokud je kód správně, tak jediné co mě napadá, je ještě zkusit dát paralelně na pullup další 10k odpor, ale ten teď bohužel nemám k dispozici. Navíc by to na tom kitu mělo normálně fungovat když to s ním osazují… Každopádně děkuju všem za rady pánové. Do “s” se mi načte hodnota 255. Je divný když má 16 bitů že to není 65535 když už to blbne…

unsigned char cidlo_reset (void) //reset cidla
{
unsigned char stav=0;
SETBIT(DDRA,0); //prepnuto na vystup
CLEARBIT(PORTA,0); //stahnout na 0
_delay_us(480);
CLEARBIT(DDRA,0); //prepnuto na vstup-uvolnit
_delay_us(70);
if (CHECKBIT(PINA,0)==0) stav=0; //kdyz cidlo vrati 0 je zresetovano
else stav=1;
_delay_us(410);
return(stav);
}

void cidlo_write(unsigned char val) //zapise bajt
{
unsigned char i;
for (i=8; i>0; i–) //zapis Byte
{
SETBIT(DDRA,0); //prepnout na vystup
CLEARBIT(PORTA,0); //stahnout na 0-start timeslot
_delay_us(6);
if (val&0x01==1)
{
CLEARBIT(DDRA,0); //prepni na vstup-uvolni
_delay_us(64);
}
else
{
_delay_us(54);
CLEARBIT(DDRA,0); //prepni na vstup-uvolni
_delay_us(10);
}
val=val/2;
}
}

unsigned char cidlo_read(void) //precte bajt
{
unsigned char i;
unsigned char value=0;
SETBIT(DDRA,0); //prepnuto na vystup
for (i=8;i>0;i–)
{
value>>=1;
CLEARBIT(PORTA,0); //stahnout na 0-start timeslot
_delay_us(6);
CLEARBIT(DDRA,0); //prepnout na vstup-uvolnit
_delay_us(9);
if (CHECKBIT(PINA,0)==1) value|=0x80; //precti stav sbernice
_delay_us(55); //cekej na konec timeslotu
}
return(value);
}

int scratchpad_read(void) //precte teplotu-dva bajty
{
unsigned char i;
int value=0;
SETBIT(DDRA,0); //prepnout na vystup
for (i=16;i>0;i–)
{
value>>=1;
CLEARBIT(PORTA,0); //stahnout na 0-start timeslot
_delay_us(6);
CLEARBIT(DDRA,0); //prepnout na vstup-uvolnit
_delay_us(9);
if (CHECKBIT(PINA,0)==1) value|=0x80; //precti stav sbernice
_delay_us(55); //cekej na konec timeslotu
}
return(value);
}

void main(void)
{
DDRB=0xff; //port B vystupni
DDRC=0x0f; //port C0-C3 vystupni zbytek vstup
PORTC=0xff;

volatile unsigned int s;
while (cidlo_reset()==1);		//pri neuspesnem resetu se tady zacykli
cidlo_write(0xcc);				//skip ROM
cidlo_write(0x44);				//prevod T
while (CHECKBIT(PINA,0)==0);	//cekej na dokonceni prevodu
while (cidlo_reset()==1);		//pri neuspesnem resetu se tady zacykli
cidlo_write(0xcc);				//skip ROM
cidlo_write(0xbe);				//read scratchpad
s=scratchpad_read();
while(1)

{
	num_7seg(s,255);//zobraz na 7seg
	
}

Omlouvam se, nemyslel jsem to tak…
Kdyz pouzivas funkci delay, tak maximalni hodnota je cca 260uS. Pokud pouzijes v tvem pripade 460uS tak to ma presnost 1/10.

Vlož sem celej projekt.

V pohodě, já toho chlapce bral jako srandu… Přikládám teda celý projekt. Zobrazovaní nemám ještě udělaný přes přerušení, to měl být další krok… Jakto že ten příkaz pro delay není přesný? To jsem netušil. Tu přesnost 1/10 myslíte tak, že při zpoždění třeba 460uS může být nepřesnost ±46uS? V tom případě bych to musel napsat na dvakrát a nebo udělat zpoždění přes časovač.

#define F_CPU 16000000
#define port7seg_data PORTB //port pro data na 7SEG +nastavit DDRx=0xff jako vystupni
#define port7seg_pos PORTC //port pro pozice na 7SEG bity 0…3 pro pozici 0-3 +nastavit DDRx=0x?f jako vystupni
#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define FLIPBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))

#include <avr/io.h>
#include <avr/delay.h>
#include <avr/pgmspace.h>
#include <math.h>

const unsigned char Cislice_tab7SEG[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //Tabulka cisel pro 7SEG Px.0-Px.7 odpovida A,B…G,tecka

//Tabulka znaku na pro 7SEG
const unsigned char Font_tbl[128] =
{
0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49, 0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,
0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49, 0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,
0x00,0x82,0x22,0x49,0x49,0x49,0x49,0x02, 0x49,0x49,0x49,0x49,0x49,0x40,0x80,0x52,
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07, 0x7F,0x6F,0x49,0x49,0x49,0x48,0x49,0x53,
0x7B,0x77,0x49,0x39,0x49,0x79,0x71,0x7D, 0x76,0x06,0x0E,0x49,0x38,0x49,0x37,0x3F,
0x73,0x49,0x49,0x6D,0x49,0x3E,0x49,0x49, 0x49,0x6E,0x5B,0x39,0x64,0x0F,0x23,0x08,
0x20,0x5F,0x7C,0x58,0x5E,0x7B,0x71,0x6F, 0x74,0x04,0x0E,0x49,0x06,0x49,0x54,0x5C,
0x73,0x67,0x50,0x6D,0x78,0x1C,0x49,0x49, 0x49,0x6E,0x5B,0x46,0x30,0x70,0x01,0x49
};

void text_7seg (unsigned char text[4],unsigned char jas) //4 znaky na 7seg, jas 0-255
{
unsigned char temp,znak,poz_disp;
temp=jas;
for(znak=0,poz_disp=8;znak<4;znak++) //posila znak od nejvyssi pozice dokud je znak<4
{
port7seg_pos|=0x0f; //maska portu na xxxx1111
port7seg_pos&=~poz_disp; //negovana maska pozice na LN portu
port7seg_data=~Font_tbl[text[znak]]; //zobrazi negovany znak na aktualni pozici (spolecna anoda)
while(jas>0) jas–; //doba zobrazeni podle jasu
port7seg_data=0xff; //zhasni data
port7seg_pos|=0x0f; //zhasni pozici
jas=255-temp; //jas=doba zhasnuti
while(jas>0) jas–; //doba zhasnuti podle jasu
jas=temp; //obnoveni jasu z temp
poz_disp>>=1; //pozice na nizsi
}
}

void num_7seg (int val,unsigned char jas) //rozsah pouze pro hodnoty -999 az 9999 4sedmisegmentovky
{
unsigned char temp,i,poz_disp,minus;
if (val<-999|val>9999) text_7seg("-OF-",jas); //kdyz je val mimo rozsah zobrazovace vypis chybu/preteceni
else
{
if (val<0) {minus=1; val=abs(val);} else minus=0; //kdyz je val zaporny nastav minus a uloz ABS do val
temp=jas; //jas do temp
for (i=0,poz_disp=1;i<4;i++) //posila cislici od nejnizsi pozice
{
port7seg_pos|=0x0f; //maska portu na xxxx1111
port7seg_pos&=~poz_disp; //negovana maska pozice na LN portu
if ((minus==1)&(poz_disp==8)) port7seg_data=~64; //kdyz minus=1 a pozice 8 zobraz minus (na nejvyssi pozici)
else
port7seg_data=~Cislice_tab7SEG[val%10]; //zobrazi negovanou cislici na aktualni pozici (spolecna anoda)
while(jas>0) jas–; //doba zobrazeni podle jasu
port7seg_data=0xff; //zhasni data
port7seg_pos|=0x0f; //zhasni pozici
jas=255-temp; //jas=doba zhasnuti
while(jas>0) jas–; //doba zhasnuti podle jasu
jas=temp; //obnoveni jasu z tempu
poz_disp<<=1; //posun pozice na vyssi
val=val/10;
}
}
}

unsigned char cidlo_reset (void) //reset cidla
{
unsigned char stav=0;
SETBIT(DDRA,0); //prepnuto na vystup
CLEARBIT(PORTA,0); //stahnout na 0
_delay_us(480);
CLEARBIT(DDRA,0); //prepnuto na vstup-uvolnit
_delay_us(70);
if (CHECKBIT(PINA,0)==0) stav=0; //kdyz cidlo vrati 0 je zresetovano
else stav=1;
_delay_us(410);
return(stav);
}

void cidlo_write(unsigned char val) //zapise bajt
{
unsigned char i;
SETBIT(DDRA,0); //prepnout na vystup
for (i=8; i>0; i–) //zapis Byte
{
CLEARBIT(PORTA,0); //stahnout na 0-start timeslot
_delay_us(6);
if (val&0x01==1)
{
CLEARBIT(DDRA,0); //prepni na vstup-uvolni
_delay_us(64);
}
else
{
_delay_us(54);
CLEARBIT(DDRA,0); //prepni na vstup-uvolni
_delay_us(10);
}
val=val/2;
}
}

unsigned char cidlo_read(void) //precte bajt
{
unsigned char i;
unsigned char value=0;
SETBIT(DDRA,0); //prepnuto na vystup
for (i=8;i>0;i–)
{
value>>=1;
CLEARBIT(PORTA,0); //stahnout na 0-start timeslot
_delay_us(6);
CLEARBIT(DDRA,0); //prepnout na vstup-uvolnit
_delay_us(9);
if (CHECKBIT(PINA,0)==1) value|=0x80; //precti stav sbernice
_delay_us(55); //cekej na konec timeslotu
}
return(value);
}

int scratchpad_read(void) //precte teplotu-dva bajty
{
unsigned char i;
int value=0;
SETBIT(DDRA,0); //prepnout na vystup
for (i=16;i>0;i–)
{
value>>=1;
CLEARBIT(PORTA,0); //stahnout na 0-start timeslot
_delay_us(6);
CLEARBIT(DDRA,0); //prepnout na vstup-uvolnit
_delay_us(9);
if (CHECKBIT(PINA,0)==1) value|=0x80; //precti stav sbernice
_delay_us(55); //cekej na konec timeslotu
}
return(value);
}

void main(void)
{
DDRB=0xff; //port B vystupni
DDRC=0x0f; //port C0-C3 vystupni zbytek vstup
PORTC=0xff;

int s;
while (cidlo_reset()==1);		//pri neuspesnem resetu se tady zacykli
cidlo_write(0xcc);				//skip ROM
cidlo_write(0x44);				//prevod T
while (CHECKBIT(PINA,0)==0);	//cekej na dokonceni prevodu
while (cidlo_reset()==1);		//pri neuspesnem resetu se tady zacykli
cidlo_write(0xcc);				//skip ROM
cidlo_write(0xbe);				//read scratchpad
s=scratchpad_read();
while(1)

{
	num_7seg(s,255);			//zobrazeni na 7seg
	
}

}