Základy práce s porty v C u AVR mikrokontrolérů

Zde mám kód :

#include <avr/io.h> // definice periferii procesoru

void delay ( volatile uint32_t time )
{
while ( time-- );
}

int main( void )
{

//--------------------------------------------- >> I/O PORTY <<
//0 - VSTUP, 1 - VYSTUP

DDRB = 0b00000001;
DDRD = 0b00000000;

//--------------------------------------------- >> Nekonecna smycka <<
while( 1 )
{
PORTB = PINB ^ 0b00000001;
if((PIND && 0x01) == 0)delay( 1e4 );

}

return 0;
}

Můj dotaz: jak to že když připojím pin D7 na zem, tak mi program nezareaguje? Ale když if((PIND && 0x01) == 1)delay( 1e4 ); tak to jedničku přečte jako standardně nastavenou. AVR studio v debugu zareaguje správně na jedničku i nulu.
Budu rád za každou radu.

:arrow_right: administrator: přejmenováno z "Amatér - vstup z pinu"

Dovolim si zacitovat

  1. Nediv sa, ze program nereaguje na pin D7 kedze ho NIKDE v programe nemas pouzity. Predpokladam ale ze sa jednalo o preklep a chcel si napisat D0. :slight_smile:

  2. && je logicky sucin a nie binarny

&& pouzijes ak chces postavit podmienku:

   if ((teplota1 > MAX_TEPLOTA) && (otacky_ventilatora > MAX_OTACKY)) {
// nieco sprav ak su obe podmienky splnene
}

& pouzijes, ak chces spravit binarny sucin AND. Napriklad, ked ta zaujima hodnota prave jedneho bitu, potom napises:

      if((PIND & 0x01) == 0) delay( 1e4 );

Myslim, ze vsjo jasno :slight_smile:
Nic si z toho nerob, obcas sa to stane kazdemu :slight_smile:

Este taka poznamocka. Podmienka

      if((PIND & 0x01) == 1) delay( 1e4 );

je velmi nebezpecna, lebo plati prave pre ten jeden pin. Skor je lepsie napisat

      if((PIND & 0x01) != 0) delay( 1e4 );

V kazdom pripade Ti doporucujem pouzivat nazvy pinov cez #define. Velmi to zprehladnuje soft. Ale v tomto pripade to chapem ako programatorsku studiu mensieho rozsahu. A pri nej by malo byt vsetko dostatocne prehladne. Napriklad oznacenie D7 :slight_smile: :slight_smile: :slight_smile:
Smejem sa, lebo to sam dobre poznam. :slight_smile: :slight_smile: :slight_smile:

Tak nic, zas pozdě :slight_smile:
Kdyžtak mě smažte…

Jé je. Tak to mnohé vysvětluje. To už je degenerace ze spojování podmínek v Javě. A ještě 01 není pin 7 ale pin 0 :smiley: . Dnes už toho nechám. Děkuji moc za radu.

Navázal by jsem na předešlý problém. Na střední škole jsme psali pro x51 v assembleru. V assembleru se hodnota z pinu přesunula pomocí instrukce mov. V C mi ale není jasné když načtu hodnotu z pinu aby se mi vrátil do původní hodnoty. Př: zkontroluji hodnotu na pinu, když je 1 tak se něco provede. (plačítko) Jak docílit toho že na pinu ta hodnota nezůstane? Jak resetovat vstupní port? Snad jsem to popsal srozumitelně.

Vstup nemůžeme v programu nijak resetovat. Ten je ovládaný tlačítkem a tudíž ho nemůžeme ovládat zároveň z programu.

Tvůj problém je asi ten (musíme hádat), že při stisknutém tlačítku proběhne hlavní smyčka kódem pro tlačítko několikrát a to ty nechceš.

Nejjednodušší pomoc je počkat na uvolnění tlačítka.

[code]// tlac = PINB.2

if ( !(PINB & (1<<2) )
{
_delay_ms(100);

// kód

while (! (PINB & (1<<2) )
{;}
_delay_ms(100);
}[/code]

Zjednoduším to. Problém je ten, že tlačítko nastaví na pinu z log0 na log 1. (stisk) Tlačítko pustím ale program stále vidí na pinu log 1. Musím tedy pin uzemnit aby již neměl log1.

Máš na tlačítku pull-down? Jinak je to nesmysl (pokud nemáš XMEGU ve sledovacím režimu). Mimochodem - procesor má možnost zapnutí vnitřního pull-upu, tento se využívá a tlačítko obvykle připojuje proti zemi.

SFIOR = (1<<2);
takto se mi to povedlo vyřešit … tedy se to tak nějak snaží chovat chová mělo by to být globální nastavení pro všechny v/v porty

Co se ti tím zápisem povedlo vyřešit??? někam jsi zapsal “1” na bit 2. Pochybuji, že to má vliv na čtení portu. Směr I/O se nastavuje v DDRx a pull-upy se zapínají v PORTx při DDRxn=0.

toto jsem našel v dokumentaci

Special Function IO Register –
SFIOR
•Bit 2 – PUD: Pull-up Disable
When this bit is written to one, the pull-ups in the I/O ports are disabled even if the DDxn
and PORTxn Registers are configured to enable the pull-ups ({DDxn, PORTxn} = 0b01).

Tím jsi pouze vypnul (globálně) pull-upy na všech portech. Stejný efekt se ovšem dostaví, když port po resetu necjáš neinicializovaný nebo ho “pro jistotu” nastavíš jako vstupní a necháš registr PORTn v nule. Pull-upy se samy od sebe nezapnou. Není tady sice tvůj kód, je ovšem nepravděpodobné, že by globání vypnutí pull-upů něco řešilo. To by fungovalo pouze v případě, že by sis ho na daném pinu ručně zapnul.
Pokud máš tlačítko proti napájení, je zkrátka nezbytný externí pull-down, který ti pin po uvolnění tlačítka stáhne k zemi.

Zkusím to taky zjednodušit.
Vždy když je tlačítko připojeno mezi vstupní pin a plus,
musíme mezi tento pin a zem připojit odpor (např 4k7 - 10k).

Tak uzemníme pin při rozpojeném tlačítku.
Nikdy ne nějakými kouzly v programu.

Děkuji za objasnění.

Vestavěný pull-up jde použít na spínání tlačítkem na zem. Pokud chceme spínat na Vcc tak je nutný externí pull-down rezistor.