současný běh dvou funkcí

Diskuze a poradna o programátorech a programování různých obvodů

Moderátor: Moderátoři

Odpovědět
Zpráva
Autor
Uživatelský avatar
pirat077
Příspěvky: 324
Registrován: 02 kvě 2014, 02:00

současný běh dvou funkcí

#1 Příspěvek od pirat077 »

Ahoj,
jsem začátečník,
chtěl bych udělat počítadlo pulzů (vstup + sedmisegmentovka)

Jen mi není jasný, jak se dělá to, že běží jedna fce + druhá k tomu
(Ideálně pořád svítí LEDka=zapnuto, počítají se pulzy, zobrazuje se číslo)

Pro zjednodušení program:
Jedna ledka pořád svítí + druhý dvě na jiným portu bliknou:

tohle logicky nemůže fungovat:

int main (void){
DDRB=0xff;
DDRC=0xff;
while(1)
{
PORTC=0b11111111;
}

for(char n=0;n<2;n++)
{
PORTB=0b00010000;
_delay_ms(400);
PORTB=0b00000000;
_delay_ms(400);
}}

Uživatelský avatar
mikollar
Příspěvky: 1406
Registrován: 26 pro 2004, 01:00
Bydliště: Košice - okolie

#2 Příspěvek od mikollar »

Vacsinou sa to riesi prerusenim, zapnes prerusenie pre vstup na ktorom chces pocitat impulzy.

Dalsie prerusenie bude dajme to mu od casovaca cca 25Hz(resp viac ak mas viac segmentov), v tomto preruseni budes multiplexovat displej. A ostatne mozes hodit do hlavnej slucky, alebo do dalsieho prerusenia a zbytok casu moze procesor byt v sleep

Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 01:00

#3 Příspěvek od AB1 »

Kód: Vybrat vše

int main (void){
   DDRB=0xff;
   DDRC=0xff;
   PORTC
   while(1)
   {
      PORTC=0b11111111;
   }

   for(char n=0;n<2;n++)
   {
      PORTB=0b00010000;
      _delay_ms(400);
      PORTB=0b00000000;
      _delay_ms(400);
}}
Toto jistě fungovat nebude, protože program bude běžet v nekonečné smyčce while(1) a dál se nikdy nedostane.
(Pozn.: Pokud má ledka na PORTC stále svítit, tak stačí nastavit PORTC jednou, před vstupem do hlavní smyčky while(1). )

Trochu obměním kód.

Kód: Vybrat vše

   while(1)
   {
      PORTC = ~PORTC; // invertuj všechny bity portu C.

      for(char n=0;n<2;n++)
      {
         PORTB = 0b00010000;
         _delay_ms(400);
         PORTB = 0b00000000;
         _delay_ms(400);
      }
   }
Teď to funguje, program bliká současně na obou portech s různou frekvencí.

Ale přitom nedělá "dvě funkce současně".
Napřed invertuje portC.
Pak dvakrát blikne ledkou na PORTB.4.
Pak opět invertuje portC.
Atd.
Jen mi není jasný, jak se dělá to, že běží jedna fce + druhá k tomu
(Ideálně pořád svítí LEDka=zapnuto, počítají se pulzy, zobrazuje se číslo)
Např. jednoduše takto:
Využiješ toho, že timery se dají přepnout do módu čítání impulsů.
V tomto módu timer počítá impulsy nezávisle na hlavním programu.

Kód: Vybrat vše

// atmega8
//-------------------------------------
int main(void)
{
uint16_t pocet_pulsu;

   // nastav timer1 do režimu čítání impulsů na pinu T1
   TCCR1B = 0b111;
   // vynuluj timer1
   TCNT1 = 0;
   DDRC = 0xff;
   PORTC = 0xff; // ledka na portC svítí
   
   while(1)
   {
      pocet_pulsu = TCNT1;   
      zobraz hodnotu pocet_pulsu;
      _delay_ms(200);
   }
}
Pokud použiješ sedmisegmentovky, tak ovšem musíš přidat přerušení pro multiplex, jak píše mikollar.

Uživatelský avatar
frpr666
Příspěvky: 1051
Registrován: 28 pro 2009, 01:00

#4 Příspěvek od frpr666 »

Podívej se na Application note na atmel.com. Tam je vzorový projekt na svítilnu s ledkou. Svícení, blikání, čtení tlačítka, pwm výstup.
Pro začátek doporučuji Arduino. :D

Uživatelský avatar
Celeron
Příspěvky: 16140
Registrován: 02 dub 2011, 02:00
Bydliště: Nový Bydžov

#5 Příspěvek od Celeron »

Copak jedno přerušení. :) To když začneš používat všech 8 přerušení, co mikroprocesor má a priority přerušení nejdou optimálně nastavit a navíc když už nestačej banky alternativních registrů, to je teprv vzrůšo napsat program, kterej by správně makal za všech okolností :wink:
Jirka

Uživatelský avatar
WLAB
Příspěvky: 867
Registrován: 13 zář 2005, 02:00
Bydliště: Praha

#6 Příspěvek od WLAB »

Predevsim, dve "funkce" nepobezi nikdy soucasne - pokud se tedy bavime o jednojadrovem MCU. Jejich beh se musi nejak "prepinat" a bezi pak zdanlive soucasne. K tomu muze slouzit preruseni (vhodne jen pro "paralelizaci" vysokoprioritnich funkci), nebo kooperativni multitasking realizovany treba uvnitr while(1) smycky, nebo preemptivni multitasking realizovany treba nejakym RTOSem.
de omnibus dubitandum est

Uživatelský avatar
pirat077
Příspěvky: 324
Registrován: 02 kvě 2014, 02:00

#7 Příspěvek od pirat077 »

Díky za odpovědi,
už se mi povedlo udělat program téměř podle mých představ ;)

Když jsem řešil to přerušení, napadla mě takové (typicky české) řešení...potřeboval bych daleko větší čas přerušení (třeba 100ms), což s 4MHz krystalem neudělám...

...tak jsem zkoušel, co to udělá, když se do programu deklaruje 8MHz a krystal bude pořád stejnej...

Zvláštní je, že to funguje u fce _delay_ms(), ale u přerušení to zřejmě nefunguje

...tak jsem to přestal řešit a pustil se do PWM :D

Uživatelský avatar
pirat077
Příspěvky: 324
Registrován: 02 kvě 2014, 02:00

#8 Příspěvek od pirat077 »

A teď jsem zjistil, že řeším naprostou ptákovinu...

Pro další nováčky: (počítání přetečení T1)

ISR (TIMER0_OVF_vect){
TCNT0 = 0; // nastavení počáteční hodnoty počítadla

if (T1==30) // kolikrat pretekl TIMER1
{
if (cislice==10) //pokud je cislo vetsi jak 9
{
cislice=0;
ukazC (cislice);
cislice++;
}
else
{
ukazC (cislice);
cislice++;
}
T1=0;
}
T1++;
}

Uživatelský avatar
WLAB
Příspěvky: 867
Registrován: 13 zář 2005, 02:00
Bydliště: Praha

#9 Příspěvek od WLAB »

proc je tam TCNT0=0;? Rekl bych, ze to tam akorat zanasi systematickou odchylku. TCNT bude 0 hned pri preteceni a pokud ISR nastane z nejakeho duvodu pozdeji, TCNT uz muze byt jinde, ale nastavi se zpet na 0...

A

Kód: Vybrat vše

ukazC (cislice);
cislice++; 
by mohlo byt mimo ten if, ne?
de omnibus dubitandum est

Uživatelský avatar
Celeron
Příspěvky: 16140
Registrován: 02 dub 2011, 02:00
Bydliště: Nový Bydžov

#10 Příspěvek od Celeron »

to pirat: Teď jsem si vzpoměl, že na tohle už léta dělá Intersil švába. ICL7216 to asi není, kdybych hledal, nekde ho mám. Umí počítadlo 0-999 na 3 multiplexní segnentovky. Možná i na 4, už si to nepamatuju. Vstupy jsou ošetřený proti zákmitům, umí nahoru, dolů, reset a set. Set se nastavuje třeba z BCD palcovýho přepínače. Myslím, že to hlásí přetečení na další brouka a vynulování. Kdysi se to dávalo s generátorem 1s jako časovač do pece na vytvrzování skel do brejlí. Ale v tý době ještě oční optika byli optici a ne prodavači.
Jirka

Uživatelský avatar
rnbw
Příspěvky: 32312
Registrován: 21 bře 2006, 01:00
Bydliště: Bratislava

#11 Příspěvek od rnbw »


Uživatelský avatar
pirat077
Příspěvky: 324
Registrován: 02 kvě 2014, 02:00

#12 Příspěvek od pirat077 »

Moje programování zdaleka nekončí touto funkcí ;)

Už dlouho jsem se tomuto tématu věnoval, ale pořád jsem se nějak nemohl pustit do pořádnýho programování

Teď mám zdravotní volno a pustil jsem se do toho ve velkým!
Už mám naprogramovanou čtyřcifernou sedmisegmentovku, čítač (a odečítač :D ) pulzů ze dvou 555 (s proměnnou dobou 1 a 0) ;)

Teď bych ještě rád přepojil sedmisegmentovku na posuvnej registr a nastudoval PWM a nějaký typy úspornejch režimů včetně nějakýho podtaktování na snížení spotřeby. Potom jdu na LCD ;)

Je až neuvěřitelný, jak rychle se na to všechno dá přijít když se do toho člověk fakt vrhne ;)

Uživatelský avatar
Karel4
Příspěvky: 11
Registrován: 27 dub 2014, 02:00

#13 Příspěvek od Karel4 »

Jenom bych nabídnul jinou funkci k invertování bitu na portu

Kód: Vybrat vše

... místo ...

PORTB=0b00010000; 
_delay_ms(400); 
PORTB=0b00000000;

... můžeš napsat  ...

PORTB ^=0b00010000; 
_delay_ms(400); 


... a bude to mít stejný efekt :-)

Uživatelský avatar
Rako
Příspěvky: 40
Registrován: 29 bře 2014, 01:00

#14 Příspěvek od Rako »

pirat077 píše:Díky za odpovědi,
Když jsem řešil to přerušení, napadla mě takové (typicky české) řešení...potřeboval bych daleko větší čas přerušení (třeba 100ms), což s 4MHz krystalem neudělám...
Toto je trik ktorým oblbneš simulátor ale nie mikrokontrolér, ten bude mať
takt podľa pripojeného kryštálu.Nechápem ako súvisí frekvencia kryštálu
s prerušením.Pokiaľ chceš vytvoriť časovú základňu pomocou časovača pre dlhšie časy,stačí v prerušení od pretečenia časovača dekrementovať ďalšie počítadlo.Keď bude počítadlo na nule, čas vypršal.

Odpovědět

Zpět na „Programování PIC, ATMEL, EEPROM a dalších obvodů“