/*************************************************************************** * * * P R I M E R 5 C . C * * digitalno Ÿasovno krmilje z mo§nostjo uŸenja z PIC16x84 * * * *==========================================================================* * Verzija Datum Opis Avtor * *--------------------------------------------------------------------------* * 1 1997-12-27 Slavko M. * *==========================================================================* * * * OPIS: Vezje je sposobno krmiliti çtiri digitalne izhode, ki jih lahko * * vkljuŸujeç in izkljuŸujeç s tipkami 1 do 4, kot v primeru 3. * * Vezje si zaponi Ÿasovne sekvence in jih je sposobno ponoviti. * * Zaponi si najveŸ 21 sprememb stanja na izhodih, Med spremembami * * je lahko najveŸ 60 min (lahko tudi veŸ z zmanjçanim çtevilom * * sprememb). ¬asovna natanŸnost je 0.05s. * * Snemanje: * * Za vstop v naŸin snemanja stanj je potrebno ob vkljuŸitvi hkrati * * dr§ati tipki 1 in 5. Med snemanjem gori LED_6. Ko je spomin poln * * zaŸne utripati. Izhod iz tega naŸina je samo izklop napajanja. * * Predvajanje: * * Ob ponovnem vklopu naprava s signalom na LED_7 javi da se odvija * * posneta sekvenca. Po zakljuŸku LED_7 ugasne na izhodih pa * * ostane zadnje stanje. Ponovno startamo predvajanje s tipko 1 * *--------------------------------------------------------------------------* * Uporabljne so funkcije iz primerov 3 in 4. Iz primera 3 uporaba * * tipkovnice za spremembo stanj na izhodih in podatkovnega eeproma * * za vpis pomnenje stanja izhodov in Ÿasovnih intervalov. * * Iz primera 4 pa generiranje natanŸne Ÿasovne enote 50ms. * * * ***************************************************************************/ #include /* vkljuŸi datoteko s deklaracijami za PIC */ #include /* vkljuŸi datoteko z funkcijami za delo s podatkovnim eepromom*/ /* KONFIGURACUJSKI BAJT NA NASLOVU 0X2007 */ __CONFIG(_CP_ON & _PWRTE_ON & _WDT_ON & _XT_OSC); /* trenutno: _CP_ON -vkljuŸena zaçŸita vpisanega programa pred kopiranjem _PWRTE_ON - vkljucen "power up timer" _WDT_ON - vkljuŸen "watchdog timer" _XT_OSC - izbran kvarc osilator */ #define PORTBIT(adr, bit) ((unsigned)(&adr)*8+(bit)) static bit LED_7 @ PORTBIT(PORTB,7); static bit LED_6 @ PORTBIT(PORTB,6); /*********************/ /* I N T E R R U P T */ /*********************/ static unsigned int irq_stevec,zakasnitev; /* 16 bitni çtevec prekinitev, ostane tudi po izhodu iz funkc*/ static bit bit_delovanje,bit_ucenje; /* enobitni spremnljivki */ void interrupt timer(void) { /* interrupt je poklican vedno ko çtevec TMR0 odçteje do 0 */ T0IF = 0; if (--irq_stevec == 0) { irq_stevec = 214; /* med irq-ji je 256micro sek, vzamemo 214 prekinitev in dobimo 54.7ms. */ if (bit_delovanje) { /* odçtevaj do 0*/ if (zakasnitev != 0) zakasnitev--; } else { if (bit_ucenje && zakasnitev != 0xFFFF) /* priçtevaj do 65000 */ zakasnitev++; } } /* konec if stavka*/ } /* vrnitev iz prekinitvenega programa */ /*************/ /* K B H I T */ /*************/ static byte staro_stanje_tipk; /* globalna spremenljivka dostopna vsem podprogramom 1byte=8bitov */ byte kbhit() { /* funkcija za testiranje tipkovnice */ byte stanje_porta,rezultat; /* lokalni sremnljivki dostopni samo znotraj te funkcije 1byte=8bitov */ int i; stanje_porta = PORTA; /* tipke so na spodnjih 4. bitih porta A*/ for (i=1000;i--;) continue; /*da onemogoŸi veŸkratni preklop poŸaka pribli§no 50ms */ stanje_porta &= PORTA; /* Ÿe je tipka çe vedno pritisnjena jo sprejmi*/ rezultat = ~staro_stanje_tipk & stanje_porta; /* Rez=/Staro AND Tipka*/ /* "1" Ÿe je tipka pritisnjena v prejçnjem ciklu pa çe ni bila */ staro_stanje_tipk = stanje_porta; /* zabele§i trenutno stanje za naslednji cikel */ return(rezultat & 0x0F); /* programu, ki je klical to funkcijo vrne byte s postavljenimi tistimi biti, katerih tipke so bile na novo pritisnjeme */ } /* konec funkcije kbhit */ /***********/ /* M A I N */ /***********/ main(void) { /* zaŸetek telesa glavnega programa */ byte tipke,naslov_ee; PORTA = 0; PORTB = 0; TRISB = 0x00; /* PORTB izhodi */ OPTION = 0x8F; /* predelilnik ni vkljuŸen na TMR0 */ irq_stevec = 1; /* zaŸetna vrednost */ bit_delovanje = 0; bit_ucenje = 0; INTCON = 0xA0; /* omogoŸi prekinitve iz TMR0 */ staro_stanje_tipk = PORTA; /* Ÿe je katera tipka sedaj pritisnjena jo bo treba najprej spustiti in ponovno pritisniti da bo prijela v kbhit();*/ if ((PORTA & 0x0F) == 0x09) goto ucenje; /* pritisnjeni tipki 1 in 4*/ while (1) { /* predvajanje - neskonŸna zanka */ PORTB = 0; LED_7 = 1; naslov_ee = 0; do { /* ponovljaj za vsako novo stanje na izhodih */ bit_delovanje = 0; /*prebere zakasnitev iz EE*/ ++naslov_ee; zakasnitev = read_eeprom(naslov_ee) << 8; ++naslov_ee; zakasnitev |= (unsigned int)read_eeprom(naslov_ee); ++naslov_ee; bit_delovanje = 1; while (zakasnitev != 0) /*Ÿakaj na iztek nastavljnega Ÿasa */ CLRWDT(); /*in briçi watchdog çtevec, da prepreŸiç reset*/ PORTB = read_eeprom(naslov_ee - 3); /* podatek o stanju porta je 3 bajte nazaj v EE*/ LED_7 = 1; /* signal na LED_7 je pomotoma brisan zato ga takoj vklopim nazaj */ } while (read_eeprom(naslov_ee) != 0xFF) ; /* dokler ne pride do znaka za konec 0xFF*/ bit_delovanje = 0; /* to je zadnje stanje v spominu*/ LED_7 = 0; staro_stanje_tipk = PORTA; /* Ÿe je katera tipka sedaj pritisnjena jo bo treba najprej spustiti in ponovno pritisniti da bo prijela */ while ((kbhit() & 0x01) == 0) /* Ÿakaj na tipko 1*/ CLRWDT(); /*in briçi watchdog çtevec, da prepreŸiç reset*/ } /* starta ponovno */ /*-------------------------------------------------------------------*/ ucenje: naslov_ee = 0; /* uŸenje */ zakasnitev = 0; bit_ucenje = 1; /* vklopi priçtevanje prekinitev v zakasnitev*/ LED_6 = 1; /* signal - uŸenje */ for(;;) { /* v naskonŸni zanki Ÿaka na pritisk tipke */ CLRWDT(); /*zbriçe watchdog çtevec, da prepreŸi reset*/ if (zakasnitev == 0xFFFF) goto zapisi_v_ee; if ((tipke = kbhit()) == 0 ) continue; /*Ÿe ni nove tipke skoŸi nazaj na for*/ PORTB ^= tipke; /* (PORTB = PORTB XOR tipke) */ /* bitom katerih tipke so na novo pritisnjene, invertira vrednost */ zapisi_v_ee: bit_ucenje = 0; /*med vpisovanjem v EE onemogoŸi spreminjanje spremenljivke zakasnitev*/ write_eeprom(naslov_ee,PORTB & 0x0F); /*in shrani v trajni spomin*/ ++naslov_ee; /*prestavi se na naslednjo lokacijo v EE*/ write_eeprom(naslov_ee,(byte)(zakasnitev >> 8)); /* zgornji byte */ ++naslov_ee; write_eeprom(naslov_ee,(byte)(zakasnitev & 0x00FF)); /* spodnji b.*/ ++naslov_ee; write_eeprom(naslov_ee,0xFF); /* znak konec spomina v naslednjo celico za primer, Ÿe bo napajanje izkljuŸeno*/ bit_ucenje = 1; /* vkljuŸi priçtevanje, samo da se spreminja */ if (naslov_ee == 63) /* Ÿe je EE poln*/ while (1) { CLRWDT(); /*zbriçe watchdog çtevec, da prepreŸi reset*/ if ((byte)zakasnitev & 0x02) /* LED_6 naj utripa v ritmu 2-gega bita v spremenljivki zakasnitev*/ LED_6 = 1; else LED_6 = 0; } bit_ucenje = 0; /* med brisanjem zakasnitev, naj ne priçteva*/ zakasnitev = 0; /* za naslednji zapis startaj çtetje iz 0 */ bit_ucenje = 1; /* vklopi priçtevanje */ } /* konec FOR zanke */ } /* konec funkcije main */