kfh13 Napisano Luty 14, 2010 Udostępnij Napisano Luty 14, 2010 Mam taki oto kod powstały na podstawie strony wkrętaka #include <avr\io.h> #include <inttypes.h> #include <avr\signal.h> #include <avr\interrupt.h> #include <avr\pgmspace.h> #include <w7s.h> #define LED_DDR DDRB //stan wyjście albo wejście #define LED_PORT PORTB //0-włączenie leda #define WYSW_1 0 #define WYSW_2 1 #define WYSW_3 2 #define WYSW_4 3 #define WYSW_5 4 #define WYSW_6 5 #define WYSW_DDR DDRC //stan wyjście albo wejście #define WYSW_PORT PORTC //0-włączenie wysw uint8_t akt_wysw[6]= { ~(1<<WYSW_6), ~(1<<WYSW_5), ~(1<<WYSW_4), ~(1<<WYSW_3), ~(1<<WYSW_2), ~(1<<WYSW_1) }; volatile uint8_t wysw; unsigned int godziny, minuty, sekundy,dziesiatki,jednosci; int main(void) { TCCR1B |= (1 << WGM12); // Ustawia timer1 w tryb CTC OCR1A = 3333; // Ustawia wartość pożądaną na 100Hz dla preskalera 1 TCCR1B |= (1 << CS10); // Ustawia timer z preskalerem Fcpu/1 TIMSK |= (1 << OCIE1A); // Zezwolenie na przerwania dla CTC sei(); // Zezwolenie globalne na przerwania/ LED_DDR = 0xff; WYSW_DDR = 0xff; sekundy=33; minuty=22; godziny=11; dziesiatki=sekundy/10; jednosci=sekundy%10; for(;;) { } return 0; } ISR(TIMER1_COMPA_vect) { switch (wysw) { case 0: WYSW_PORT=akt_wysw[0]; LED_PORT=znaki_wysw[jednosci]; wysw++; break; case 1: WYSW_PORT=akt_wysw[1]; LED_PORT=znaki_wysw[dziesiatki]; wysw++; break; case 2: WYSW_PORT=akt_wysw[2]; LED_PORT=znaki_wysw[1]; wysw++; break; case 3: WYSW_PORT=akt_wysw[3]; LED_PORT=znaki_wysw[minuty/10]; wysw++; break; case 4: WYSW_PORT=akt_wysw[4]; LED_PORT=znaki_wysw[godziny-(godziny/10)*10]; wysw++; break; case 5: WYSW_PORT=akt_wysw[5]; LED_PORT=znaki_wysw[godziny/10]; wysw=0; break; } } Nie wiem dlaczego program nie chce wyświetlić poprawnie liczby. W "caseach" mam kilka metod moich prób i działa jedynie ta w której sztywno wpisałem liczbę (case 2). Przy reszcie świecą wszystkie diody, czyli jakby nie znalazł odpowiedniej liczby w tabeli. Ma ktoś jakiś pomysł co robię źle ? Link do komentarza Share on other sites More sharing options...
Bobby Luty 14, 2010 Udostępnij Luty 14, 2010 Przy przypisywaniu wartości do zmiennych nie masz spacji: sekundy=33; minuty=22; godziny=11; + przy deklarowaniu tych zmiennych to samo: unsigned int godziny, minuty, sekundy,dziesiatki,jednosci; Nie jestem pewien czy w tym tkwi błąd (czystego C uczę się od kilku godzin) ale sprawdź 🙂 edit: Jeszcze tutaj masz głupi błąd: jednosci=sekundy%10; Link do komentarza Share on other sites More sharing options...
kfh13 Luty 14, 2010 Autor tematu Udostępnij Luty 14, 2010 @BoBBy Nie. Link do komentarza Share on other sites More sharing options...
Elvis Luty 14, 2010 Udostępnij Luty 14, 2010 A co program wyświetla? [ Dodano: 14 Lut 10 10:34 ] Próbowałeś w case 2: wyświetlać inne cyfry? [ Dodano: 14 Lut 10 10:34 ] Możesz jeszcze dodać volatile do deklaracji zmiennych, czyli volatile unsigned int godziny, minuty, sekundy,dziesiatki,jednosci; Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
Mihau Luty 14, 2010 Udostępnij Luty 14, 2010 A gdzie masz deklarację tablicy "znaki_wysw"? 1 Link do komentarza Share on other sites More sharing options...
kfh13 Luty 14, 2010 Autor tematu Udostępnij Luty 14, 2010 Tak wygląda tablica znaki_wysw, teraz już znaki. prog_uint8_t znaki[11] PROGMEM = { ~(1<<LED_A | 1<<LED_B | 1<<LED_C | 1<<LED_D | 1<<LED_E | 1<<LED_F), //0 ~(1<<LED_B | 1<<LED_C), //1 ~(1<<LED_A | 1<<LED_B | 1<<LED_G | 1<<LED_E | 1<<LED_D), //2 ~(1<<LED_A | 1<<LED_B | 1<<LED_G | 1<<LED_C | 1<<LED_D), //3 ~(1<<LED_F | 1<<LED_G | 1<<LED_B | 1<<LED_C), //4 ~(1<<LED_A | 1<<LED_F | 1<<LED_G | 1<<LED_C | 1<<LED_D), //5 ~(1<<LED_A | 1<<LED_F | 1<<LED_G | 1<<LED_C | 1<<LED_D | 1<<LED_E), //6 ~(1<<LED_A | 1<<LED_B | 1<<LED_C), //7 ~(1<<LED_A | 1<<LED_B | 1<<LED_C | 1<<LED_D | 1<<LED_E | 1<<LED_F | 1<<LED_G),//8 ~(1<<LED_A | 1<<LED_B | 1<<LED_C | 1<<LED_D | 1<<LED_F | 1<<LED_G), //9 ~(1<<LED_DP), }; uint8_t wysw_znak(uint8_t cyfra) { return pgm_read_byte(&znaki[cyfra]); } Zapomniałem, że ta tablica jest typu progmen, więc jej wartości odczytuje się inaczej. Wynikł następny problem... przerobiłem "kajsy" na: switch (wysw) { case 0: WYSW_PORT=akt_wysw[0]; LED_PORT=wysw_znak(sekundy%10); wysw++; break; case 1: WYSW_PORT=akt_wysw[1]; LED_PORT=wysw_znak(sekundy/10); wysw++; break; case 2: WYSW_PORT=akt_wysw[2]; LED_PORT=wysw_znak(minuty%10); wysw++; break; case 3: WYSW_PORT=akt_wysw[3]; LED_PORT=wysw_znak(minuty/10); wysw++; break; case 4: WYSW_PORT=akt_wysw[4]; LED_PORT=wysw_znak(godziny%10); wysw++; break; case 5: WYSW_PORT=akt_wysw[5]; LED_PORT=wysw_znak(godziny/10); wysw=0; break; } Jakoś dziwnie liczby się "przebijają". Tzn. jęśli ustawie wyświetlacz na 654321. To widać na 1 jak przebija 6, na 2 przebija 1, na 3 przebija 2 itd. Dołączam foto: Link do komentarza Share on other sites More sharing options...
regrom Luty 14, 2010 Udostępnij Luty 14, 2010 To co mi przychodzi do głowy: 1) zmień częstotliwość multipleksowania 2) nie wygaszasz poprzedniego wyświetlacza zanim podasz następną cyfrę 3) za mała wartość rezystora na bazie tranzystorów Ja robiłem tak i nie miałem tej poświaty, co prawda tylko 2 wyświetlacze, bez użycia tablic, ale poglądowo: switch (w) { case 0: PORTD =0xFF; // wyzerowanie portu D - zgaszenie wszystkich lini sbi(PORTB,0); //zgaszenie segmentu 2 led7(x); cbi(PORTD,7); // zapalenie segment 1 w++; break; case 1: PORTD =0xFF; sbi(PORTD,7); ///zgaszenie segmentu 1 led7(y); cbi(PORTB,0); // zapalenie segment 2 w=0; break; } } Link do komentarza Share on other sites More sharing options...
kfh13 Luty 15, 2010 Autor tematu Udostępnij Luty 15, 2010 @regrom 1) Zwiększenie częstotliwości pogarsza problem, a zmniejszenie powoduje miganie a poświata nadal występuje. 2) To samo robi moja tablica. Obecnie nie używa się sbi i cbi tylko PORTB|=_BV(4) // bit ustawiony (1) PORTB&=~_BV(4) // bit wyzerowany To i tak nic nie daje! 3) To raczej ominięcie problemu niż jego usunięcie. No chyba, że to czysto "sprzętowa dolegliwość" a nie wina software. Znalazłem rozwiązanie ! Którego do końca nie rozumiem, ale co tam. Zastosowałem podwójne wygaszanie - czyli wygaszam wyświetlacze i diody. Poświata znikneła. Oto przykład: ISR(TIMER1_COMPA_vect) { WYSW_PORT= 0xff; LED_PORT= 0xff; switch (wysw) { case 0: WYSW_PORT&=akt_wysw[0]; LED_PORT=wysw_znak(sekundy%10); wysw++; break; case 1: WYSW_PORT&=akt_wysw[1]; LED_PORT=wysw_znak(sekundy/10); wysw++; break; case 2: WYSW_PORT&=akt_wysw[2]; LED_PORT=wysw_znak(minuty%10); wysw++; break; case 3: WYSW_PORT&=akt_wysw[3]; LED_PORT=wysw_znak(minuty/10); wysw++; break; case 4: WYSW_PORT&=akt_wysw[4]; LED_PORT=wysw_znak(godziny%10); wysw++; break; case 5: WYSW_PORT&=akt_wysw[5]; LED_PORT=wysw_znak(godziny/10); wysw=0; break; } } Link do komentarza Share on other sites More sharing options...
Elvis Luty 15, 2010 Udostępnij Luty 15, 2010 regrom, miał rację. Pomogło wygaszanie przed przełączeniem do kolejnej cyfry. Nie jest prawdą, że: 2) To samo robi moja tablica. W programie najpierw przełączasz na kolejny segment: WYSW_PORT&=akt_wysw[5]; co powoduje, że na bardzo krótko, ale zawsze zapalasz na nim cyfrę z poprzedniego. Dopiero później wykonujesz: LED_PORT=wysw_znak(godziny/10); co ustawia poprawną wartość. Takie przełączanie jest krótkie, ale jak sam zaobserwowałeś widoczne. Pomysł 3) wcale nie jest zły - efekt byłby o wiele mniej widoczny, gdyby tranzystor przełączał się szybciej. Link do komentarza Share on other sites More sharing options...
kfh13 Luty 15, 2010 Autor tematu Udostępnij Luty 15, 2010 Tylko, że samo wygaszenie wyświetlacza nic nie dało. Dopiero połączenie z "zerowaniem" znaku daje całkowite zlikwidowanie poświaty. Link do komentarza Share on other sites More sharing options...
Elvis Luty 15, 2010 Udostępnij Luty 15, 2010 Spróbuj zamienić kolejność instrukcji: WYSW_PORT&=akt_wysw[0]; LED_PORT=wysw_znak(sekundy%10); Ewentualnie dodaj małe opóźnienie 1 Link do komentarza Share on other sites More sharing options...
kfh13 Luty 15, 2010 Autor tematu Udostępnij Luty 15, 2010 @Elvis No rzeczywiście teraz działa. Całość kodu została zmieniona na: WYSW_PORT= 0xff; LED_PORT=wysw_znak(stan_wysw[numer_wysw]); WYSW_PORT=akt_wysw[numer_wysw]; numer_wysw++; if(numer_wysw==6) { numer_wysw=0; } Pozwoliło to na zaoszczędzenie około 90 bajtów i zrobiło się bardziej uniwersalne. Link do komentarza Share on other sites More sharing options...
regrom Luty 15, 2010 Udostępnij Luty 15, 2010 Dokładnie o to mi chodziło, sam rozwiązywałem ten problem, jak widać w kodzie który podałem jest to samo: PORTD =0xFF; // wyzerowanie portu D - zgaszenie wszystkich lini sbi(PORTB,0); //zgaszenie segmentu 2 led7(x); cbi(PORTD,7); // zapalenie segment 1 najpierw wygaszenie wszystkich segmentów, odłączenie segmentu, funkcja led(7) ustawienie odpowiedniej kombinacji, i dopiero wtedy następuje zapalenie tego segmentu co powinno. Pozdrawiam i życzę dalszych sukcesów 😉 1 Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »