Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- *
- * Brojac koji broji od -999 do 999, postoji mod brzog bojanja koji ubrzano broji
- * i ispisuje na displej u zavisnosti od podesene brzine (promenjiva u vrhu)
- *
- * Bez ikakvih delaya, koriscen interrupt koji se aktivira svakih 1ms
- *
- * Tasteri bi trebalo da su realizovani pomocu PIN CHANGE interrupta ali ne radi bas
- * najbolje u ovoj situaciji, pa sam izostavio. Ko voli nek izvoli.
- *
- * Video prezentacija: https://photos.app.goo.gl/136HhUbY4pe7gweT2
- * Mozda totalno grijesim po pitanju objasnjenja zasto ne radi sa PIN CHANGE interapta...
- *
- * 15.01.2018, 03:59
- *
- * */
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <stdlib.h> // funkcija abs();
- // -123 npr daje problem kada ga koristim sa % i ostalom logikom
- // koja priprema cifre za ispis na dipslej, pa sam ukljucio ovo radi
- // te funkcije abs()
- ///////////////////////////////////////////////////////////////////////////////////////
- // moze i ovako da se implementira ova zajebavancija sa tasterima.
- #define KEY_UP 3 // redni broj PIN-a na portu za tastere
- #define KEY_RIGHT 2
- #define KEY_DN 1
- // PINC je ulazni port koji ocitava tastere
- #define KEY_PINS PINC
- // Macroi koji definisu tastere
- #define KEY_DN_PRESS (~(KEY_PINS) & (1 << KEY_DN)) // ~(PINC) & 1 << 1
- #define KEY_RIGHT_PRESS (~(KEY_PINS) & (1 << KEY_RIGHT)) // ~(PINC) & 1 << 2
- #define KEY_UP_PRESS (~(KEY_PINS) & (1 << KEY_UP)) // ~(PINC) & 1 << 3
- // Nabrajanje ocekivanih stanja tastera.
- enum BUTTONS {NONE = 0, DOWN = 1, RIGHT = 2, UP = 3};
- enum ZNAKBROJACA {POZITIVAN = 1, NEGATIVAN = 2};
- enum ZNAKBROJACA znak;
- ///////////////////////////////////////////////////////////////////////////////////////
- const unsigned char simboli[] = {
- 0x0c, 0xa4, 0x27, 0xc4
- }; //look-up tabela sa simbolima
- unsigned char DISP_BAFER[4] = {
- //0xfe, 0xfe, 0xfe, 0xfe
- 0xff, 0xff, 0xff, 0xff // brisem displej na pocetku.
- }; //bafer displeja
- unsigned long millis = 0;
- unsigned char disp = 3;
- ///////////////////////////////////////////////////////////////////////////////////////
- unsigned char jedinice = 1;
- unsigned char desetice = 1;
- unsigned char stotice = 0;
- unsigned char taster;
- unsigned char enable = 0; // sluzi za implementaciju debouncera.
- unsigned char fastCounting = 0;
- unsigned char intBrzogBrojanja = 70; // 70ms je interval brzog brojanja.
- unsigned char minus = 0xfe;
- // 0 1 2 3 4 5 6 7 8 9
- const unsigned char cifre[] = { 0x05, 0xdd, 0x46, 0x54, 0x9c, 0x34, 0x24, 0x5d, 0x04, 0x14 };
- long brojac = 7; // treba mi integer jer ocekujem broj do 999
- // vraca vrednosti iz enumeracije u zavisnosti od pritisnutog tastera.
- unsigned char ocitajTaster(){
- enum BUTTONS btn;
- if(KEY_DN_PRESS){ // pogledati makroe na vrhu...
- btn = DOWN;
- } else if(KEY_UP_PRESS){
- btn = UP;
- } else if(KEY_RIGHT_PRESS){
- btn = RIGHT;
- } else {
- btn = NONE;
- }
- return btn;
- }
- // Ovo provjeravanje znaka je zbog problema koji se javio pri radu sa negativnim brojevima
- // kada od cifarskih vrednosti pravim broj, gubio se znak brojaca pa nikada nije mogao
- // uci u negativni segment brojanja. Na ovaj nacin provjerim da li se nalazim
- // u negativnom dijelu brojanja i "vjestacki" napravim negativan broj mnozenjem sa -1
- void azurirajBrojac() {
- if(znak == POZITIVAN) {
- brojac = jedinice + (desetice * 10) + (stotice * 100);
- } else if (znak == NEGATIVAN) {
- brojac = (jedinice + (desetice * 10) + (stotice * 100)) * (-1);
- } else {
- brojac = jedinice + (desetice * 10) + (stotice * 100);
- }
- }
- // univerzalna funkcija za upisa karaktera u bafer za slanje na displej.
- void dispBuffer(unsigned char disp0, unsigned char disp1, unsigned char disp2, unsigned char disp3){
- DISP_BAFER[0] = disp0;
- DISP_BAFER[1] = disp1;
- DISP_BAFER[2] = disp2;
- DISP_BAFER[3] = disp3;
- }
- // Ispotavlja se da je ova funkcija prepunjena
- void budziNaDisplej(){
- // npr brojac = 123;
- stotice = abs(brojac) / 100; // (1234 % 1000) / 100 = 234 / 100 = 2
- desetice = (abs(brojac) % 100) / 10; // ((1234 % 1000) % 100) / 10 = (234 % 100) / 10 = 34 / 10 = 3
- jedinice = (abs(brojac) % 100) % 10; // 1234 % 1000 = 234 % 100 = 34 % 10 = 4
- dispBuffer(0xff, 0xff, 0xff, cifre[jedinice]);
- // Podesavam kada da ispisujem znak minus ispred prve znacajne cifre.
- if(brojac < 0 && brojac >= -9) dispBuffer(0xff, 0xff, minus, cifre[jedinice]);
- if(brojac < 0 && brojac >= -99 && brojac < -9) {
- dispBuffer(0xff, minus, cifre[desetice], cifre[jedinice]);
- }
- if(brojac < 0 && brojac < -99) {
- dispBuffer(minus, cifre[stotice], cifre[desetice], cifre[jedinice]);
- }
- // Pozitivni dio brojaca
- if(brojac > 9) {
- dispBuffer(0xff, 0xff , cifre[desetice], cifre[jedinice]);
- }
- if (brojac > 99) {
- dispBuffer(0xff, cifre[stotice], cifre[desetice], cifre[jedinice]);
- }
- }
- void uvecajBrojac(unsigned char koliko){
- if(brojac + koliko <= 999) brojac += koliko;
- if(brojac > 0) znak = POZITIVAN;
- }
- void umanjiBrojac(unsigned char koliko){
- if(brojac - koliko > -999) brojac -= koliko; //
- if(brojac < 0) znak = NEGATIVAN;
- }
- void radSaTasterima(){
- taster = ocitajTaster();
- if(!taster) enable = 1;
- if(enable == 1) {
- // odradjeno kao na vezbama iz cistog Arduina.
- // + koriscenje enumeracije.
- switch(taster){
- case UP:
- uvecajBrojac(1);
- enable = 0; // zabrani ponovni ulazak u ovaj scope
- // i samim tim sprijeci unedogled uvecavanje brojaca
- // dok se drzi taster
- break;
- case DOWN:
- enable = 0; // zabrani ponovni ulazak u ovaj scope...
- umanjiBrojac(1);
- break;
- case RIGHT: // omoguci ubrzano brojanje
- switch(fastCounting){
- case 0: fastCounting = 1; break;
- case 1: fastCounting = 0; break;
- }
- enable = 0;
- break;
- }
- // millis % intBrzogBrojanja == 0 odobrava ulazak u ove else dijelove svakih npr. 100ms, tako da brojac ne
- // trci previse brzo...
- // dakle else if dijelovi se izvrsavaju svakih intBrzogBrojanja ms samo ako je enable iskljucen
- // (drzis taster pritisnut) aktivan je fastCounting ili pritisnut neki od DOWN ili UP tastera.
- } else if (enable == 0 && fastCounting == 1 && KEY_UP_PRESS && millis % intBrzogBrojanja == 0){
- uvecajBrojac(1);
- } else if (enable == 0 && fastCounting == 1 && KEY_DN_PRESS && millis % intBrzogBrojanja == 0){
- umanjiBrojac(1);
- }
- }
- ////////////////////////////////////////////////////////////////////////////////////////
- // Ovo je los pristup, funkcija radSaTasterima poziva gomilu drugih funkcija
- // i u nekoj izvedbi bi moglo biti dosta sporo rjesavanje problema na ovaj nacin.
- // Interrupt Service Routine treba da se izvrsava sto je brze moguce kako bi procesor
- // sto kvalitetnije radio svoj posao. Ovde slusi svrsi vise nego dobro, ali treba imati na umu.
- ISR(TIMER0_COMPA_vect)
- {
- //prekid tajmera 0 usled dostizanja vrednosti registra OCR0A
- if (++disp > 3)
- disp = 0;
- PORTB = ~(1 << (3-disp)); //ukljucenje tranzistora
- PORTD = DISP_BAFER[disp]; //ispis na trenutno aktivan displej
- // Zakljucak, displeji su blinkali kada su ove tri linije ispod bile u WHILE(1)
- // Vjerovatno mu treba neko vrijeme da on to izvrsi kako treba, ovo se izvrsava svakih 1ms
- // Tako da mu je to dovoljno vremena da odradi posao kako treba.
- azurirajBrojac();
- radSaTasterima();
- budziNaDisplej();
- millis++; //sistemsko vreme
- }
- int main()
- {
- //unsigned long t0;
- //unsigned char i;
- //inicijalizacija portova:
- DDRB = 0x0f; //PB3-PB0 -> izlazi
- DDRC = 0x00; //port C -> ulaz
- DDRD = 0xff; //port D -> izlaz
- //PCICR = (1 << PCIE1); //dozvola prekida usled promene stanja
- //PCMSK1 = 0x05; //pina PCINT10, ili pina PCINT8
- //inicijalizacija tajmera 0:
- TCCR0A = 0x02; //tajmer 0: CTC mod
- TCCR0B = 0x03; //tajmer 0: fclk = fosc/64
- OCR0A = 249; //perioda tajmera 0: 250 Tclk (OCR0A + 1 = 250)
- TIMSK0 = 0x02; //dozvola prekida tajmera 0
- //usled dostizanja vrednosti registra OCR0A
- sei(); //I = 1 (dozvola prekida)
- while(1); // sprecava da odlaskom u return 0; izadje iz programa.
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement