Porty: nastavení I/O, čtení z portu, přerušení při změně

Zdravim,
programuji atmegu16 v codevisionu (jazyk C) a nastal mensi problem. Napsal jsem jednoduche cykly (while), ketere po splneni podminky (je na pinu 1?) provedou co chci, jenze piny, ktere hrajou roly ve whilu, nereaguji na log. 1 (5V).

pr:
while(PORTC.0==1){
lcd_gotoxy(0,0);
lcd_puts(“nejaky text”);
delay_ms(3000);
lcd_clear();
}

Otazky tedy zni:

  1. Jak se nastavi urcity port jako vstupni nebo jako vystupni, abych s nimi mohl dale pracovat. Treba porty C0 jako vstup, C1 vystup.

  2. Mam v zarizeni nejaka tlacitka, jenze jsem zjistil ze mi nestaci testovat, jestli neni nejake tlacitko sepnute, az pote co se ukonci predesly cyklus. Potreboval bych, aby byl prvotni cyklus prerusen a pak se rozbehl jiny cyklus, kdyz se stiskne tlacitko pripojene na pinu treba B1.

  3. Jakym zpusobem se v C zjisti hodnota pinu (treba A2) a ta se pak ulozi do nejakeho registru (nevim jestli lze definovat nazev vlastniho registru, pokud ano, tak jmeno treba Zjisteni) v hodnote 0 nebo 1.

Prozatim je to vse, kdy by me jeste neco napadlo, urcite to sem pripisi. Dekuji predem za nazorne ukazky kodu a vase rady.

:arrow_right: administrator: přejmenováno z "Prace s porty a prerusenim"

Takže:
1.)
DDRC = 0x00; //všechny vystupy C nastaveny jako pull-up vstupy
PORTC = 0xFF;

while(PINC.0==1){ //chceš-li testovat vstup, musíš použít PINx lcd_gotoxy(0,0); lcd_puts("nejaky text"); delay_ms(3000); lcd_clear(); }

2.) Nevím sice jak moc obtížný cyklus hodlat použít, ale ATMegy jsou
podle mne dost rychlé na to, aby stihly dokončit cyklus a následně otestovat druhé tlačítko.
Pokud však nehodláš ustoupit, tak ti dám pár tipů:
A) testuj obě tlačítka současně
while((PINC.0)&&(!PINC.1))
B) připoj tlačítko na INTx pin a naprogramuj si pro něj přerušení.
C) dělej testy vstupů během cyklu. Moc to však nedoporučuji.
Chce to mít už nějaké zkušenosti.
D) Projdi si ještě jednou zadání. Beztak přijdeš na to, že to lze udělat jednodušeji.

3.) To si snad už vážně děláš legraci.
Pro boha kup si nějakou publikaci o programování MCU v C.
Doporučované jsou knihy z nakladatelství BEN.

tvůj problém s nestíháním je podle toho jak jsem to pochopil delay_ms(3000), je to logicke že když zde čekáš. pokud nechceš vymýšlet nic složitého zkus

while…
{

for(i = 0; i < 100; i++)
{
delay_ms(30);
if(PINC.1 == 1) break;
}

}

Vyzkousel jsem nastaveni pinu B na vstupni a atmega uz reaguje na tlacitka, takze se mi dany cyklus rozjede. Jenze bych potreboval vedet, jak lze jen JEDEN urcity pin treba A1 nastavit jako vstupni. Mam totiz cykl, ve kterem na pinu A0 nasatvim log1 a pak testuji zda je na pinu A1 log 1 nebo 0.

S tim prerusenim to budu muset vyresit jinak, protoze tlacitka (4 tlacitka) jsou pripojena na pinech B.
Pokud tedy neni nejaky zpusob jak atmegu prerusit, kdyz sepnu tlacitko na portu B1, tak budu muset prvni cyklus, ktery musi trvat 6 sekund nejak predelat.

citace divous

Zaslal: 22 březen 2010, 6:32 Předmět:
Takže:
1.)
DDRC = 0x00; //všechny vystupy C nastaveny jako pull-up vstupy
PORTC = 0xFF;

vysvětlení

registr DDRC určuje zdali má byt port vstupní(0), či výstupní(1)

DDRC = 0b00000000; - všechny vstupní
DDRC = 0b00000001; - PINC.0 výstupní
citace divous

Zaslal: 22 březen 2010, 6:32 Předmět:
Takže:
1.)
DDRC = 0x00; //všechny vystupy C nastaveny jako pull-up vstupy
PORTC = 0xFF;

vysvětlení

registr DDRC určuje zdali má byt port vstupní(0), či výstupní(1)

DDRC = 0b00000000; - všechny vstupní
DDRC = 0b00000001; - PINC.0 výstupn
citace divous

Zaslal: 22 březen 2010, 6:32 Předmět:
Takže:
1.)
DDRC = 0x00; //všechny vystupy C nastaveny jako pull-up vstupy
PORTC = 0xFF;

vysvětlení

registr DDRC určuje zdali má byt port vstupní(0), či výstupní(1)

DDRC = 0b00000000; - všechny vstupní
DDRC = 0b00000001; - PINC.0 výstupní, ostatní vstupní
DDRC = 0b00001001; - PINC.0, PINC.3 výstup, ostatní vstup

PORTC určuje zdali budeš mět pull up = log. 1 na pinu nebo ne.

už to chápeš?

Jo, jo ted uz mi to docvaklo :smiley:
Prakticky priklad na dvou pinech je myslim nejlepsi vysvetleni :wink:

Zatim zkousim vyuzit cyklu for misto preruseni a snad to pujde…

To “preruseni” diky cyklu for bez problemu funguje, diky.
Jen bych rad znal odpoved na tu trapnou otazku s cislem 3 :smiley:

Tak nějak jsem to o co ti jde nepochopil. jako jestli ti jde o toto?

hodnota = PINC.1;

tak v proměnné hodnota budeš mít buď 1 nebo 0.

No nevim jistě jestli by fungovalo :

char hodnota;
hodnota=PINC.1;

to by se muselo zkusit

ale pro zjištění jestli je na PINC.1 0,nebo 1stačí přece:

if(PINC.1==1) hodnota=1;
else hodnota =0;

nic jiného tam samozřejmě - jak psal zalda mít nebudeš

Ok, je to tak jak jsem si myslel, kazdopadne dik za pomoc, kdyby se vyskytl nejaky problem, urcite se o nem dozvite… :slight_smile:

char hodnota;
hodnota = PINC.1;

  • funguje.

Nastal prblem, ktery nechapu.

.......    
DDRC=0b00000000;  //Piny C nastaveny na vstup
DDRC=0b10000000;  //Pin C.7 nastaven na výstup    
PORTC.7=1;
delay_ms(250);   //kvuli dlouhemu kabelu zapojenemu na C7 a C6
while(PINC.6==1){
        lcd_clear();
        lcd_gotoxy(0,0);
        lcd_puts("PINC.6 je 1");
        delay_ms(3000);
{
.......

Po napsani tohoto kody jsem ocekaval, ze pinC6 bude bez privedeni napeti v log 0 (kabel nebyl zapojen), jenze ono ne. Aniz bych mel nekde v programu nastaven pin C6 na jednicku, tak se cykl provede, jakoby C6 byl v log1.
Zrejme je tam pro me nekde skryta chyba.

no kedze ti ten pin 6 visi v o vzduchu tak na nom nieje definovany stav a vplyvom okolnosti na nom moze byt log1. TAk ze bud zapni pullup a obrat logiku. alepo uzemni ten pin cez nejaku rozumnu hodnotu napr10k na zem tj gnd

Myslim si ze snad neni chyba v indukci napeti z jineho pinu, protoze kdyz jsem vyzkousel i jiny pin, daleko od veskerych zdroju napeti, tak se take hlasi jako jednicka. Ono naindukovat uroven vetsi jak 1V je docela sila, kdyz tam mam vsude minimalne rozestupy 1mm. Jinak v mem zarizeni budu potrebovat v jedne fazi vypnout pull up, pote jej zase zapnou na jinem pinu a tak dal.

pr:
Vezmu to po lopate, treba pin C.0 nastavim jako vystupni a na nej log 1, na pinu C.1 nastavim vnitrni pullup a vstup. V dalsi fazi bude C.0 a C.2 jako vstup s vnitrnim pullupem a C.1 jako vystup s log 1. atd…

Jaka je syntaxe pro zapnuti pullupu na pinu a pote jeho vypnuti. Mohl by prosim nekdo napsat, jak by vypadal kod uvedeneho prikladu?

Jeste dotaz, existuje u atmegy16 interni Pull-Down?
Kdyby ano, tak by mi to usetrilo namahu pri programovani, pac bych nemusel obracet log urovne.
Jakym zapisem se da Pull-Down treba na pinu C5 aktivovat?

neda…a hod tam odpor na zem a bude

Vidím ,že je na čase předat ti nejlepší radu, jakou jsem kdy dostal- nauč se pracovat s datasheetem příslušného procesoru tam v sekci I/O Ports najdeš odpovědi na všechny svoje otázky. A při jakémkoli problému nahlédnout nejdřív právě tam. :slight_smile:

Asi nejednodussi bude dopripajet 10k odpory (pull/downy), cimz nedojde ke zmene logiky. Snad uz to pak pobezi.
Jinak jsem nemcinar, takze mam s anglictinou trochu problemy…